Add disable autoplay preference and group related settings into a dedicated page (#3626)

* add autoplay preference

* group accessibility settings into a dedicated page

* fix gray background on web

* Put a11y first

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
zio/stable
Samuel Newman 2024-04-19 22:10:37 +01:00 committed by GitHub
parent ade2ea6172
commit 8b33ffdfb5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 263 additions and 82 deletions

View File

@ -190,6 +190,7 @@ func serve(cctx *cli.Context) error {
e.GET("/settings/saved-feeds", server.WebGeneric) e.GET("/settings/saved-feeds", server.WebGeneric)
e.GET("/settings/threads", server.WebGeneric) e.GET("/settings/threads", server.WebGeneric)
e.GET("/settings/external-embeds", server.WebGeneric) e.GET("/settings/external-embeds", server.WebGeneric)
e.GET("/settings/accessibility", server.WebGeneric)
e.GET("/sys/debug", server.WebGeneric) e.GET("/sys/debug", server.WebGeneric)
e.GET("/sys/debug-mod", server.WebGeneric) e.GET("/sys/debug-mod", server.WebGeneric)
e.GET("/sys/log", server.WebGeneric) e.GET("/sys/log", server.WebGeneric)

View File

@ -53,6 +53,7 @@ import {
setEmailConfirmationRequested, setEmailConfirmationRequested,
shouldRequestEmailConfirmation, shouldRequestEmailConfirmation,
} from './state/shell/reminders' } from './state/shell/reminders'
import {AccessibilitySettingsScreen} from './view/screens/AccessibilitySettings'
import {CommunityGuidelinesScreen} from './view/screens/CommunityGuidelines' import {CommunityGuidelinesScreen} from './view/screens/CommunityGuidelines'
import {CopyrightPolicyScreen} from './view/screens/CopyrightPolicy' import {CopyrightPolicyScreen} from './view/screens/CopyrightPolicy'
import {DebugModScreen} from './view/screens/DebugMod' import {DebugModScreen} from './view/screens/DebugMod'
@ -276,6 +277,14 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
requireAuth: true, requireAuth: true,
}} }}
/> />
<Stack.Screen
name="AccessibilitySettings"
getComponent={() => AccessibilitySettingsScreen}
options={{
title: title(msg`Accessibility Settings`),
requireAuth: true,
}}
/>
<Stack.Screen <Stack.Screen
name="Hashtag" name="Hashtag"
getComponent={() => HashtagScreen} getComponent={() => HashtagScreen}

View File

@ -35,6 +35,7 @@ export type CommonNavigatorParams = {
PreferencesFollowingFeed: undefined PreferencesFollowingFeed: undefined
PreferencesThreads: undefined PreferencesThreads: undefined
PreferencesExternalEmbeds: undefined PreferencesExternalEmbeds: undefined
AccessibilitySettings: undefined
Search: {q?: string} Search: {q?: string}
Hashtag: {tag: string; author?: string} Hashtag: {tag: string; author?: string}
} }

View File

@ -29,6 +29,7 @@ export const router = new Router({
PreferencesFollowingFeed: '/settings/following-feed', PreferencesFollowingFeed: '/settings/following-feed',
PreferencesThreads: '/settings/threads', PreferencesThreads: '/settings/threads',
PreferencesExternalEmbeds: '/settings/external-embeds', PreferencesExternalEmbeds: '/settings/external-embeds',
AccessibilitySettings: '/settings/accessibility',
SavedFeeds: '/settings/saved-feeds', SavedFeeds: '/settings/saved-feeds',
Support: '/support', Support: '/support',
PrivacyPolicy: '/support/privacy', PrivacyPolicy: '/support/privacy',

View File

@ -60,6 +60,7 @@ export const schema = z.object({
lastSelectedHomeFeed: z.string().optional(), lastSelectedHomeFeed: z.string().optional(),
pdsAddressHistory: z.array(z.string()).optional(), pdsAddressHistory: z.array(z.string()).optional(),
disableHaptics: z.boolean().optional(), disableHaptics: z.boolean().optional(),
disableAutoplay: z.boolean().optional(),
}) })
export type Schema = z.infer<typeof schema> export type Schema = z.infer<typeof schema>
@ -96,4 +97,5 @@ export const defaults: Schema = {
lastSelectedHomeFeed: undefined, lastSelectedHomeFeed: undefined,
pdsAddressHistory: [], pdsAddressHistory: [],
disableHaptics: false, disableHaptics: false,
disableAutoplay: false,
} }

