diff options
Diffstat (limited to 'src/view/screens')
-rw-r--r-- | src/view/screens/DebugNew.tsx | 541 | ||||
-rw-r--r-- | src/view/screens/Home.tsx | 5 | ||||
-rw-r--r-- | src/view/screens/Moderation.tsx | 8 | ||||
-rw-r--r-- | src/view/screens/PreferencesExternalEmbeds.tsx | 138 | ||||
-rw-r--r-- | src/view/screens/PreferencesHomeFeed.tsx | 8 | ||||
-rw-r--r-- | src/view/screens/PreferencesThreads.tsx | 18 | ||||
-rw-r--r-- | src/view/screens/SavedFeeds.tsx | 12 | ||||
-rw-r--r-- | src/view/screens/Settings.tsx | 35 |
8 files changed, 752 insertions, 13 deletions
diff --git a/src/view/screens/DebugNew.tsx b/src/view/screens/DebugNew.tsx new file mode 100644 index 000000000..0b7c5f03b --- /dev/null +++ b/src/view/screens/DebugNew.tsx @@ -0,0 +1,541 @@ +import React from 'react' +import {View} from 'react-native' +import {CenteredView, ScrollView} from '#/view/com/util/Views' +import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' + +import {useSetColorMode} from '#/state/shell' +import * as tokens from '#/alf/tokens' +import {atoms as a, useTheme, useBreakpoints, ThemeProvider as Alf} from '#/alf' +import {Button, ButtonText} from '#/view/com/Button' +import {Text, H1, H2, H3, H4, H5, H6} from '#/view/com/Typography' + +function ThemeSelector() { + const setColorMode = useSetColorMode() + + return ( + <View style={[a.flex_row, a.gap_md]}> + <Button + type="secondary" + size="small" + onPress={() => setColorMode('system')}> + System + </Button> + <Button + type="secondary" + size="small" + onPress={() => setColorMode('light')}> + Light + </Button> + <Button + type="secondary" + size="small" + onPress={() => setColorMode('dark')}> + Dark + </Button> + </View> + ) +} + +function BreakpointDebugger() { + const t = useTheme() + const breakpoints = useBreakpoints() + + return ( + <View> + <H3 style={[a.pb_md]}>Breakpoint Debugger</H3> + <Text style={[a.pb_md]}> + Current breakpoint: {!breakpoints.gtMobile && <Text>mobile</Text>} + {breakpoints.gtMobile && !breakpoints.gtTablet && <Text>tablet</Text>} + {breakpoints.gtTablet && <Text>desktop</Text>} + </Text> + <Text + style={[a.p_md, t.atoms.bg_contrast_100, {fontFamily: 'monospace'}]}> + {JSON.stringify(breakpoints, null, 2)} + </Text> + </View> + ) +} + +function ThemedSection() { + const t = useTheme() + + return ( + <View style={[t.atoms.bg, a.gap_md, a.p_xl]}> + <H3 style={[a.font_bold]}>theme.atoms.text</H3> + <View style={[a.flex_1, t.atoms.border, a.border_t]} /> + <H3 style={[a.font_bold, t.atoms.text_contrast_700]}> + theme.atoms.text_contrast_700 + </H3> + <View style={[a.flex_1, t.atoms.border, a.border_t]} /> + <H3 style={[a.font_bold, t.atoms.text_contrast_500]}> + theme.atoms.text_contrast_500 + </H3> + <View style={[a.flex_1, t.atoms.border_contrast_500, a.border_t]} /> + + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + t.atoms.bg, + a.align_center, + a.justify_center, + {height: 60}, + ]}> + <Text>theme.bg</Text> + </View> + <View + style={[ + a.flex_1, + t.atoms.bg_contrast_100, + a.align_center, + a.justify_center, + {height: 60}, + ]}> + <Text>theme.bg_contrast_100</Text> + </View> + </View> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + t.atoms.bg_contrast_200, + a.align_center, + a.justify_center, + {height: 60}, + ]}> + <Text>theme.bg_contrast_200</Text> + </View> + <View + style={[ + a.flex_1, + t.atoms.bg_contrast_300, + a.align_center, + a.justify_center, + {height: 60}, + ]}> + <Text>theme.bg_contrast_300</Text> + </View> + </View> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + t.atoms.bg_positive, + a.align_center, + a.justify_center, + {height: 60}, + ]}> + <Text>theme.bg_positive</Text> + </View> + <View + style={[ + a.flex_1, + t.atoms.bg_negative, + a.align_center, + a.justify_center, + {height: 60}, + ]}> + <Text>theme.bg_negative</Text> + </View> + </View> + </View> + ) +} + +export function DebugScreen() { + const t = useTheme() + + return ( + <ScrollView> + <CenteredView style={[t.atoms.bg]}> + <View style={[a.p_xl, a.gap_xxl, {paddingBottom: 200}]}> + <ThemeSelector /> + + <Alf theme="light"> + <ThemedSection /> + </Alf> + <Alf theme="dark"> + <ThemedSection /> + </Alf> + + <H1>Heading 1</H1> + <H2>Heading 2</H2> + <H3>Heading 3</H3> + <H4>Heading 4</H4> + <H5>Heading 5</H5> + <H6>Heading 6</H6> + + <Text style={[a.text_xxl]}>atoms.text_xxl</Text> + <Text style={[a.text_xl]}>atoms.text_xl</Text> + <Text style={[a.text_lg]}>atoms.text_lg</Text> + <Text style={[a.text_md]}>atoms.text_md</Text> + <Text style={[a.text_sm]}>atoms.text_sm</Text> + <Text style={[a.text_xs]}>atoms.text_xs</Text> + <Text style={[a.text_xxs]}>atoms.text_xxs</Text> + + <View style={[a.gap_md, a.align_start]}> + <Button> + {({state}) => ( + <View style={[a.p_md, a.rounded_full, t.atoms.bg_contrast_300]}> + <Text>Unstyled button, state: {JSON.stringify(state)}</Text> + </View> + )} + </Button> + + <Button type="primary" size="small"> + Button + </Button> + <Button type="secondary" size="small"> + Button + </Button> + + <Button type="primary" size="large"> + Button + </Button> + <Button type="secondary" size="large"> + Button + </Button> + + <Button type="secondary" size="small"> + {({type, size}) => ( + <> + <FontAwesomeIcon icon={['fas', 'plus']} size={12} /> + <ButtonText type={type} size={size}> + With an icon + </ButtonText> + </> + )} + </Button> + <Button type="primary" size="large"> + {({state: _state, ...rest}) => ( + <> + <FontAwesomeIcon icon={['fas', 'plus']} /> + <ButtonText {...rest}>With an icon</ButtonText> + </> + )} + </Button> + </View> + + <View style={[a.gap_md]}> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_0}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.gray_1000}, + ]} + /> + </View> + + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_0}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.blue_1000}, + ]} + /> + </View> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_0}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.green_1000}, + ]} + /> + </View> + <View style={[a.flex_row, a.gap_md]}> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_0}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_100}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_200}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_300}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_400}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_500}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_600}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_700}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_800}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_900}, + ]} + /> + <View + style={[ + a.flex_1, + {height: 60, backgroundColor: tokens.color.red_1000}, + ]} + /> + </View> + </View> + + <View> + <H3 style={[a.pb_md, a.font_bold]}>Spacing</H3> + + <View style={[a.gap_md]}> + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>xxs (2px)</Text> + <View style={[a.flex_1, a.pt_xxs, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>xs (4px)</Text> + <View style={[a.flex_1, a.pt_xs, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>sm (8px)</Text> + <View style={[a.flex_1, a.pt_sm, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>md (12px)</Text> + <View style={[a.flex_1, a.pt_md, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>lg (18px)</Text> + <View style={[a.flex_1, a.pt_lg, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>xl (24px)</Text> + <View style={[a.flex_1, a.pt_xl, t.atoms.bg_contrast_300]} /> + </View> + + <View style={[a.flex_row, a.align_center]}> + <Text style={{width: 80}}>xxl (32px)</Text> + <View style={[a.flex_1, a.pt_xxl, t.atoms.bg_contrast_300]} /> + </View> + </View> + </View> + + <BreakpointDebugger /> + </View> + </CenteredView> + </ScrollView> + ) +} diff --git a/src/view/screens/Home.tsx b/src/view/screens/Home.tsx index b8033f0b4..0e20a9cf7 100644 --- a/src/view/screens/Home.tsx +++ b/src/view/screens/Home.tsx @@ -19,6 +19,7 @@ import {useSession} from '#/state/session' import {loadString, saveString} from '#/lib/storage' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {clamp} from '#/lib/numbers' +import {PROD_DEFAULT_FEED} from '#/lib/constants' type Props = NativeStackScreenProps<HomeTabNavigatorParams, 'Home'> export function HomeScreen(props: Props) { @@ -109,7 +110,9 @@ function HomeScreenReady({ const homeFeedParams = React.useMemo<FeedParams>(() => { return { mergeFeedEnabled: Boolean(preferences.feedViewPrefs.lab_mergeFeedEnabled), - mergeFeedSources: preferences.feeds.saved, + mergeFeedSources: preferences.feedViewPrefs.lab_mergeFeedEnabled + ? preferences.feeds.saved + : [PROD_DEFAULT_FEED('whats-hot')], } }, [preferences]) diff --git a/src/view/screens/Moderation.tsx b/src/view/screens/Moderation.tsx index 1bf8db2e0..96bb46cef 100644 --- a/src/view/screens/Moderation.tsx +++ b/src/view/screens/Moderation.tsx @@ -62,7 +62,7 @@ export function ModerationScreen({}: Props) { ]} testID="moderationScreen"> <ViewHeader title={_(msg`Moderation`)} showOnDesktop /> - <ScrollView> + <ScrollView contentContainerStyle={[styles.noBorder]}> <View style={styles.spacer} /> <TouchableOpacity testID="contentFilteringBtn" @@ -275,4 +275,10 @@ const styles = StyleSheet.create({ borderRadius: 30, marginRight: 12, }, + noBorder: { + borderBottomWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderTopWidth: 0, + }, }) diff --git a/src/view/screens/PreferencesExternalEmbeds.tsx b/src/view/screens/PreferencesExternalEmbeds.tsx new file mode 100644 index 000000000..24e7d56df --- /dev/null +++ b/src/view/screens/PreferencesExternalEmbeds.tsx @@ -0,0 +1,138 @@ +import React from 'react' +import {StyleSheet, View} from 'react-native' +import {useFocusEffect} from '@react-navigation/native' +import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types' +import {s} from 'lib/styles' +import {Text} from '../com/util/text/Text' +import {usePalette} from 'lib/hooks/usePalette' +import {useAnalytics} from 'lib/analytics/analytics' +import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' +import { + EmbedPlayerSource, + externalEmbedLabels, +} from '#/lib/strings/embed-player' +import {useSetMinimalShellMode} from '#/state/shell' +import {Trans} from '@lingui/macro' +import {ScrollView} from '../com/util/Views' +import { + useExternalEmbedsPrefs, + useSetExternalEmbedPref, +} from 'state/preferences' +import {ToggleButton} from 'view/com/util/forms/ToggleButton' +import {SimpleViewHeader} from '../com/util/SimpleViewHeader' + +type Props = NativeStackScreenProps< + CommonNavigatorParams, + 'PreferencesExternalEmbeds' +> +export function PreferencesExternalEmbeds({}: Props) { + const pal = usePalette('default') + const setMinimalShellMode = useSetMinimalShellMode() + const {screen} = useAnalytics() + const {isMobile} = useWebMediaQueries() + + useFocusEffect( + React.useCallback(() => { + screen('PreferencesExternalEmbeds') + setMinimalShellMode(false) + }, [screen, setMinimalShellMode]), + ) + + return ( + <View style={s.hContentRegion} testID="preferencesExternalEmbedsScreen"> + <SimpleViewHeader + showBackButton={isMobile} + style={[ + pal.border, + {borderBottomWidth: 1}, + !isMobile && {borderLeftWidth: 1, borderRightWidth: 1}, + ]}> + <View style={{flex: 1}}> + <Text type="title-lg" style={[pal.text, {fontWeight: 'bold'}]}> + <Trans>External Media Preferences</Trans> + </Text> + <Text style={pal.textLight}> + <Trans>Customize media from external sites.</Trans> + </Text> + </View> + </SimpleViewHeader> + <ScrollView + // @ts-ignore web only -prf + dataSet={{'stable-gutters': 1}} + contentContainerStyle={[pal.viewLight, {paddingBottom: 200}]}> + <View style={[pal.view]}> + <View style={styles.infoCard}> + <Text style={pal.text}> + <Trans> + External media may allow websites to collect information about + you and your device. No information is sent or requested until + you press the "play" button. + </Trans> + </Text> + </View> + </View> + <Text type="xl-bold" style={[pal.text, styles.heading]}> + Enable media players for + </Text> + {Object.entries(externalEmbedLabels).map(([key, label]) => ( + <PrefSelector + source={key as EmbedPlayerSource} + label={label} + key={key} + /> + ))} + </ScrollView> + </View> + ) +} + +function PrefSelector({ + source, + label, +}: { + source: EmbedPlayerSource + label: string +}) { + const pal = usePalette('default') + const setExternalEmbedPref = useSetExternalEmbedPref() + const sources = useExternalEmbedsPrefs() + + return ( + <View> + <View style={[pal.view, styles.toggleCard]}> + <ToggleButton + type="default-light" + label={label} + labelType="lg" + isSelected={sources?.[source] === 'show'} + onPress={() => + setExternalEmbedPref( + source, + sources?.[source] === 'show' ? 'hide' : 'show', + ) + } + /> + </View> + </View> + ) +} + +const styles = StyleSheet.create({ + heading: { + paddingHorizontal: 18, + paddingTop: 14, + paddingBottom: 14, + }, + spacer: { + height: 8, + }, + infoCard: { + paddingHorizontal: 20, + paddingVertical: 14, + }, + toggleCard: { + paddingVertical: 8, + paddingHorizontal: 6, + marginBottom: 1, + }, +}) diff --git a/src/view/screens/PreferencesHomeFeed.tsx b/src/view/screens/PreferencesHomeFeed.tsx index 20ef72923..874272831 100644 --- a/src/view/screens/PreferencesHomeFeed.tsx +++ b/src/view/screens/PreferencesHomeFeed.tsx @@ -29,6 +29,7 @@ function RepliesThresholdInput({ const pal = usePalette('default') const [value, setValue] = useState(initialValue) const {mutate: setFeedViewPref} = useSetFeedViewPreferencesMutation() + const preValue = React.useRef(initialValue) const save = React.useMemo( () => debounce( @@ -46,7 +47,12 @@ function RepliesThresholdInput({ <Slider value={value} onValueChange={(v: number | number[]) => { - const threshold = Math.floor(Array.isArray(v) ? v[0] : v) + let threshold = Array.isArray(v) ? v[0] : v + if (threshold > preValue.current) threshold = Math.floor(threshold) + else threshold = Math.ceil(threshold) + + preValue.current = threshold + setValue(threshold) save(threshold) }} diff --git a/src/view/screens/PreferencesThreads.tsx b/src/view/screens/PreferencesThreads.tsx index 73d941932..35a010b55 100644 --- a/src/view/screens/PreferencesThreads.tsx +++ b/src/view/screens/PreferencesThreads.tsx @@ -75,10 +75,16 @@ export function PreferencesThreads({navigation}: Props) { <RadioGroup type="default-light" items={[ - {key: 'oldest', label: 'Oldest replies first'}, - {key: 'newest', label: 'Newest replies first'}, - {key: 'most-likes', label: 'Most-liked replies first'}, - {key: 'random', label: 'Random (aka "Poster\'s Roulette")'}, + {key: 'oldest', label: _(msg`Oldest replies first`)}, + {key: 'newest', label: _(msg`Newest replies first`)}, + { + key: 'most-likes', + label: _(msg`Most-liked replies first`), + }, + { + key: 'random', + label: _(msg`Random (aka "Poster's Roulette")`), + }, ]} onSelect={key => setThreadViewPrefs({sort: key})} initialSelection={preferences?.threadViewPrefs?.sort} @@ -97,7 +103,7 @@ export function PreferencesThreads({navigation}: Props) { </Text> <ToggleButton type="default-light" - label={prioritizeFollowedUsers ? 'Yes' : 'No'} + label={prioritizeFollowedUsers ? _(msg`Yes`) : _(msg`No`)} isSelected={prioritizeFollowedUsers} onPress={() => setThreadViewPrefs({ @@ -120,7 +126,7 @@ export function PreferencesThreads({navigation}: Props) { </Text> <ToggleButton type="default-light" - label={treeViewEnabled ? 'Yes' : 'No'} + label={treeViewEnabled ? _(msg`Yes`) : _(msg`No`)} isSelected={treeViewEnabled} onPress={() => setThreadViewPrefs({ diff --git a/src/view/screens/SavedFeeds.tsx b/src/view/screens/SavedFeeds.tsx index bbac30689..8a16ffdf2 100644 --- a/src/view/screens/SavedFeeds.tsx +++ b/src/view/screens/SavedFeeds.tsx @@ -82,7 +82,7 @@ export function SavedFeeds({}: Props) { isTabletOrDesktop && styles.desktopContainer, ]}> <ViewHeader title={_(msg`Edit My Feeds`)} showOnDesktop showBorder /> - <ScrollView style={s.flex1}> + <ScrollView style={s.flex1} contentContainerStyle={[styles.noBorder]}> <View style={[pal.text, pal.border, styles.title]}> <Text type="title" style={pal.text}> <Trans>Pinned Feeds</Trans> @@ -288,7 +288,7 @@ function ListItem({ <FeedSourceCard key={feedUri} feedUri={feedUri} - style={styles.noBorder} + style={styles.noTopBorder} showSaveBtn showMinimalPlaceholder /> @@ -344,7 +344,7 @@ const styles = StyleSheet.create({ webArrowUpButton: { marginBottom: 10, }, - noBorder: { + noTopBorder: { borderTopWidth: 0, }, footerText: { @@ -352,4 +352,10 @@ const styles = StyleSheet.create({ paddingTop: 22, paddingBottom: 100, }, + noBorder: { + borderBottomWidth: 0, + borderRightWidth: 0, + borderLeftWidth: 0, + borderTopWidth: 0, + }, }) diff --git a/src/view/screens/Settings.tsx b/src/view/screens/Settings.tsx index f85ce44b2..d413e234f 100644 --- a/src/view/screens/Settings.tsx +++ b/src/view/screens/Settings.tsx @@ -431,7 +431,7 @@ export function SettingsScreen({}: Props) { <View style={[pal.view, styles.toggleCard]}> <ToggleButton type="default-light" - label="Require alt text before posting" + label={_(msg`Require alt text before posting`)} labelType="lg" isSelected={requireAltTextEnabled} onPress={() => setRequireAltTextEnabled(!requireAltTextEnabled)} @@ -575,6 +575,39 @@ export function SettingsScreen({}: Props) { <Trans>Moderation</Trans> </Text> </TouchableOpacity> + + <View style={styles.spacer20} /> + + <Text type="xl-bold" style={[pal.text, styles.heading]}> + <Trans>Privacy</Trans> + </Text> + + <TouchableOpacity + testID="externalEmbedsBtn" + style={[ + styles.linkCard, + pal.view, + isSwitchingAccounts && styles.dimmed, + ]} + onPress={ + isSwitchingAccounts + ? undefined + : () => navigation.navigate('PreferencesExternalEmbeds') + } + accessibilityRole="button" + accessibilityHint="" + accessibilityLabel={_(msg`Opens external embeds settings`)}> + <View style={[styles.iconContainer, pal.btn]}> + <FontAwesomeIcon + icon={['far', 'circle-play']} + style={pal.text as FontAwesomeIconStyle} + /> + </View> + <Text type="lg" style={pal.text}> + <Trans>External Media Preferences</Trans> + </Text> + </TouchableOpacity> + <View style={styles.spacer20} /> <Text type="xl-bold" style={[pal.text, styles.heading]}> |