mirror of
https://github.com/tooot-app/app
synced 2025-04-08 23:51:20 +02:00
Fix #611
This commit is contained in:
parent
57e1206faf
commit
f3c40e9486
@ -1,2 +1,3 @@
|
|||||||
Enjoy toooting! This version includes following improvements and fixes:
|
Enjoy toooting! This version includes following improvements and fixes:
|
||||||
- Allowing adding more context of reports
|
- Allowing adding more context of reports
|
||||||
|
- Option to disable autoplay gif
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
toooting愉快!此版本包括以下改进和修复:
|
toooting愉快!此版本包括以下改进和修复:
|
||||||
- 可添加举报细节
|
- 可添加举报细节
|
||||||
|
- 新增暂停自动播放gif动画选项
|
@ -8,6 +8,8 @@ import AttachmentAltText from './AltText'
|
|||||||
import { Platform } from 'expo-modules-core'
|
import { Platform } from 'expo-modules-core'
|
||||||
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
import { useAccessibility } from '@utils/accessibility/AccessibilityManager'
|
||||||
import { aspectRatio } from './dimensions'
|
import { aspectRatio } from './dimensions'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { getSettingsAutoplayGifv } from '@utils/slices/settingsSlice'
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
total: number
|
total: number
|
||||||
@ -25,6 +27,7 @@ const AttachmentVideo: React.FC<Props> = ({
|
|||||||
gifv = false
|
gifv = false
|
||||||
}) => {
|
}) => {
|
||||||
const { reduceMotionEnabled } = useAccessibility()
|
const { reduceMotionEnabled } = useAccessibility()
|
||||||
|
const autoplayGifv = useSelector(getSettingsAutoplayGifv)
|
||||||
|
|
||||||
const videoPlayer = useRef<Video>(null)
|
const videoPlayer = useRef<Video>(null)
|
||||||
const [videoLoading, setVideoLoading] = useState(false)
|
const [videoLoading, setVideoLoading] = useState(false)
|
||||||
@ -60,7 +63,7 @@ const AttachmentVideo: React.FC<Props> = ({
|
|||||||
resizeMode={videoResizeMode}
|
resizeMode={videoResizeMode}
|
||||||
{...(gifv
|
{...(gifv
|
||||||
? {
|
? {
|
||||||
shouldPlay: reduceMotionEnabled ? false : true,
|
shouldPlay: reduceMotionEnabled || !autoplayGifv ? false : true,
|
||||||
isMuted: true,
|
isMuted: true,
|
||||||
isLooping: true,
|
isLooping: true,
|
||||||
source: { uri: video.url }
|
source: { uri: video.url }
|
||||||
@ -73,7 +76,7 @@ const AttachmentVideo: React.FC<Props> = ({
|
|||||||
onFullscreenUpdate={event => {
|
onFullscreenUpdate={event => {
|
||||||
if (event.fullscreenUpdate === VideoFullscreenUpdate.PLAYER_DID_DISMISS) {
|
if (event.fullscreenUpdate === VideoFullscreenUpdate.PLAYER_DID_DISMISS) {
|
||||||
Platform.OS === 'android' && setVideoResizeMode(ResizeMode.COVER)
|
Platform.OS === 'android' && setVideoResizeMode(ResizeMode.COVER)
|
||||||
if (gifv && !reduceMotionEnabled) {
|
if (gifv && !reduceMotionEnabled && autoplayGifv) {
|
||||||
videoPlayer.current?.playAsync()
|
videoPlayer.current?.playAsync()
|
||||||
} else {
|
} else {
|
||||||
videoPlayer.current?.pauseAsync()
|
videoPlayer.current?.pauseAsync()
|
||||||
@ -106,7 +109,7 @@ const AttachmentVideo: React.FC<Props> = ({
|
|||||||
video.blurhash ? (
|
video.blurhash ? (
|
||||||
<Blurhash blurhash={video.blurhash} style={{ width: '100%', height: '100%' }} />
|
<Blurhash blurhash={video.blurhash} style={{ width: '100%', height: '100%' }} />
|
||||||
) : null
|
) : null
|
||||||
) : !gifv || (gifv && reduceMotionEnabled) ? (
|
) : !gifv || (gifv && (reduceMotionEnabled || !autoplayGifv)) ? (
|
||||||
<Button
|
<Button
|
||||||
round
|
round
|
||||||
overlay
|
overlay
|
||||||
@ -119,6 +122,21 @@ const AttachmentVideo: React.FC<Props> = ({
|
|||||||
) : null}
|
) : null}
|
||||||
<AttachmentAltText sensitiveShown={sensitiveShown} text={video.description} />
|
<AttachmentAltText sensitiveShown={sensitiveShown} text={video.description} />
|
||||||
</Pressable>
|
</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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,7 @@
|
|||||||
"placeholder": "What's on your mind",
|
"placeholder": "What's on your mind",
|
||||||
"keyboardImage": {
|
"keyboardImage": {
|
||||||
"exceedMaximum": {
|
"exceedMaximum": {
|
||||||
"title": "Maximum attachments amount reached",
|
"title": "Maximum attachments amount reached"
|
||||||
"OK": "$t(common:buttons.OK)"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,19 +28,7 @@
|
|||||||
"filters": {
|
"filters": {
|
||||||
"accessibilityLabel": "Filter",
|
"accessibilityLabel": "Filter",
|
||||||
"accessibilityHint": "Filter shown notifications' types",
|
"accessibilityHint": "Filter shown notifications' types",
|
||||||
"title": "Show notifications",
|
"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)"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"me": {
|
"me": {
|
||||||
@ -266,19 +254,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"settings": {
|
"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": {
|
"theme": {
|
||||||
"heading": "Appearance",
|
"heading": "Appearance",
|
||||||
"options": {
|
"options": {
|
||||||
@ -301,9 +276,8 @@
|
|||||||
"external": "Use system browser"
|
"external": "Use system browser"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"staticEmoji": {
|
"autoplayGifv": {
|
||||||
"heading": "Use static emoji",
|
"heading": "Autoplay GIF in timeline"
|
||||||
"description": "If you encounter frequent app crash when viewing emoji list, you can try to use static emoji instead."
|
|
||||||
},
|
},
|
||||||
"feedback": {
|
"feedback": {
|
||||||
"heading": "Feature Requests"
|
"heading": "Feature Requests"
|
||||||
@ -332,9 +306,7 @@
|
|||||||
"moved": "User moved",
|
"moved": "User moved",
|
||||||
"created_at": "Joined: {{date}}",
|
"created_at": "Joined: {{date}}",
|
||||||
"summary": {
|
"summary": {
|
||||||
"statuses_count": "{{count}} toots",
|
"statuses_count": "{{count}} toots"
|
||||||
"following_count": "$t(shared.users.accounts.following)",
|
|
||||||
"followers_count": "$t(shared.users.accounts.followers)"
|
|
||||||
},
|
},
|
||||||
"toots": {
|
"toots": {
|
||||||
"default": "Toots",
|
"default": "Toots",
|
||||||
|
@ -15,7 +15,7 @@ import { uploadAttachment } from '../Footer/addAttachment'
|
|||||||
|
|
||||||
const ComposeTextInput: React.FC = () => {
|
const ComposeTextInput: React.FC = () => {
|
||||||
const { composeState, composeDispatch } = useContext(ComposeContext)
|
const { composeState, composeDispatch } = useContext(ComposeContext)
|
||||||
const { t } = useTranslation('screenCompose')
|
const { t } = useTranslation(['common', 'screenCompose'])
|
||||||
const { colors, mode } = useTheme()
|
const { colors, mode } = useTheme()
|
||||||
|
|
||||||
const maxAttachments = useSelector(getInstanceConfigurationStatusMaxAttachments, () => true)
|
const maxAttachments = useSelector(getInstanceConfigurationStatusMaxAttachments, () => true)
|
||||||
@ -39,7 +39,7 @@ const ComposeTextInput: React.FC = () => {
|
|||||||
autoFocus
|
autoFocus
|
||||||
enablesReturnKeyAutomatically
|
enablesReturnKeyAutomatically
|
||||||
multiline
|
multiline
|
||||||
placeholder={t('content.root.header.textInput.placeholder')}
|
placeholder={t('screenCompose:content.root.header.textInput.placeholder')}
|
||||||
placeholderTextColor={colors.secondary}
|
placeholderTextColor={colors.secondary}
|
||||||
onChangeText={content =>
|
onChangeText={content =>
|
||||||
formatText({
|
formatText({
|
||||||
@ -74,11 +74,11 @@ const ComposeTextInput: React.FC = () => {
|
|||||||
onPaste={(error: string | null | undefined, files: PastedFile[]) => {
|
onPaste={(error: string | null | undefined, files: PastedFile[]) => {
|
||||||
if (composeState.attachments.uploads.length + files.length > maxAttachments) {
|
if (composeState.attachments.uploads.length + files.length > maxAttachments) {
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
t('content.root.header.textInput.keyboardImage.exceedMaximum.title'),
|
t('screenCompose:content.root.header.textInput.keyboardImage.exceedMaximum.title'),
|
||||||
undefined,
|
undefined,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: t('content.root.header.textInput.keyboardImage.exceedMaximum.OK'),
|
text: t('common:buttons.OK'),
|
||||||
style: 'default'
|
style: 'default'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -13,8 +13,8 @@ import {
|
|||||||
getSettingsFontsize,
|
getSettingsFontsize,
|
||||||
getSettingsDarkTheme,
|
getSettingsDarkTheme,
|
||||||
changeDarkTheme,
|
changeDarkTheme,
|
||||||
getSettingsStaticEmoji,
|
getSettingsAutoplayGifv,
|
||||||
changeStaticEmoji
|
changeAutoplayGifv
|
||||||
} from '@utils/slices/settingsSlice'
|
} from '@utils/slices/settingsSlice'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
import * as Localization from 'expo-localization'
|
import * as Localization from 'expo-localization'
|
||||||
@ -35,20 +35,18 @@ const SettingsApp: React.FC = () => {
|
|||||||
const settingsTheme = useSelector(getSettingsTheme)
|
const settingsTheme = useSelector(getSettingsTheme)
|
||||||
const settingsDarkTheme = useSelector(getSettingsDarkTheme)
|
const settingsDarkTheme = useSelector(getSettingsDarkTheme)
|
||||||
const settingsBrowser = useSelector(getSettingsBrowser)
|
const settingsBrowser = useSelector(getSettingsBrowser)
|
||||||
const settingsStaticEmoji = useSelector(getSettingsStaticEmoji)
|
const settingsAutoplayGifv = useSelector(getSettingsAutoplayGifv)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('screenTabs:me.settings.fontsize.heading')}
|
title={t('screenTabs:me.stacks.fontSize.name')}
|
||||||
content={t(
|
content={t(`screenTabs:me.fontSize.sizes.${mapFontsizeToName(settingsFontsize)}`)}
|
||||||
`screenTabs:me.settings.fontsize.content.${mapFontsizeToName(settingsFontsize)}`
|
|
||||||
)}
|
|
||||||
iconBack='ChevronRight'
|
iconBack='ChevronRight'
|
||||||
onPress={() => navigation.navigate('Tab-Me-Settings-Fontsize')}
|
onPress={() => navigation.navigate('Tab-Me-Settings-Fontsize')}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('screenTabs:me.settings.language.heading')}
|
title={t('screenTabs:me.stacks.language.name')}
|
||||||
content={
|
content={
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
LOCALES[
|
LOCALES[
|
||||||
@ -161,10 +159,9 @@ const SettingsApp: React.FC = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<MenuRow
|
<MenuRow
|
||||||
title={t('screenTabs:me.settings.staticEmoji.heading')}
|
title={t('screenTabs:me.settings.autoplayGifv.heading')}
|
||||||
description={t('screenTabs:me.settings.staticEmoji.description')}
|
switchValue={settingsAutoplayGifv}
|
||||||
switchValue={settingsStaticEmoji}
|
switchOnValueChange={() => dispatch(changeAutoplayGifv(!settingsAutoplayGifv))}
|
||||||
switchOnValueChange={() => dispatch(changeStaticEmoji(!settingsStaticEmoji))}
|
|
||||||
/>
|
/>
|
||||||
</MenuContainer>
|
</MenuContainer>
|
||||||
)
|
)
|
||||||
|
@ -4,8 +4,9 @@ import ComponentSeparator from '@components/Separator'
|
|||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
import { useAppDispatch } from '@root/store'
|
import { useAppDispatch } from '@root/store'
|
||||||
|
import { SettingsLatest } from '@utils/migrations/settings/migration'
|
||||||
import { TabMeStackScreenProps } from '@utils/navigation/navigators'
|
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 { StyleConstants } from '@utils/styles/constants'
|
||||||
import { adaptiveScale } from '@utils/styles/scaling'
|
import { adaptiveScale } from '@utils/styles/scaling'
|
||||||
import { useTheme } from '@utils/styles/ThemeManager'
|
import { useTheme } from '@utils/styles/ThemeManager'
|
||||||
@ -15,7 +16,7 @@ import { StyleSheet, View } from 'react-native'
|
|||||||
import { ScrollView } from 'react-native-gesture-handler'
|
import { ScrollView } from 'react-native-gesture-handler'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
export const mapFontsizeToName = (size: SettingsState['fontsize']) => {
|
export const mapFontsizeToName = (size: SettingsLatest['fontsize']) => {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case -1:
|
case -1:
|
||||||
return 'S'
|
return 'S'
|
||||||
|
@ -81,7 +81,7 @@ const TabNotificationsFilters: React.FC<
|
|||||||
{PUSH_DEFAULT(pushFeatures).map((type, index) => (
|
{PUSH_DEFAULT(pushFeatures).map((type, index) => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={index}
|
key={index}
|
||||||
title={t(`screenTabs:notifications.filters.options.${type}`)}
|
title={t(`screenTabs:me.push.${type}.heading`)}
|
||||||
switchValue={filters[type]}
|
switchValue={filters[type]}
|
||||||
switchOnValueChange={() => setFilters({ ...filters, [type]: !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 }) => (
|
{PUSH_ADMIN(pushFeatures, profileQuery.data?.role?.permissions).map(({ type }) => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={type}
|
key={type}
|
||||||
title={t(`screenTabs:notifications.filters.options.${type}`)}
|
title={t(`screenTabs:me.push.${type}.heading`)}
|
||||||
switchValue={filters[type]}
|
switchValue={filters[type]}
|
||||||
switchOnValueChange={() => setFilters({ ...filters, [type]: !filters[type] })}
|
switchOnValueChange={() => setFilters({ ...filters, [type]: !filters[type] })}
|
||||||
/>
|
/>
|
||||||
|
@ -47,7 +47,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
|
|||||||
{account ? (
|
{account ? (
|
||||||
<CustomText
|
<CustomText
|
||||||
style={[styles.stat, { color: colors.primaryDefault, textAlign: 'right' }]}
|
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
|
count: account.following_count
|
||||||
})}
|
})}
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
@ -71,7 +71,7 @@ const AccountInformationStats: React.FC<Props> = ({ account, myInfo }) => {
|
|||||||
{account ? (
|
{account ? (
|
||||||
<CustomText
|
<CustomText
|
||||||
style={[styles.stat, { color: colors.primaryDefault, textAlign: 'center' }]}
|
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
|
count: account.followers_count
|
||||||
})}
|
})}
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
|
@ -3,11 +3,11 @@ import AsyncStorage from '@react-native-async-storage/async-storage'
|
|||||||
import { AnyAction, configureStore, Reducer } from '@reduxjs/toolkit'
|
import { AnyAction, configureStore, Reducer } from '@reduxjs/toolkit'
|
||||||
import contextsMigration, { ContextsLatest } from '@utils/migrations/contexts/migration'
|
import contextsMigration, { ContextsLatest } from '@utils/migrations/contexts/migration'
|
||||||
import instancesMigration from '@utils/migrations/instances/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 appSlice, { AppState } from '@utils/slices/appSlice'
|
||||||
import contextsSlice from '@utils/slices/contextsSlice'
|
import contextsSlice from '@utils/slices/contextsSlice'
|
||||||
import instancesSlice, { InstancesState } from '@utils/slices/instancesSlice'
|
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 { Platform } from 'react-native'
|
||||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
|
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
|
||||||
import {
|
import {
|
||||||
@ -72,7 +72,7 @@ const store = configureStore({
|
|||||||
AnyAction
|
AnyAction
|
||||||
>,
|
>,
|
||||||
settings: persistReducer(settingsPersistConfig, settingsSlice) as Reducer<
|
settings: persistReducer(settingsPersistConfig, settingsSlice) as Reducer<
|
||||||
SettingsState,
|
SettingsLatest,
|
||||||
AnyAction
|
AnyAction
|
||||||
>
|
>
|
||||||
},
|
},
|
||||||
|
@ -2,6 +2,7 @@ import { SettingsV0 } from './v0'
|
|||||||
import { SettingsV1 } from './v1'
|
import { SettingsV1 } from './v1'
|
||||||
import { SettingsV2 } from './v2'
|
import { SettingsV2 } from './v2'
|
||||||
import { SettingsV3 } from './v3'
|
import { SettingsV3 } from './v3'
|
||||||
|
import { SettingsV4 } from './v4'
|
||||||
|
|
||||||
const settingsMigration = {
|
const settingsMigration = {
|
||||||
1: (state: SettingsV0): SettingsV1 => {
|
1: (state: SettingsV0): SettingsV1 => {
|
||||||
@ -20,7 +21,13 @@ const settingsMigration = {
|
|||||||
3: (state: SettingsV2): SettingsV3 => {
|
3: (state: SettingsV2): SettingsV3 => {
|
||||||
const { analytics, ...rest } = state
|
const { analytics, ...rest } = state
|
||||||
return rest
|
return rest
|
||||||
|
},
|
||||||
|
4: (state: SettingsV3): SettingsV4 => {
|
||||||
|
const { staticEmoji, ...rest } = state
|
||||||
|
return { ...rest, autoplayGifv: true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { SettingsV4 as SettingsLatest }
|
||||||
|
|
||||||
export default settingsMigration
|
export default settingsMigration
|
||||||
|
8
src/utils/migrations/settings/v4.ts
Normal file
8
src/utils/migrations/settings/v4.ts
Normal 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
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||||
import { LOCALES } from '@root/i18n/locales'
|
import { LOCALES } from '@root/i18n/locales'
|
||||||
import { RootState } from '@root/store'
|
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 * as Localization from 'expo-localization'
|
||||||
import { pickBy } from 'lodash'
|
import { pickBy } from 'lodash'
|
||||||
|
|
||||||
export type SettingsState = SettingsV3
|
|
||||||
|
|
||||||
export const settingsInitialState = {
|
export const settingsInitialState = {
|
||||||
fontsize: 0,
|
fontsize: 0,
|
||||||
notification: {
|
notification: {
|
||||||
@ -18,33 +16,33 @@ export const settingsInitialState = {
|
|||||||
theme: 'auto',
|
theme: 'auto',
|
||||||
darkTheme: 'lighter',
|
darkTheme: 'lighter',
|
||||||
browser: 'internal',
|
browser: 'internal',
|
||||||
staticEmoji: false
|
autoplayGifv: true
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsSlice = createSlice({
|
const settingsSlice = createSlice({
|
||||||
name: 'settings',
|
name: 'settings',
|
||||||
initialState: settingsInitialState as SettingsState,
|
initialState: settingsInitialState as SettingsLatest,
|
||||||
reducers: {
|
reducers: {
|
||||||
changeFontsize: (state, action: PayloadAction<SettingsState['fontsize']>) => {
|
changeFontsize: (state, action: PayloadAction<SettingsLatest['fontsize']>) => {
|
||||||
state.fontsize = action.payload
|
state.fontsize = action.payload
|
||||||
},
|
},
|
||||||
changeLanguage: (state, action: PayloadAction<NonNullable<SettingsState['language']>>) => {
|
changeLanguage: (state, action: PayloadAction<NonNullable<SettingsLatest['language']>>) => {
|
||||||
state.language = action.payload
|
state.language = action.payload
|
||||||
},
|
},
|
||||||
changeTheme: (state, action: PayloadAction<NonNullable<SettingsState['theme']>>) => {
|
changeTheme: (state, action: PayloadAction<NonNullable<SettingsLatest['theme']>>) => {
|
||||||
state.theme = action.payload
|
state.theme = action.payload
|
||||||
},
|
},
|
||||||
changeDarkTheme: (state, action: PayloadAction<NonNullable<SettingsState['darkTheme']>>) => {
|
changeDarkTheme: (state, action: PayloadAction<NonNullable<SettingsLatest['darkTheme']>>) => {
|
||||||
state.darkTheme = action.payload
|
state.darkTheme = action.payload
|
||||||
},
|
},
|
||||||
changeBrowser: (state, action: PayloadAction<NonNullable<SettingsState['browser']>>) => {
|
changeBrowser: (state, action: PayloadAction<NonNullable<SettingsLatest['browser']>>) => {
|
||||||
state.browser = action.payload
|
state.browser = action.payload
|
||||||
},
|
},
|
||||||
changeStaticEmoji: (
|
changeAutoplayGifv: (
|
||||||
state,
|
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 getSettingsTheme = (state: RootState) => state.settings.theme
|
||||||
export const getSettingsDarkTheme = (state: RootState) => state.settings.darkTheme
|
export const getSettingsDarkTheme = (state: RootState) => state.settings.darkTheme
|
||||||
export const getSettingsBrowser = (state: RootState) => state.settings.browser
|
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 {
|
export const {
|
||||||
changeFontsize,
|
changeFontsize,
|
||||||
@ -62,6 +60,6 @@ export const {
|
|||||||
changeTheme,
|
changeTheme,
|
||||||
changeDarkTheme,
|
changeDarkTheme,
|
||||||
changeBrowser,
|
changeBrowser,
|
||||||
changeStaticEmoji
|
changeAutoplayGifv
|
||||||
} = settingsSlice.actions
|
} = settingsSlice.actions
|
||||||
export default settingsSlice.reducer
|
export default settingsSlice.reducer
|
||||||
|
@ -1,19 +1,10 @@
|
|||||||
import React, {
|
import React, { createContext, PropsWithChildren, useContext, useEffect, useState } from 'react'
|
||||||
createContext,
|
|
||||||
PropsWithChildren,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useState
|
|
||||||
} from 'react'
|
|
||||||
import { Appearance } from 'react-native'
|
import { Appearance } from 'react-native'
|
||||||
import { useSelector } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
import { ColorDefinitions, getColors, Theme } from '@utils/styles/themes'
|
import { ColorDefinitions, getColors, Theme } from '@utils/styles/themes'
|
||||||
import {
|
import { getSettingsDarkTheme, getSettingsTheme } from '@utils/slices/settingsSlice'
|
||||||
getSettingsDarkTheme,
|
|
||||||
getSettingsTheme,
|
|
||||||
SettingsState
|
|
||||||
} from '@utils/slices/settingsSlice'
|
|
||||||
import { throttle } from 'lodash'
|
import { throttle } from 'lodash'
|
||||||
|
import { SettingsLatest } from '@utils/migrations/settings/migration'
|
||||||
|
|
||||||
type ContextType = {
|
type ContextType = {
|
||||||
mode: 'light' | 'dark'
|
mode: 'light' | 'dark'
|
||||||
@ -30,9 +21,7 @@ const ManageThemeContext = createContext<ContextType>({
|
|||||||
export const useTheme = () => useContext(ManageThemeContext)
|
export const useTheme = () => useContext(ManageThemeContext)
|
||||||
|
|
||||||
const useColorSchemeDelay = (delay = 500) => {
|
const useColorSchemeDelay = (delay = 500) => {
|
||||||
const [colorScheme, setColorScheme] = React.useState(
|
const [colorScheme, setColorScheme] = React.useState(Appearance.getColorScheme())
|
||||||
Appearance.getColorScheme()
|
|
||||||
)
|
|
||||||
const onColorSchemeChange = React.useCallback(
|
const onColorSchemeChange = React.useCallback(
|
||||||
throttle(
|
throttle(
|
||||||
({ colorScheme }) => {
|
({ colorScheme }) => {
|
||||||
@ -57,8 +46,8 @@ const useColorSchemeDelay = (delay = 500) => {
|
|||||||
|
|
||||||
const determineTheme = (
|
const determineTheme = (
|
||||||
osTheme: 'light' | 'dark' | null | undefined,
|
osTheme: 'light' | 'dark' | null | undefined,
|
||||||
userTheme: SettingsState['theme'],
|
userTheme: SettingsLatest['theme'],
|
||||||
darkTheme: SettingsState['darkTheme']
|
darkTheme: SettingsLatest['darkTheme']
|
||||||
): 'light' | 'dark_lighter' | 'dark_darker' => {
|
): 'light' | 'dark_lighter' | 'dark_darker' => {
|
||||||
enum DarkTheme {
|
enum DarkTheme {
|
||||||
lighter = 'dark_lighter',
|
lighter = 'dark_lighter',
|
||||||
@ -85,12 +74,8 @@ const ThemeManager: React.FC<PropsWithChildren> = ({ children }) => {
|
|||||||
const userTheme = useSelector(getSettingsTheme)
|
const userTheme = useSelector(getSettingsTheme)
|
||||||
const darkTheme = useSelector(getSettingsDarkTheme)
|
const darkTheme = useSelector(getSettingsDarkTheme)
|
||||||
|
|
||||||
const [mode, setMode] = useState(
|
const [mode, setMode] = useState(userTheme === 'auto' ? osTheme || 'light' : userTheme)
|
||||||
userTheme === 'auto' ? osTheme || 'light' : userTheme
|
const [theme, setTheme] = useState<Theme>(determineTheme(osTheme, userTheme, darkTheme))
|
||||||
)
|
|
||||||
const [theme, setTheme] = useState<Theme>(
|
|
||||||
determineTheme(osTheme, userTheme, darkTheme)
|
|
||||||
)
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMode(userTheme === 'auto' ? osTheme || 'light' : userTheme)
|
setMode(userTheme === 'auto' ? osTheme || 'light' : userTheme)
|
||||||
@ -100,9 +85,7 @@ const ThemeManager: React.FC<PropsWithChildren> = ({ children }) => {
|
|||||||
}, [osTheme, userTheme, darkTheme])
|
}, [osTheme, userTheme, darkTheme])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ManageThemeContext.Provider
|
<ManageThemeContext.Provider value={{ mode, theme, colors: getColors(theme) }}>
|
||||||
value={{ mode, theme, colors: getColors(theme) }}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</ManageThemeContext.Provider>
|
</ManageThemeContext.Provider>
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user