This commit is contained in:
xmflsct 2022-12-23 18:19:14 +01:00
parent 57e1206faf
commit f3c40e9486
15 changed files with 88 additions and 103 deletions

View File

@ -1,2 +1,3 @@
Enjoy toooting! This version includes following improvements and fixes:
- Allowing adding more context of reports
- Option to disable autoplay gif

View File

@ -1,2 +1,3 @@
toooting愉快此版本包括以下改进和修复
- 可添加举报细节
- 新增暂停自动播放gif动画选项

View File

@ -8,6 +8,8 @@ import AttachmentAltText from './AltText'
import { Platform } from 'expo-modules-core'
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
import { aspectRatio } from './dimensions'
import { useSelector } from 'react-redux'
import { getSettingsAutoplayGifv } from '@utils/slices/settingsSlice'
export interface Props {
total: number
@ -25,6 +27,7 @@ const AttachmentVideo: React.FC<Props> = ({
gifv = false
}) => {
const { reduceMotionEnabled } = useAccessibility()
const autoplayGifv = useSelector(getSettingsAutoplayGifv)
const videoPlayer = useRef<Video>(null)
const [videoLoading, setVideoLoading] = useState(false)
@ -60,7 +63,7 @@ const AttachmentVideo: React.FC<Props> = ({
resizeMode={videoResizeMode}
{...(gifv
? {
shouldPlay: reduceMotionEnabled ? false : true,
shouldPlay: reduceMotionEnabled || !autoplayGifv ? false : true,
isMuted: true,
isLooping: true,
source: { uri: video.url }
@ -73,7 +76,7 @@ const AttachmentVideo: React.FC<Props> = ({
onFullscreenUpdate={event => {
if (event.fullscreenUpdate === VideoFullscreenUpdate.PLAYER_DID_DISMISS) {
Platform.OS === 'android' && setVideoResizeMode(ResizeMode.COVER)
if (gifv && !reduceMotionEnabled) {
if (gifv && !reduceMotionEnabled && autoplayGifv) {
videoPlayer.current?.playAsync()
} else {
videoPlayer.current?.pauseAsync()
@ -106,7 +109,7 @@ const AttachmentVideo: React.FC<Props> = ({
video.blurhash ? (
<Blurhash blurhash={video.blurhash} style={{ width: '100%', height: '100%' }} />
) : null
) : !gifv || (gifv && reduceMotionEnabled) ? (
) : !gifv || (gifv && (reduceMotionEnabled || !autoplayGifv)) ? (
<Button
round
overlay
@ -119,6 +122,21 @@ const AttachmentVideo: React.FC<Props> = ({
) : null}
<AttachmentAltText sensitiveShown={sensitiveShown} text={video.description} />
</Pressable>
{gifv && !autoplayGifv ? (
<Button
style={{
position: 'absolute',
left: StyleConstants.Spacing.S,
bottom: StyleConstants.Spacing.S
}}
overlay
size='S'
type='text'
content='GIF'
fontBold
onPress={() => {}}
/>
) : null}
</View>
)
}

View File

@ -42,8 +42,7 @@
"placeholder": "What's on your mind",
"keyboardImage": {
"exceedMaximum": {
"title": "Maximum attachments amount reached",
"OK": "$t(common:buttons.OK)"
"title": "Maximum attachments amount reached"
}
}
}

View File

@ -28,19 +28,7 @@
"filters": {
"accessibilityLabel": "Filter",
"accessibilityHint": "Filter shown notifications' types",
"title": "Show notifications",
"options": {
"follow": "$t(screenTabs:me.push.follow.heading)",
"follow_request": "Follow request",
"favourite": "$t(screenTabs:me.push.favourite.heading)",
"reblog": "$t(screenTabs:me.push.reblog.heading)",
"mention": "$t(screenTabs:me.push.mention.heading)",
"poll": "$t(screenTabs:me.push.poll.heading)",
"status": "Toot from subscribed users",
"update": "Reblog has been edited",
"admin.sign_up": "$t(screenTabs:me.push.admin.sign_up.heading)",
"admin.report": "$t(screenTabs:me.push.admin.report.heading)"
}
"title": "Show notifications"
}
},
"me": {
@ -266,19 +254,6 @@
}
},
"settings": {
"fontsize": {
"heading": "$t(me.stacks.fontSize.name)",
"content": {
"S": "$t(me.fontSize.sizes.S)",
"M": "$t(me.fontSize.sizes.M)",
"L": "$t(me.fontSize.sizes.L)",
"XL": "$t(me.fontSize.sizes.XL)",
"XXL": "$t(me.fontSize.sizes.XXL)"
}
},
"language": {
"heading": "$t(me.stacks.language.name)"
},
"theme": {
"heading": "Appearance",
"options": {
@ -301,9 +276,8 @@
"external": "Use system browser"
}
},
"staticEmoji": {
"heading": "Use static emoji",
"description": "If you encounter frequent app crash when viewing emoji list, you can try to use static emoji instead."
"autoplayGifv": {
"heading": "Autoplay GIF in timeline"
},
"feedback": {
"heading": "Feature Requests"
@ -332,9 +306,7 @@
"moved": "User moved",
"created_at": "Joined: {{date}}",
"summary": {
"statuses_count": "{{count}} toots",
"following_count": "$t(shared.users.accounts.following)",
"followers_count": "$t(shared.users.accounts.followers)"
"statuses_count": "{{count}} toots"
},
"toots": {
"default": "Toots",

View File

@ -15,7 +15,7 @@ import { uploadAttachment } from '../Footer/addAttachment'
const ComposeTextInput: React.FC = () => {
const { composeState, composeDispatch } = useContext(ComposeContext)
const { t } = useTranslation('screenCompose')
const { t } = useTranslation(['common', 'screenCompose'])
const { colors, mode } = useTheme()
const maxAttachments = useSelector(getInstanceConfigurationStatusMaxAttachments, () => true)
@ -39,7 +39,7 @@ const ComposeTextInput: React.FC = () => {
autoFocus
enablesReturnKeyAutomatically
multiline
placeholder={t('content.root.header.textInput.placeholder')}
placeholder={t('screenCompose:content.root.header.textInput.placeholder')}
placeholderTextColor={colors.secondary}
onChangeText={content =>
formatText({
@ -74,11 +74,11 @@ const ComposeTextInput: React.FC = () => {
onPaste={(error: string | null | undefined, files: PastedFile[]) => {
if (composeState.attachments.uploads.length + files.length > maxAttachments) {
Alert.alert(
t('content.root.header.textInput.keyboardImage.exceedMaximum.title'),
t('screenCompose:content.root.header.textInput.keyboardImage.exceedMaximum.title'),
undefined,
[
{
text: t('content.root.header.textInput.keyboardImage.exceedMaximum.OK'),
text: t('common:buttons.OK'),
style: 'default'
}
]

View File

@ -13,8 +13,8 @@ import {
getSettingsFontsize,
getSettingsDarkTheme,
changeDarkTheme,
getSettingsStaticEmoji,
changeStaticEmoji
getSettingsAutoplayGifv,
changeAutoplayGifv
} from '@utils/slices/settingsSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import * as Localization from 'expo-localization'
@ -35,20 +35,18 @@ const SettingsApp: React.FC = () => {
const settingsTheme = useSelector(getSettingsTheme)
const settingsDarkTheme = useSelector(getSettingsDarkTheme)
const settingsBrowser = useSelector(getSettingsBrowser)
const settingsStaticEmoji = useSelector(getSettingsStaticEmoji)
const settingsAutoplayGifv = useSelector(getSettingsAutoplayGifv)
return (
<MenuContainer>
<MenuRow
title={t('screenTabs:me.settings.fontsize.heading')}
content={t(
`screenTabs:me.settings.fontsize.content.${mapFontsizeToName(settingsFontsize)}`
)}
title={t('screenTabs:me.stacks.fontSize.name')}
content={t(`screenTabs:me.fontSize.sizes.${mapFontsizeToName(settingsFontsize)}`)}
iconBack='ChevronRight'
onPress={() => navigation.navigate('Tab-Me-Settings-Fontsize')}
/>
<MenuRow
title={t('screenTabs:me.settings.language.heading')}
title={t('screenTabs:me.stacks.language.name')}
content={
// @ts-ignore
LOCALES[
@ -161,10 +159,9 @@ const SettingsApp: React.FC = () => {
}
/>
<MenuRow
title={t('screenTabs:me.settings.staticEmoji.heading')}
description={t('screenTabs:me.settings.staticEmoji.description')}
switchValue={settingsStaticEmoji}
switchOnValueChange={() => dispatch(changeStaticEmoji(!settingsStaticEmoji))}
title={t('screenTabs:me.settings.autoplayGifv.heading')}
switchValue={settingsAutoplayGifv}
switchOnValueChange={() => dispatch(changeAutoplayGifv(!settingsAutoplayGifv))}
/>
</MenuContainer>
)

View File

@ -4,8 +4,9 @@ import ComponentSeparator from '@components/Separator'
import CustomText from '@components/Text'
import TimelineDefault from '@components/Timeline/Default'
import { useAppDispatch } from '@root/store'
import { SettingsLatest } from '@utils/migrations/settings/migration'
import { TabMeStackScreenProps } from '@utils/navigation/navigators'
import { changeFontsize, getSettingsFontsize, SettingsState } from '@utils/slices/settingsSlice'
import { changeFontsize, getSettingsFontsize } from '@utils/slices/settingsSlice'
import { StyleConstants } from '@utils/styles/constants'
import { adaptiveScale } from '@utils/styles/scaling'
import { useTheme } from '@utils/styles/ThemeManager'
@ -15,7 +16,7 @@ import { StyleSheet, View } from 'react-native'
import { ScrollView } from 'react-native-gesture-handler'
import { useSelector } from 'react-redux'
export const mapFontsizeToName = (size: SettingsState['fontsize']) => {
export const mapFontsizeToName = (size: SettingsLatest['fontsize']) => {
switch (size) {
case -1:
return 'S'

View File

@ -81,7 +81,7 @@ const TabNotificationsFilters: React.FC<
{PUSH_DEFAULT(pushFeatures).map((type, index) => (
<MenuRow
key={index}
title={t(`screenTabs:notifications.filters.options.${type}`)}
title={t(`screenTabs:me.push.${type}.heading`)}
switchValue={filters[type]}
switchOnValueChange={() => setFilters({ ...filters, [type]: !filters[type] })}
/>
@ -89,7 +89,7 @@ const TabNotificationsFilters: React.FC<
{PUSH_ADMIN(pushFeatures, profileQuery.data?.role?.permissions).map(({ type }) => (
<MenuRow
key={type}
title={t(`screenTabs:notifications.filters.options.${type}`)}
title={t(`screenTabs:me.push.${type}.heading`)}
switchValue={filters[type]}
switchOnValueChange={() => setFilters({ ...filters, [type]: !filters[type] })}
/>

View File

@ -47,7 +47,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
{account ? (
<CustomText
style={[styles.stat, { color: colors.primaryDefault, textAlign: 'right' }]}
children={t('shared.account.summary.following_count', {
children={t('shared.users.accounts.following', {
count: account.following_count
})}
onPress={() =>
@ -71,7 +71,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
{account ? (
<CustomText
style={[styles.stat, { color: colors.primaryDefault, textAlign: 'center' }]}
children={t('shared.account.summary.followers_count', {
children={t('shared.users.accounts.followers', {
count: account.followers_count
})}
onPress={() =>

View File

@ -3,11 +3,11 @@ import AsyncStorage from '@react-native-async-storage/async-storage'
import { AnyAction, configureStore, Reducer } from '@reduxjs/toolkit'
import contextsMigration, { ContextsLatest } from '@utils/migrations/contexts/migration'
import instancesMigration from '@utils/migrations/instances/migration'
import settingsMigration from '@utils/migrations/settings/migration'
import settingsMigration, { SettingsLatest } from '@utils/migrations/settings/migration'
import appSlice, { AppState } from '@utils/slices/appSlice'
import contextsSlice from '@utils/slices/contextsSlice'
import instancesSlice, { InstancesState } from '@utils/slices/instancesSlice'
import settingsSlice, { SettingsState } from '@utils/slices/settingsSlice'
import settingsSlice from '@utils/slices/settingsSlice'
import { Platform } from 'react-native'
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import {
@ -72,7 +72,7 @@ const store = configureStore({
AnyAction
>,
settings: persistReducer(settingsPersistConfig, settingsSlice) as Reducer<
SettingsState,
SettingsLatest,
AnyAction
>
},

View File

@ -2,6 +2,7 @@ import { SettingsV0 } from './v0'
import { SettingsV1 } from './v1'
import { SettingsV2 } from './v2'
import { SettingsV3 } from './v3'
import { SettingsV4 } from './v4'
const settingsMigration = {
1: (state: SettingsV0): SettingsV1 => {
@ -20,7 +21,13 @@ const settingsMigration = {
3: (state: SettingsV2): SettingsV3 => {
const { analytics, ...rest } = state
return rest
},
4: (state: SettingsV3): SettingsV4 => {
const { staticEmoji, ...rest } = state
return { ...rest, autoplayGifv: true }
}
}
export { SettingsV4 as SettingsLatest }
export default settingsMigration

View File

@ -0,0 +1,8 @@
export type SettingsV4 = {
fontsize: -1 | 0 | 1 | 2 | 3
language: string
theme: 'light' | 'dark' | 'auto'
darkTheme: 'lighter' | 'darker'
browser: 'internal' | 'external'
autoplayGifv: boolean
}

View File

@ -1,12 +1,10 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { LOCALES } from '@root/i18n/locales'
import { RootState } from '@root/store'
import { SettingsV3 } from '@utils/migrations/settings/v3'
import { SettingsLatest } from '@utils/migrations/settings/migration'
import * as Localization from 'expo-localization'
import { pickBy } from 'lodash'
export type SettingsState = SettingsV3
export const settingsInitialState = {
fontsize: 0,
notification: {
@ -18,33 +16,33 @@ export const settingsInitialState = {
theme: 'auto',
darkTheme: 'lighter',
browser: 'internal',
staticEmoji: false
autoplayGifv: true
}
const settingsSlice = createSlice({
name: 'settings',
initialState: settingsInitialState as SettingsState,
initialState: settingsInitialState as SettingsLatest,
reducers: {
changeFontsize: (state, action: PayloadAction<SettingsState['fontsize']>) => {
changeFontsize: (state, action: PayloadAction<SettingsLatest['fontsize']>) => {
state.fontsize = action.payload
},
changeLanguage: (state, action: PayloadAction<NonNullable<SettingsState['language']>>) => {
changeLanguage: (state, action: PayloadAction<NonNullable<SettingsLatest['language']>>) => {
state.language = action.payload
},
changeTheme: (state, action: PayloadAction<NonNullable<SettingsState['theme']>>) => {
changeTheme: (state, action: PayloadAction<NonNullable<SettingsLatest['theme']>>) => {
state.theme = action.payload
},
changeDarkTheme: (state, action: PayloadAction<NonNullable<SettingsState['darkTheme']>>) => {
changeDarkTheme: (state, action: PayloadAction<NonNullable<SettingsLatest['darkTheme']>>) => {
state.darkTheme = action.payload
},
changeBrowser: (state, action: PayloadAction<NonNullable<SettingsState['browser']>>) => {
changeBrowser: (state, action: PayloadAction<NonNullable<SettingsLatest['browser']>>) => {
state.browser = action.payload
},
changeStaticEmoji: (
changeAutoplayGifv: (
state,
action: PayloadAction<NonNullable<SettingsState['staticEmoji']>>
action: PayloadAction<NonNullable<SettingsLatest['autoplayGifv']>>
) => {
state.staticEmoji = action.payload
state.autoplayGifv = action.payload
}
}
})
@ -54,7 +52,7 @@ export const getSettingsLanguage = (state: RootState) => state.settings.language
export const getSettingsTheme = (state: RootState) => state.settings.theme
export const getSettingsDarkTheme = (state: RootState) => state.settings.darkTheme
export const getSettingsBrowser = (state: RootState) => state.settings.browser
export const getSettingsStaticEmoji = (state: RootState) => state.settings.staticEmoji
export const getSettingsAutoplayGifv = (state: RootState) => state.settings.autoplayGifv
export const {
changeFontsize,
@ -62,6 +60,6 @@ export const {
changeTheme,
changeDarkTheme,
changeBrowser,
changeStaticEmoji
changeAutoplayGifv
} = settingsSlice.actions
export default settingsSlice.reducer

View File

@ -1,19 +1,10 @@
import React, {
createContext,
PropsWithChildren,
useContext,
useEffect,
useState
} from 'react'
import React, { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'
import { Appearance } from 'react-native'
import { useSelector } from 'react-redux'
import { ColorDefinitions, getColors, Theme } from '@utils/styles/themes'
import {
getSettingsDarkTheme,
getSettingsTheme,
SettingsState
} from '@utils/slices/settingsSlice'
import { getSettingsDarkTheme, getSettingsTheme } from '@utils/slices/settingsSlice'
import { throttle } from 'lodash'
import { SettingsLatest } from '@utils/migrations/settings/migration'
type ContextType = {
mode: 'light' | 'dark'
@ -30,9 +21,7 @@ const ManageThemeContext = createContext<ContextType>({
export const useTheme = () => useContext(ManageThemeContext)
const useColorSchemeDelay = (delay = 500) => {
const [colorScheme, setColorScheme] = React.useState(
Appearance.getColorScheme()
)
const [colorScheme, setColorScheme] = React.useState(Appearance.getColorScheme())
const onColorSchemeChange = React.useCallback(
throttle(
({ colorScheme }) => {
@ -57,8 +46,8 @@ const useColorSchemeDelay = (delay = 500) => {
const determineTheme = (
osTheme: 'light' | 'dark' | null | undefined,
userTheme: SettingsState['theme'],
darkTheme: SettingsState['darkTheme']
userTheme: SettingsLatest['theme'],
darkTheme: SettingsLatest['darkTheme']
): 'light' | 'dark_lighter' | 'dark_darker' => {
enum DarkTheme {
lighter = 'dark_lighter',
@ -85,12 +74,8 @@ const ThemeManager: React.FC<PropsWithChildren> = ({ children }) => {
const userTheme = useSelector(getSettingsTheme)
const darkTheme = useSelector(getSettingsDarkTheme)
const [mode, setMode] = useState(
userTheme === 'auto' ? osTheme || 'light' : userTheme
)
const [theme, setTheme] = useState<Theme>(
determineTheme(osTheme, userTheme, darkTheme)
)
const [mode, setMode] = useState(userTheme === 'auto' ? osTheme || 'light' : userTheme)
const [theme, setTheme] = useState<Theme>(determineTheme(osTheme, userTheme, darkTheme))
useEffect(() => {
setMode(userTheme === 'auto' ? osTheme || 'light' : userTheme)
@ -100,9 +85,7 @@ const ThemeManager: React.FC<PropsWithChildren> = ({ children }) => {
}, [osTheme, userTheme, darkTheme])
return (
<ManageThemeContext.Provider
value={{ mode, theme, colors: getColors(theme) }}
>
<ManageThemeContext.Provider value={{ mode, theme, colors: getColors(theme) }}>
{children}
</ManageThemeContext.Provider>
)