View File

@ -0,0 +1,42 @@
import React from 'react'
import * as persisted from '#/state/persisted'
type StateContext = boolean
type SetContext = (v: boolean) => void
const stateContext = React.createContext<StateContext>(
Boolean(persisted.defaults.disableAutoplay),
)
const setContext = React.createContext<SetContext>((_: boolean) => {})
export function Provider({children}: {children: React.ReactNode}) {
const [state, setState] = React.useState(
Boolean(persisted.get('disableAutoplay')),
)
const setStateWrapped = React.useCallback(
(autoplayDisabled: persisted.Schema['disableAutoplay']) => {
setState(Boolean(autoplayDisabled))
persisted.write('disableAutoplay', autoplayDisabled)
},
[setState],
)
React.useEffect(() => {
return persisted.onUpdate(() => {
setState(Boolean(persisted.get('disableAutoplay')))
})
}, [setStateWrapped])
return (
<stateContext.Provider value={state}>
<setContext.Provider value={setStateWrapped}>
{children}
</setContext.Provider>
</stateContext.Provider>
)
}
export const useAutoplayDisabled = () => React.useContext(stateContext)
export const useSetAutoplayDisabled = () => React.useContext(setContext)

View File

@ -1,9 +1,10 @@
import React from 'react' import React from 'react'
import {Provider as AltTextRequiredProvider} from '../preferences/alt-text-required' import {Provider as AltTextRequiredProvider} from './alt-text-required'
import {Provider as HiddenPostsProvider} from '../preferences/hidden-posts' import {Provider as AutoplayProvider} from './autoplay'
import {Provider as DisableHapticsProvider} from './disable-haptics' import {Provider as DisableHapticsProvider} from './disable-haptics'
import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs' import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs'
import {Provider as HiddenPostsProvider} from './hidden-posts'
import {Provider as InAppBrowserProvider} from './in-app-browser' import {Provider as InAppBrowserProvider} from './in-app-browser'
import {Provider as LanguagesProvider} from './languages' import {Provider as LanguagesProvider} from './languages'
@ -11,6 +12,8 @@ export {
useRequireAltTextEnabled, useRequireAltTextEnabled,
useSetRequireAltTextEnabled, useSetRequireAltTextEnabled,
} from './alt-text-required' } from './alt-text-required'
export {useAutoplayDisabled, useSetAutoplayDisabled} from './autoplay'
export {useHapticsDisabled, useSetHapticsDisabled} from './disable-haptics'
export { export {
useExternalEmbedsPrefs, useExternalEmbedsPrefs,
useSetExternalEmbedPref, useSetExternalEmbedPref,
@ -26,7 +29,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
<ExternalEmbedsProvider> <ExternalEmbedsProvider>
<HiddenPostsProvider> <HiddenPostsProvider>
<InAppBrowserProvider> <InAppBrowserProvider>
<DisableHapticsProvider>{children}</DisableHapticsProvider> <DisableHapticsProvider>
<AutoplayProvider>{children}</AutoplayProvider>
</DisableHapticsProvider>
</InAppBrowserProvider> </InAppBrowserProvider>
</HiddenPostsProvider> </HiddenPostsProvider>
</ExternalEmbedsProvider> </ExternalEmbedsProvider>

View File

@ -1,63 +1,72 @@
import {library} from '@fortawesome/fontawesome-svg-core' import {library} from '@fortawesome/fontawesome-svg-core'
import {faAddressCard} from '@fortawesome/free-regular-svg-icons' import {faAddressCard} from '@fortawesome/free-regular-svg-icons'
import {faBell as farBell} from '@fortawesome/free-regular-svg-icons/faBell'
import {faBookmark as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark'
import {faCalendar as farCalendar} from '@fortawesome/free-regular-svg-icons/faCalendar'
import {faCircle} from '@fortawesome/free-regular-svg-icons/faCircle'
import {faCircleCheck as farCircleCheck} from '@fortawesome/free-regular-svg-icons/faCircleCheck'
import {faCirclePlay} from '@fortawesome/free-regular-svg-icons/faCirclePlay'
import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
import {faClone as farClone} from '@fortawesome/free-regular-svg-icons/faClone'
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
import {faComments} from '@fortawesome/free-regular-svg-icons/faComments'
import {faCompass} from '@fortawesome/free-regular-svg-icons/faCompass'
import {faEyeSlash as farEyeSlash} from '@fortawesome/free-regular-svg-icons/faEyeSlash'
import {faFaceSmile} from '@fortawesome/free-regular-svg-icons/faFaceSmile'
import {faFloppyDisk} from '@fortawesome/free-regular-svg-icons/faFloppyDisk'
import {faHand as farHand} from '@fortawesome/free-regular-svg-icons/faHand'
import {faHeart} from '@fortawesome/free-regular-svg-icons/faHeart'
import {faImage as farImage} from '@fortawesome/free-regular-svg-icons/faImage'
import {faMessage} from '@fortawesome/free-regular-svg-icons/faMessage'
import {faPaste} from '@fortawesome/free-regular-svg-icons/faPaste'
import {faSquare} from '@fortawesome/free-regular-svg-icons/faSquare'
import {faSquareCheck} from '@fortawesome/free-regular-svg-icons/faSquareCheck'
import {faSquarePlus} from '@fortawesome/free-regular-svg-icons/faSquarePlus'
import {faTrashCan} from '@fortawesome/free-regular-svg-icons/faTrashCan'
import {faUser} from '@fortawesome/free-regular-svg-icons/faUser'
import {faFlask} from '@fortawesome/free-solid-svg-icons'
import {faUniversalAccess} from '@fortawesome/free-solid-svg-icons'
import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown' import {faAngleDown} from '@fortawesome/free-solid-svg-icons/faAngleDown'
import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft' import {faAngleLeft} from '@fortawesome/free-solid-svg-icons/faAngleLeft'
import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight' import {faAngleRight} from '@fortawesome/free-solid-svg-icons/faAngleRight'
import {faAngleUp} from '@fortawesome/free-solid-svg-icons/faAngleUp' import {faAngleUp} from '@fortawesome/free-solid-svg-icons/faAngleUp'
import {faArrowDown} from '@fortawesome/free-solid-svg-icons/faArrowDown'
import {faArrowLeft} from '@fortawesome/free-solid-svg-icons/faArrowLeft' import {faArrowLeft} from '@fortawesome/free-solid-svg-icons/faArrowLeft'
import {faArrowRight} from '@fortawesome/free-solid-svg-icons/faArrowRight' import {faArrowRight} from '@fortawesome/free-solid-svg-icons/faArrowRight'
import {faArrowUp} from '@fortawesome/free-solid-svg-icons/faArrowUp'
import {faArrowDown} from '@fortawesome/free-solid-svg-icons/faArrowDown'
import {faArrowRightFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowRightFromBracket' import {faArrowRightFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowRightFromBracket'
import {faArrowRotateLeft} from '@fortawesome/free-solid-svg-icons/faArrowRotateLeft'
import {faArrowsRotate} from '@fortawesome/free-solid-svg-icons/faArrowsRotate'
import {faArrowTrendUp} from '@fortawesome/free-solid-svg-icons/faArrowTrendUp'
import {faArrowUp} from '@fortawesome/free-solid-svg-icons/faArrowUp'
import {faArrowUpFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowUpFromBracket' import {faArrowUpFromBracket} from '@fortawesome/free-solid-svg-icons/faArrowUpFromBracket'
import {faArrowUpRightFromSquare} from '@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare' import {faArrowUpRightFromSquare} from '@fortawesome/free-solid-svg-icons/faArrowUpRightFromSquare'
import {faArrowRotateLeft} from '@fortawesome/free-solid-svg-icons/faArrowRotateLeft'
import {faArrowTrendUp} from '@fortawesome/free-solid-svg-icons/faArrowTrendUp'
import {faArrowsRotate} from '@fortawesome/free-solid-svg-icons/faArrowsRotate'
import {faAt} from '@fortawesome/free-solid-svg-icons/faAt' import {faAt} from '@fortawesome/free-solid-svg-icons/faAt'
import {faBars} from '@fortawesome/free-solid-svg-icons/faBars'
import {faBan} from '@fortawesome/free-solid-svg-icons/faBan' import {faBan} from '@fortawesome/free-solid-svg-icons/faBan'
import {faBars} from '@fortawesome/free-solid-svg-icons/faBars'
import {faBell} from '@fortawesome/free-solid-svg-icons/faBell' import {faBell} from '@fortawesome/free-solid-svg-icons/faBell'
import {faBell as farBell} from '@fortawesome/free-regular-svg-icons/faBell'
import {faBookmark} from '@fortawesome/free-solid-svg-icons/faBookmark' import {faBookmark} from '@fortawesome/free-solid-svg-icons/faBookmark'
import {faBookmark as farBookmark} from '@fortawesome/free-regular-svg-icons/faBookmark'
import {faCalendar as farCalendar} from '@fortawesome/free-regular-svg-icons/faCalendar'
import {faCamera} from '@fortawesome/free-solid-svg-icons/faCamera' import {faCamera} from '@fortawesome/free-solid-svg-icons/faCamera'
import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck' import {faCheck} from '@fortawesome/free-solid-svg-icons/faCheck'
import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown'
import {faChevronRight} from '@fortawesome/free-solid-svg-icons/faChevronRight' import {faChevronRight} from '@fortawesome/free-solid-svg-icons/faChevronRight'
import {faCircle} from '@fortawesome/free-regular-svg-icons/faCircle'
import {faCircleCheck as farCircleCheck} from '@fortawesome/free-regular-svg-icons/faCircleCheck'
import {faCircleCheck} from '@fortawesome/free-solid-svg-icons/faCircleCheck' import {faCircleCheck} from '@fortawesome/free-solid-svg-icons/faCircleCheck'
import {faCircleDot} from '@fortawesome/free-solid-svg-icons/faCircleDot' import {faCircleDot} from '@fortawesome/free-solid-svg-icons/faCircleDot'
import {faCircleExclamation} from '@fortawesome/free-solid-svg-icons/faCircleExclamation' import {faCircleExclamation} from '@fortawesome/free-solid-svg-icons/faCircleExclamation'
import {faCirclePlay} from '@fortawesome/free-regular-svg-icons/faCirclePlay'
import {faCircleUser} from '@fortawesome/free-regular-svg-icons/faCircleUser'
import {faClone} from '@fortawesome/free-solid-svg-icons/faClone' import {faClone} from '@fortawesome/free-solid-svg-icons/faClone'
import {faClone as farClone} from '@fortawesome/free-regular-svg-icons/faClone'
import {faComment} from '@fortawesome/free-regular-svg-icons/faComment'
import {faCommentSlash} from '@fortawesome/free-solid-svg-icons/faCommentSlash' import {faCommentSlash} from '@fortawesome/free-solid-svg-icons/faCommentSlash'
import {faComments} from '@fortawesome/free-regular-svg-icons/faComments'
import {faCompass} from '@fortawesome/free-regular-svg-icons/faCompass'
import {faDownload} from '@fortawesome/free-solid-svg-icons/faDownload' import {faDownload} from '@fortawesome/free-solid-svg-icons/faDownload'
import {faEllipsis} from '@fortawesome/free-solid-svg-icons/faEllipsis' import {faEllipsis} from '@fortawesome/free-solid-svg-icons/faEllipsis'
import {faEnvelope} from '@fortawesome/free-solid-svg-icons/faEnvelope' import {faEnvelope} from '@fortawesome/free-solid-svg-icons/faEnvelope'
import {faExclamation} from '@fortawesome/free-solid-svg-icons/faExclamation' import {faExclamation} from '@fortawesome/free-solid-svg-icons/faExclamation'
import {faEye} from '@fortawesome/free-solid-svg-icons/faEye' import {faEye} from '@fortawesome/free-solid-svg-icons/faEye'
import {faEyeSlash as farEyeSlash} from '@fortawesome/free-regular-svg-icons/faEyeSlash' import {faFilter} from '@fortawesome/free-solid-svg-icons/faFilter'
import {faFaceSmile} from '@fortawesome/free-regular-svg-icons/faFaceSmile'
import {faFire} from '@fortawesome/free-solid-svg-icons/faFire' import {faFire} from '@fortawesome/free-solid-svg-icons/faFire'
import {faFlask} from '@fortawesome/free-solid-svg-icons'
import {faFloppyDisk} from '@fortawesome/free-regular-svg-icons/faFloppyDisk'
import {faGear} from '@fortawesome/free-solid-svg-icons/faGear' import {faGear} from '@fortawesome/free-solid-svg-icons/faGear'
import {faGlobe} from '@fortawesome/free-solid-svg-icons/faGlobe' import {faGlobe} from '@fortawesome/free-solid-svg-icons/faGlobe'
import {faHand} from '@fortawesome/free-solid-svg-icons/faHand' import {faHand} from '@fortawesome/free-solid-svg-icons/faHand'
import {faHand as farHand} from '@fortawesome/free-regular-svg-icons/faHand'
import {faHashtag} from '@fortawesome/free-solid-svg-icons/faHashtag' import {faHashtag} from '@fortawesome/free-solid-svg-icons/faHashtag'
import {faHeart} from '@fortawesome/free-regular-svg-icons/faHeart'
import {faHeart as fasHeart} from '@fortawesome/free-solid-svg-icons/faHeart' import {faHeart as fasHeart} from '@fortawesome/free-solid-svg-icons/faHeart'
import {faHouse} from '@fortawesome/free-solid-svg-icons/faHouse' import {faHouse} from '@fortawesome/free-solid-svg-icons/faHouse'
import {faImage as farImage} from '@fortawesome/free-regular-svg-icons/faImage'
import {faImage} from '@fortawesome/free-solid-svg-icons/faImage' import {faImage} from '@fortawesome/free-solid-svg-icons/faImage'
import {faInfo} from '@fortawesome/free-solid-svg-icons/faInfo' import {faInfo} from '@fortawesome/free-solid-svg-icons/faInfo'
import {faLanguage} from '@fortawesome/free-solid-svg-icons/faLanguage' import {faLanguage} from '@fortawesome/free-solid-svg-icons/faLanguage'
@ -66,10 +75,8 @@ import {faList} from '@fortawesome/free-solid-svg-icons/faList'
import {faListUl} from '@fortawesome/free-solid-svg-icons/faListUl' import {faListUl} from '@fortawesome/free-solid-svg-icons/faListUl'
import {faLock} from '@fortawesome/free-solid-svg-icons/faLock' import {faLock} from '@fortawesome/free-solid-svg-icons/faLock'
import {faMagnifyingGlass} from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass' import {faMagnifyingGlass} from '@fortawesome/free-solid-svg-icons/faMagnifyingGlass'
import {faMessage} from '@fortawesome/free-regular-svg-icons/faMessage'
import {faNoteSticky} from '@fortawesome/free-solid-svg-icons/faNoteSticky' import {faNoteSticky} from '@fortawesome/free-solid-svg-icons/faNoteSticky'
import {faPause} from '@fortawesome/free-solid-svg-icons/faPause' import {faPause} from '@fortawesome/free-solid-svg-icons/faPause'
import {faPaste} from '@fortawesome/free-regular-svg-icons/faPaste'
import {faPen} from '@fortawesome/free-solid-svg-icons/faPen' import {faPen} from '@fortawesome/free-solid-svg-icons/faPen'
import {faPenNib} from '@fortawesome/free-solid-svg-icons/faPenNib' import {faPenNib} from '@fortawesome/free-solid-svg-icons/faPenNib'
import {faPenToSquare} from '@fortawesome/free-solid-svg-icons/faPenToSquare' import {faPenToSquare} from '@fortawesome/free-solid-svg-icons/faPenToSquare'
@ -87,23 +94,16 @@ import {faShareFromSquare} from '@fortawesome/free-solid-svg-icons/faShareFromSq
import {faShield} from '@fortawesome/free-solid-svg-icons/faShield' import {faShield} from '@fortawesome/free-solid-svg-icons/faShield'
import {faSignal} from '@fortawesome/free-solid-svg-icons/faSignal' import {faSignal} from '@fortawesome/free-solid-svg-icons/faSignal'
import {faSliders} from '@fortawesome/free-solid-svg-icons/faSliders' import {faSliders} from '@fortawesome/free-solid-svg-icons/faSliders'
import {faSquare} from '@fortawesome/free-regular-svg-icons/faSquare'
import {faSquareCheck} from '@fortawesome/free-regular-svg-icons/faSquareCheck'
import {faSquarePlus} from '@fortawesome/free-regular-svg-icons/faSquarePlus'
import {faThumbtack} from '@fortawesome/free-solid-svg-icons/faThumbtack' import {faThumbtack} from '@fortawesome/free-solid-svg-icons/faThumbtack'
import {faTicket} from '@fortawesome/free-solid-svg-icons/faTicket' import {faTicket} from '@fortawesome/free-solid-svg-icons/faTicket'
import {faTrashCan} from '@fortawesome/free-regular-svg-icons/faTrashCan'
import {faUser} from '@fortawesome/free-regular-svg-icons/faUser'
import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers'
import {faUserCheck} from '@fortawesome/free-solid-svg-icons/faUserCheck' import {faUserCheck} from '@fortawesome/free-solid-svg-icons/faUserCheck'
import {faUserSlash} from '@fortawesome/free-solid-svg-icons/faUserSlash'
import {faUserPlus} from '@fortawesome/free-solid-svg-icons/faUserPlus' import {faUserPlus} from '@fortawesome/free-solid-svg-icons/faUserPlus'
import {faUserXmark} from '@fortawesome/free-solid-svg-icons/faUserXmark' import {faUsers} from '@fortawesome/free-solid-svg-icons/faUsers'
import {faUserSlash} from '@fortawesome/free-solid-svg-icons/faUserSlash'
import {faUsersSlash} from '@fortawesome/free-solid-svg-icons/faUsersSlash' import {faUsersSlash} from '@fortawesome/free-solid-svg-icons/faUsersSlash'
import {faUserXmark} from '@fortawesome/free-solid-svg-icons/faUserXmark'
import {faX} from '@fortawesome/free-solid-svg-icons/faX' import {faX} from '@fortawesome/free-solid-svg-icons/faX'
import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark' import {faXmark} from '@fortawesome/free-solid-svg-icons/faXmark'
import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown'
import {faFilter} from '@fortawesome/free-solid-svg-icons/faFilter'
library.add( library.add(
faAddressCard, faAddressCard,
@ -196,6 +196,7 @@ library.add(
faSquare, faSquare,
faSquareCheck, faSquareCheck,
faSquarePlus, faSquarePlus,
faUniversalAccess,
faUser, faUser,
faUsers, faUsers,
faUserCheck, faUserCheck,

View File

@ -0,0 +1,132 @@
import React from 'react'
import {StyleSheet, View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useFocusEffect} from '@react-navigation/native'
import {isNative} from '#/platform/detection'
import {useSetMinimalShellMode} from '#/state/shell'
import {useAnalytics} from 'lib/analytics/analytics'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
import {s} from 'lib/styles'
import {
useAutoplayDisabled,
useHapticsDisabled,
useRequireAltTextEnabled,
useSetAutoplayDisabled,
useSetHapticsDisabled,
useSetRequireAltTextEnabled,
} from 'state/preferences'
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
import {SimpleViewHeader} from '../com/util/SimpleViewHeader'
import {Text} from '../com/util/text/Text'
import {ScrollView} from '../com/util/Views'
type Props = NativeStackScreenProps<
CommonNavigatorParams,
'AccessibilitySettings'
>
export function AccessibilitySettingsScreen({}: Props) {
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
const {screen} = useAnalytics()
const {isMobile} = useWebMediaQueries()
const {_} = useLingui()
const requireAltTextEnabled = useRequireAltTextEnabled()
const setRequireAltTextEnabled = useSetRequireAltTextEnabled()
const autoplayDisabled = useAutoplayDisabled()
const setAutoplayDisabled = useSetAutoplayDisabled()
const hapticsDisabled = useHapticsDisabled()
const setHapticsDisabled = useSetHapticsDisabled()
useFocusEffect(
React.useCallback(() => {
screen('PreferencesExternalEmbeds')
setMinimalShellMode(false)
}, [screen, setMinimalShellMode]),
)
return (
<View style={s.hContentRegion} testID="accessibilitySettingsScreen">
<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>Accessibility Settings</Trans>
</Text>
</View>
</SimpleViewHeader>
<ScrollView
// @ts-ignore web only -prf
dataSet={{'stable-gutters': 1}}
style={s.flex1}
contentContainerStyle={[
s.flex1,
{paddingBottom: 200},
isMobile && pal.viewLight,
]}>
<Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Alt text</Trans>
</Text>
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label={_(msg`Require alt text before posting`)}
labelType="lg"
isSelected={requireAltTextEnabled}
onPress={() => setRequireAltTextEnabled(!requireAltTextEnabled)}
/>
</View>
<Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Media</Trans>
</Text>
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label={_(msg`Disable autoplay for GIFs`)}
labelType="lg"
isSelected={autoplayDisabled}
onPress={() => setAutoplayDisabled(!autoplayDisabled)}
/>
</View>
{isNative && (
<>
<Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Haptics</Trans>
</Text>
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label={_(msg`Disable haptic feedback`)}
labelType="lg"
isSelected={hapticsDisabled}
onPress={() => setHapticsDisabled(!hapticsDisabled)}
/>
</View>
</>
)}
</ScrollView>
</View>
)
}
const styles = StyleSheet.create({
heading: {
paddingHorizontal: 18,
paddingTop: 14,
paddingBottom: 6,
},
toggleCard: {
paddingVertical: 8,
paddingHorizontal: 6,
marginBottom: 1,
},
})

View File

@ -20,14 +20,10 @@ import {useLingui} from '@lingui/react'
import {useFocusEffect, useNavigation} from '@react-navigation/native' import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {isIOS, isNative} from '#/platform/detection' import {isNative} from '#/platform/detection'
import {useModalControls} from '#/state/modals' import {useModalControls} from '#/state/modals'
import {clearLegacyStorage} from '#/state/persisted/legacy' import {clearLegacyStorage} from '#/state/persisted/legacy'
import {clear as clearStorage} from '#/state/persisted/store' import {clear as clearStorage} from '#/state/persisted/store'
import {
useRequireAltTextEnabled,
useSetRequireAltTextEnabled,
} from '#/state/preferences'
import { import {
useInAppBrowser, useInAppBrowser,
useSetInAppBrowser, useSetInAppBrowser,
@ -56,10 +52,6 @@ import {makeProfileLink} from 'lib/routes/links'
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
import {NavigationProp} from 'lib/routes/types' import {NavigationProp} from 'lib/routes/types'
import {colors, s} from 'lib/styles' import {colors, s} from 'lib/styles'
import {
useHapticsDisabled,
useSetHapticsDisabled,
} from 'state/preferences/disable-haptics'
import {AccountDropdownBtn} from 'view/com/util/AccountDropdownBtn' import {AccountDropdownBtn} from 'view/com/util/AccountDropdownBtn'
import {SelectableBtn} from 'view/com/util/forms/SelectableBtn' import {SelectableBtn} from 'view/com/util/forms/SelectableBtn'
import {ToggleButton} from 'view/com/util/forms/ToggleButton' import {ToggleButton} from 'view/com/util/forms/ToggleButton'
@ -162,12 +154,8 @@ export function SettingsScreen({}: Props) {
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const requireAltTextEnabled = useRequireAltTextEnabled()
const setRequireAltTextEnabled = useSetRequireAltTextEnabled()
const inAppBrowserPref = useInAppBrowser() const inAppBrowserPref = useInAppBrowser()
const setUseInAppBrowser = useSetInAppBrowser() const setUseInAppBrowser = useSetInAppBrowser()
const isHapticsDisabled = useHapticsDisabled()
const setHapticsDisabled = useSetHapticsDisabled()
const onboardingDispatch = useOnboardingDispatch() const onboardingDispatch = useOnboardingDispatch()
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {isMobile} = useWebMediaQueries() const {isMobile} = useWebMediaQueries()
@ -282,6 +270,10 @@ export function SettingsScreen({}: Props) {
navigation.navigate('SavedFeeds') navigation.navigate('SavedFeeds')
}, [navigation]) }, [navigation])
const onPressAccessibilitySettings = React.useCallback(() => {
navigation.navigate('AccessibilitySettings')
}, [navigation])
const onPressStatusPage = React.useCallback(() => { const onPressStatusPage = React.useCallback(() => {
Linking.openURL(STATUS_PAGE_URL) Linking.openURL(STATUS_PAGE_URL)
}, []) }, [])
@ -318,7 +310,7 @@ export function SettingsScreen({}: Props) {
</View> </View>
</SimpleViewHeader> </SimpleViewHeader>
<ScrollView <ScrollView
style={[s.hContentRegion]} style={s.hContentRegion}
contentContainerStyle={isMobile && pal.viewLight} contentContainerStyle={isMobile && pal.viewLight}
scrollIndicatorInsets={{right: 1}} scrollIndicatorInsets={{right: 1}}
// @ts-ignore web only -prf // @ts-ignore web only -prf
@ -417,21 +409,6 @@ export function SettingsScreen({}: Props) {
<View style={styles.spacer20} /> <View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Accessibility</Trans>
</Text>
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label={_(msg`Require alt text before posting`)}
labelType="lg"
isSelected={requireAltTextEnabled}
onPress={() => setRequireAltTextEnabled(!requireAltTextEnabled)}
/>
</View>
<View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}> <Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Appearance</Trans> <Trans>Appearance</Trans>
</Text> </Text>
@ -492,6 +469,29 @@ export function SettingsScreen({}: Props) {
<Text type="xl-bold" style={[pal.text, styles.heading]}> <Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Basics</Trans> <Trans>Basics</Trans>
</Text> </Text>
<TouchableOpacity
testID="accessibilitySettingsBtn"
style={[
styles.linkCard,
pal.view,
isSwitchingAccounts && styles.dimmed,
]}
onPress={
isSwitchingAccounts ? undefined : onPressAccessibilitySettings
}
accessibilityRole="button"
accessibilityLabel={_(msg`Accessibility settings`)}
accessibilityHint={_(msg`Opens accessibility settings`)}>
<View style={[styles.iconContainer, pal.btn]}>
<FontAwesomeIcon
icon="universal-access"
style={pal.text as FontAwesomeIconStyle}
/>
</View>
<Text type="lg" style={pal.text}>
<Trans>Accessibility</Trans>
</Text>
</TouchableOpacity>
<TouchableOpacity <TouchableOpacity
testID="preferencesHomeFeedButton" testID="preferencesHomeFeedButton"
style={[ style={[
@ -689,19 +689,6 @@ export function SettingsScreen({}: Props) {
/> />
</View> </View>
)} )}
{isNative && (
<View style={[pal.view, styles.toggleCard]}>
<ToggleButton
type="default-light"
label={
isIOS ? _(msg`Disable haptics`) : _(msg`Disable vibrations`)
}
labelType="lg"
isSelected={isHapticsDisabled}
onPress={() => setHapticsDisabled(!isHapticsDisabled)}
/>
</View>
)}
<View style={styles.spacer20} /> <View style={styles.spacer20} />
<Text type="xl-bold" style={[pal.text, styles.heading]}> <Text type="xl-bold" style={[pal.text, styles.heading]}>
<Trans>Account</Trans> <Trans>Account</Trans>