diff options
author | Samuel Newman <mozzius@protonmail.com> | 2024-08-01 19:14:32 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-08-01 19:14:32 +0200 |
commit | c78e9e31472af42a7920af18186f9ae499595100 (patch) | |
tree | adb5481c1459ba5c0291291795975c52036332bd /src | |
parent | 388c157c366e67e0cb3d74e1cd05413ef41b235d (diff) | |
download | voidsky-c78e9e31472af42a7920af18186f9ae499595100.tar.zst |
Move theme controls to its own screen (#4866)
Diffstat (limited to 'src')
-rw-r--r-- | src/Navigation.tsx | 9 | ||||
-rw-r--r-- | src/components/forms/ToggleButton.tsx | 2 | ||||
-rw-r--r-- | src/components/icons/Moon.tsx | 5 | ||||
-rw-r--r-- | src/components/icons/Phone.tsx | 5 | ||||
-rw-r--r-- | src/lib/routes/types.ts | 1 | ||||
-rw-r--r-- | src/routes.ts | 1 | ||||
-rw-r--r-- | src/screens/Settings/AppearanceSettings.tsx | 135 | ||||
-rw-r--r-- | src/view/icons/index.tsx | 2 | ||||
-rw-r--r-- | src/view/screens/AccessibilitySettings.tsx | 10 | ||||
-rw-r--r-- | src/view/screens/PreferencesExternalEmbeds.tsx | 5 | ||||
-rw-r--r-- | src/view/screens/PreferencesFollowingFeed.tsx | 5 | ||||
-rw-r--r-- | src/view/screens/PreferencesThreads.tsx | 4 | ||||
-rw-r--r-- | src/view/screens/Settings/index.tsx | 95 |
13 files changed, 201 insertions, 78 deletions
diff --git a/src/Navigation.tsx b/src/Navigation.tsx index 8646577c8..79856879c 100644 --- a/src/Navigation.tsx +++ b/src/Navigation.tsx @@ -44,6 +44,7 @@ import HashtagScreen from '#/screens/Hashtag' import {ModerationScreen} from '#/screens/Moderation' import {ProfileKnownFollowersScreen} from '#/screens/Profile/KnownFollowers' import {ProfileLabelerLikedByScreen} from '#/screens/Profile/ProfileLabelerLikedBy' +import {AppearanceSettingsScreen} from '#/screens/Settings/AppearanceSettings' import { StarterPackScreen, StarterPackScreenShort, @@ -311,6 +312,14 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) { }} /> <Stack.Screen + name="AppearanceSettings" + getComponent={() => AppearanceSettingsScreen} + options={{ + title: title(msg`Appearance Settings`), + requireAuth: true, + }} + /> + <Stack.Screen name="Hashtag" getComponent={() => HashtagScreen} options={{title: title(msg`Hashtag`)}} diff --git a/src/components/forms/ToggleButton.tsx b/src/components/forms/ToggleButton.tsx index 752842638..f47a272b1 100644 --- a/src/components/forms/ToggleButton.tsx +++ b/src/components/forms/ToggleButton.tsx @@ -23,10 +23,10 @@ export function Group({children, multiple, ...props}: GroupProps) { style={[ a.w_full, a.flex_row, - a.border, a.rounded_sm, a.overflow_hidden, t.atoms.border_contrast_low, + {borderWidth: 1}, ]}> {children} </View> diff --git a/src/components/icons/Moon.tsx b/src/components/icons/Moon.tsx new file mode 100644 index 000000000..4994370b9 --- /dev/null +++ b/src/components/icons/Moon.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const Moon_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M12.097 2.53a1 1 0 0 1-.041 1.07 6 6 0 0 0 8.345 8.344 1 1 0 0 1 1.563.908c-.434 5.122-4.728 9.144-9.962 9.144-5.522 0-9.998-4.476-9.998-9.998 0-5.234 4.021-9.528 9.144-9.962a1 1 0 0 1 .949.494ZM9.424 4.424a7.998 7.998 0 1 0 10.152 10.152A8 8 0 0 1 9.424 4.424Z', +}) diff --git a/src/components/icons/Phone.tsx b/src/components/icons/Phone.tsx new file mode 100644 index 000000000..62000a1e5 --- /dev/null +++ b/src/components/icons/Phone.tsx @@ -0,0 +1,5 @@ +import {createSinglePathSVG} from './TEMPLATE' + +export const Phone_Stroke2_Corner0_Rounded = createSinglePathSVG({ + path: 'M5 4a3 3 0 0 1 3-3h8a3 3 0 0 1 3 3v16a3 3 0 0 1-3 3H8a3 3 0 0 1-3-3V4Zm3-1a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H8Zm2 2a1 1 0 0 1 1-1h2a1 1 0 1 1 0 2h-2a1 1 0 0 1-1-1Z', +}) diff --git a/src/lib/routes/types.ts b/src/lib/routes/types.ts index fbb66c9e9..0cc83b475 100644 --- a/src/lib/routes/types.ts +++ b/src/lib/routes/types.ts @@ -38,6 +38,7 @@ export type CommonNavigatorParams = { PreferencesThreads: undefined PreferencesExternalEmbeds: undefined AccessibilitySettings: undefined + AppearanceSettings: undefined Search: {q?: string} Hashtag: {tag: string; author?: string} MessagesConversation: {conversation: string; embed?: string} diff --git a/src/routes.ts b/src/routes.ts index ddf4fb39f..c9e23e08c 100644 --- a/src/routes.ts +++ b/src/routes.ts @@ -32,6 +32,7 @@ export const router = new Router({ PreferencesThreads: '/settings/threads', PreferencesExternalEmbeds: '/settings/external-embeds', AccessibilitySettings: '/settings/accessibility', + AppearanceSettings: '/settings/appearance', SavedFeeds: '/settings/saved-feeds', Support: '/support', PrivacyPolicy: '/support/privacy', diff --git a/src/screens/Settings/AppearanceSettings.tsx b/src/screens/Settings/AppearanceSettings.tsx new file mode 100644 index 000000000..00a04bbfb --- /dev/null +++ b/src/screens/Settings/AppearanceSettings.tsx @@ -0,0 +1,135 @@ +import React, {useCallback} from 'react' +import {View} from 'react-native' +import Animated, { + FadeInDown, + FadeOutDown, + LayoutAnimationConfig, +} from 'react-native-reanimated' +import {msg, Trans} from '@lingui/macro' +import {useLingui} from '@lingui/react' + +import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' +import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types' +import {s} from '#/lib/styles' +import {useSetThemePrefs, useThemePrefs} from '#/state/shell' +import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader' +import {ScrollView} from '#/view/com/util/Views' +import {atoms as a, native, useTheme} from '#/alf' +import * as ToggleButton from '#/components/forms/ToggleButton' +import {Moon_Stroke2_Corner0_Rounded as MoonIcon} from '#/components/icons/Moon' +import {Phone_Stroke2_Corner0_Rounded as PhoneIcon} from '#/components/icons/Phone' +import {Text} from '#/components/Typography' + +type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppearanceSettings'> +export function AppearanceSettingsScreen({}: Props) { + const {_} = useLingui() + const t = useTheme() + const {isTabletOrMobile} = useWebMediaQueries() + + const {colorMode, darkTheme} = useThemePrefs() + const {setColorMode, setDarkTheme} = useSetThemePrefs() + + const onChangeAppearance = useCallback( + (keys: string[]) => { + const appearance = keys.find(key => key !== colorMode) as + | 'system' + | 'light' + | 'dark' + | undefined + if (!appearance) return + setColorMode(appearance) + }, + [setColorMode, colorMode], + ) + + const onChangeDarkTheme = useCallback( + (keys: string[]) => { + const theme = keys.find(key => key !== darkTheme) as + | 'dim' + | 'dark' + | undefined + if (!theme) return + setDarkTheme(theme) + }, + [setDarkTheme, darkTheme], + ) + + return ( + <LayoutAnimationConfig skipExiting skipEntering> + <View testID="preferencesThreadsScreen" style={s.hContentRegion}> + <ScrollView + // @ts-ignore web only -prf + dataSet={{'stable-gutters': 1}} + contentContainerStyle={{paddingBottom: 75}}> + <SimpleViewHeader + showBackButton={isTabletOrMobile} + style={[t.atoms.border_contrast_medium, a.border_b]}> + <View style={a.flex_1}> + <Text style={[a.text_2xl, a.font_bold]}> + <Trans>Appearance</Trans> + </Text> + </View> + </SimpleViewHeader> + + <View style={[a.p_xl, a.gap_lg]}> + <View style={[a.flex_row, a.align_center, a.gap_md]}> + <PhoneIcon style={t.atoms.text} /> + <Text style={a.text_md}> + <Trans>Mode</Trans> + </Text> + </View> + <ToggleButton.Group + label={_(msg`Dark mode`)} + values={[colorMode]} + onChange={onChangeAppearance}> + <ToggleButton.Button label={_(msg`System`)} name="system"> + <ToggleButton.ButtonText> + <Trans>System</Trans> + </ToggleButton.ButtonText> + </ToggleButton.Button> + <ToggleButton.Button label={_(msg`Light`)} name="light"> + <ToggleButton.ButtonText> + <Trans>Light</Trans> + </ToggleButton.ButtonText> + </ToggleButton.Button> + <ToggleButton.Button label={_(msg`Dark`)} name="dark"> + <ToggleButton.ButtonText> + <Trans>Dark</Trans> + </ToggleButton.ButtonText> + </ToggleButton.Button> + </ToggleButton.Group> + {colorMode !== 'light' && ( + <Animated.View + entering={native(FadeInDown)} + exiting={native(FadeOutDown)} + style={[a.mt_md, a.gap_lg]}> + <View style={[a.flex_row, a.align_center, a.gap_md]}> + <MoonIcon style={t.atoms.text} /> + <Text style={a.text_md}> + <Trans>Dark theme</Trans> + </Text> + </View> + + <ToggleButton.Group + label={_(msg`Dark theme`)} + values={[darkTheme ?? 'dim']} + onChange={onChangeDarkTheme}> + <ToggleButton.Button label={_(msg`Dim`)} name="dim"> + <ToggleButton.ButtonText> + <Trans>Dim</Trans> + </ToggleButton.ButtonText> + </ToggleButton.Button> + <ToggleButton.Button label={_(msg`Dark`)} name="dark"> + <ToggleButton.ButtonText> + <Trans>Dark</Trans> + </ToggleButton.ButtonText> + </ToggleButton.Button> + </ToggleButton.Group> + </Animated.View> + )} + </View> + </ScrollView> + </View> + </LayoutAnimationConfig> + ) +} diff --git a/src/view/icons/index.tsx b/src/view/icons/index.tsx index beb31eca4..8b1655e6a 100644 --- a/src/view/icons/index.tsx +++ b/src/view/icons/index.tsx @@ -77,6 +77,7 @@ import {faListUl} from '@fortawesome/free-solid-svg-icons/faListUl' import {faLock} from '@fortawesome/free-solid-svg-icons/faLock' import {faMagnifyingGlass} from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass' import {faNoteSticky} from '@fortawesome/free-solid-svg-icons/faNoteSticky' +import {faPaintRoller} from '@fortawesome/free-solid-svg-icons/faPaintRoller' import {faPause} from '@fortawesome/free-solid-svg-icons/faPause' import {faPen} from '@fortawesome/free-solid-svg-icons/faPen' import {faPenNib} from '@fortawesome/free-solid-svg-icons/faPenNib' @@ -178,6 +179,7 @@ library.add( faMagnifyingGlass, faMessage, faNoteSticky, + faPaintRoller, faPaste, faPause, faPen, diff --git a/src/view/screens/AccessibilitySettings.tsx b/src/view/screens/AccessibilitySettings.tsx index abe155076..2a4477532 100644 --- a/src/view/screens/AccessibilitySettings.tsx +++ b/src/view/screens/AccessibilitySettings.tsx @@ -27,6 +27,7 @@ import {ToggleButton} from '#/view/com/util/forms/ToggleButton' import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader' import {Text} from '#/view/com/util/text/Text' import {ScrollView} from '#/view/com/util/Views' +import {atoms as a} from '#/alf' type Props = NativeStackScreenProps< CommonNavigatorParams, @@ -61,10 +62,13 @@ export function AccessibilitySettingsScreen({}: Props) { showBackButton={isTabletOrMobile} style={[ pal.border, - {borderBottomWidth: 1}, - !isMobile && {borderLeftWidth: 1, borderRightWidth: 1}, + a.border_b, + !isMobile && { + borderLeftWidth: StyleSheet.hairlineWidth, + borderRightWidth: StyleSheet.hairlineWidth, + }, ]}> - <View style={{flex: 1}}> + <View style={a.flex_1}> <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}> <Trans>Accessibility Settings</Trans> </Text> diff --git a/src/view/screens/PreferencesExternalEmbeds.tsx b/src/view/screens/PreferencesExternalEmbeds.tsx index 57ca5e765..ade7a53d9 100644 --- a/src/view/screens/PreferencesExternalEmbeds.tsx +++ b/src/view/screens/PreferencesExternalEmbeds.tsx @@ -18,6 +18,7 @@ import { useSetExternalEmbedPref, } from 'state/preferences' import {ToggleButton} from 'view/com/util/forms/ToggleButton' +import {atoms as a} from '#/alf' import {SimpleViewHeader} from '../com/util/SimpleViewHeader' import {Text} from '../com/util/text/Text' import {ScrollView} from '../com/util/Views' @@ -47,8 +48,8 @@ export function PreferencesExternalEmbeds({}: Props) { contentContainerStyle={[pal.viewLight, {paddingBottom: 75}]}> <SimpleViewHeader showBackButton={isTabletOrMobile} - style={[pal.border, {borderBottomWidth: 1}]}> - <View style={{flex: 1}}> + style={[pal.border, a.border_b]}> + <View style={a.flex_1}> <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}> <Trans>External Media Preferences</Trans> </Text> diff --git a/src/view/screens/PreferencesFollowingFeed.tsx b/src/view/screens/PreferencesFollowingFeed.tsx index 879c925fb..daa2aba85 100644 --- a/src/view/screens/PreferencesFollowingFeed.tsx +++ b/src/view/screens/PreferencesFollowingFeed.tsx @@ -19,6 +19,7 @@ import {ToggleButton} from '#/view/com/util/forms/ToggleButton' import {SimpleViewHeader} from '#/view/com/util/SimpleViewHeader' import {Text} from '#/view/com/util/text/Text' import {ScrollView} from '#/view/com/util/Views' +import {atoms as a} from '#/alf' function RepliesThresholdInput({ enabled, @@ -99,8 +100,8 @@ export function PreferencesFollowingFeed({}: Props) { contentContainerStyle={{paddingBottom: 75}}> <SimpleViewHeader showBackButton={isTabletOrMobile} - style={[pal.border, {borderBottomWidth: 1}]}> - <View style={{flex: 1}}> + style={[pal.border, a.border_b]}> + <View style={a.flex_1}> <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}> <Trans>Following Feed Preferences</Trans> </Text> diff --git a/src/view/screens/PreferencesThreads.tsx b/src/view/screens/PreferencesThreads.tsx index 3b09f0abb..4a311f91c 100644 --- a/src/view/screens/PreferencesThreads.tsx +++ b/src/view/screens/PreferencesThreads.tsx @@ -45,8 +45,8 @@ export function PreferencesThreads({}: Props) { contentContainerStyle={{paddingBottom: 75}}> <SimpleViewHeader showBackButton={isTabletOrMobile} - style={[pal.border, {borderBottomWidth: 1}]}> - <View style={{flex: 1}}> + style={[pal.border, a.border_b]}> + <View style={a.flex_1}> <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}> <Trans>Thread Preferences</Trans> </Text> diff --git a/src/view/screens/Settings/index.tsx b/src/view/screens/Settings/index.tsx index db74d5c0d..c33be7d54 100644 --- a/src/view/screens/Settings/index.tsx +++ b/src/view/screens/Settings/index.tsx @@ -31,12 +31,7 @@ import {useClearPreferencesMutation} from '#/state/queries/preferences' import {RQKEY as RQKEY_PROFILE} from '#/state/queries/profile' import {useProfileQuery} from '#/state/queries/profile' import {SessionAccount, useSession, useSessionApi} from '#/state/session' -import { - useOnboardingDispatch, - useSetMinimalShellMode, - useSetThemePrefs, - useThemePrefs, -} from '#/state/shell' +import {useOnboardingDispatch, useSetMinimalShellMode} from '#/state/shell' import {useLoggedOutViewControls} from '#/state/shell/logged-out' import {useCloseAllActiveElements} from '#/state/util' import {useAnalytics} from 'lib/analytics/analytics' @@ -52,7 +47,6 @@ import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' import {NavigationProp} from 'lib/routes/types' import {colors, s} from 'lib/styles' import {AccountDropdownBtn} from 'view/com/util/AccountDropdownBtn' -import {SelectableBtn} from 'view/com/util/forms/SelectableBtn' import {ToggleButton} from 'view/com/util/forms/ToggleButton' import {Link, TextLink} from 'view/com/util/Link' import {SimpleViewHeader} from 'view/com/util/SimpleViewHeader' @@ -61,8 +55,7 @@ import * as Toast from 'view/com/util/Toast' import {UserAvatar} from 'view/com/util/UserAvatar' import {ScrollView} from 'view/com/util/Views' import {DeactivateAccountDialog} from '#/screens/Settings/components/DeactivateAccountDialog' -import {useTheme} from '#/alf' -import {atoms as a} from '#/alf' +import {atoms as a, useTheme} from '#/alf' import {useDialogControl} from '#/components/Dialog' import {BirthDateSettingsDialog} from '#/components/dialogs/BirthDateSettings' import {navigate, resetToTab} from '#/Navigation' @@ -168,8 +161,6 @@ function SettingsAccountCard({ type Props = NativeStackScreenProps<CommonNavigatorParams, 'Settings'> export function SettingsScreen({}: Props) { const queryClient = useQueryClient() - const {colorMode, darkTheme} = useThemePrefs() - const {setColorMode, setDarkTheme} = useSetThemePrefs() const pal = usePalette('default') const {_} = useLingui() const setMinimalShellMode = useSetMinimalShellMode() @@ -296,6 +287,10 @@ export function SettingsScreen({}: Props) { navigation.navigate('AccessibilitySettings') }, [navigation]) + const onPressAppearanceSettings = React.useCallback(() => { + navigation.navigate('AppearanceSettings') + }, [navigation]) + const onPressBirthday = React.useCallback(() => { birthdayControl.open() }, [birthdayControl]) @@ -437,63 +432,6 @@ export function SettingsScreen({}: Props) { <View style={styles.spacer20} /> <Text type="xl-bold" style={[pal.text, styles.heading]}> - <Trans>Appearance</Trans> - </Text> - <View> - <View style={[styles.linkCard, pal.view, styles.selectableBtns]}> - <SelectableBtn - selected={colorMode === 'system'} - label={_(msg`System`)} - left - onSelect={() => setColorMode('system')} - accessibilityHint={_(msg`Sets color theme to system setting`)} - /> - <SelectableBtn - selected={colorMode === 'light'} - label={_(msg`Light`)} - onSelect={() => setColorMode('light')} - accessibilityHint={_(msg`Sets color theme to light`)} - /> - <SelectableBtn - selected={colorMode === 'dark'} - label={_(msg`Dark`)} - right - onSelect={() => setColorMode('dark')} - accessibilityHint={_(msg`Sets color theme to dark`)} - /> - </View> - </View> - - <View style={styles.spacer20} /> - - {colorMode !== 'light' && ( - <> - <Text type="xl-bold" style={[pal.text, styles.heading]}> - <Trans>Dark Theme</Trans> - </Text> - <View> - <View style={[styles.linkCard, pal.view, styles.selectableBtns]}> - <SelectableBtn - selected={!darkTheme || darkTheme === 'dim'} - label={_(msg`Dim`)} - left - onSelect={() => setDarkTheme('dim')} - accessibilityHint={_(msg`Sets dark theme to the dim theme`)} - /> - <SelectableBtn - selected={darkTheme === 'dark'} - label={_(msg`Dark`)} - right - onSelect={() => setDarkTheme('dark')} - accessibilityHint={_(msg`Sets dark theme to the dark theme`)} - /> - </View> - </View> - <View style={styles.spacer20} /> - </> - )} - - <Text type="xl-bold" style={[pal.text, styles.heading]}> <Trans>Basics</Trans> </Text> <TouchableOpacity @@ -520,6 +458,27 @@ export function SettingsScreen({}: Props) { </Text> </TouchableOpacity> <TouchableOpacity + testID="appearanceSettingsBtn" + style={[ + styles.linkCard, + pal.view, + isSwitchingAccounts && styles.dimmed, + ]} + onPress={isSwitchingAccounts ? undefined : onPressAppearanceSettings} + accessibilityRole="button" + accessibilityLabel={_(msg`Appearance settings`)} + accessibilityHint={_(msg`Opens appearance settings`)}> + <View style={[styles.iconContainer, pal.btn]}> + <FontAwesomeIcon + icon="paint-roller" + style={pal.text as FontAwesomeIconStyle} + /> + </View> + <Text type="lg" style={pal.text}> + <Trans>Appearance</Trans> + </Text> + </TouchableOpacity> + <TouchableOpacity testID="languageSettingsBtn" style={[ styles.linkCard, |