From 3bbf735c1b34060d8916d8d18cdbdac7ec854295 Mon Sep 17 00:00:00 2001 From: Ewan Date: Fri, 02 Jan 2026 05:25:50 +0000 Subject: [PATCH] feat: allow users to choose post terminology (skeet/post/spell) --- src/screens/Settings/DeerSettings.tsx | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/state/persisted/schema.ts | 2 ++ src/state/preferences/index.tsx | 9 ++++++++- src/state/preferences/terminology-preference.tsx | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 file(s) changed, 126 insertion(s)(+), 1 deletion(s)(-) diff --git a/src/screens/Settings/DeerSettings.tsx b/src/screens/Settings/DeerSettings.tsx --- a/src/screens/Settings/DeerSettings.tsx +++ b/src/screens/Settings/DeerSettings.tsx @@ -81,6 +81,10 @@ useShowExternalShareButtons, } from '#/state/preferences/external-share-buttons' import { + useSetTerminologyPreference, + useTerminologyPreference, +} from '#/state/preferences/terminology-preference' +import { useHideFeedsPromoTab, useSetHideFeedsPromoTab, } from '#/state/preferences/hide-feeds-promo-tab' @@ -467,6 +471,9 @@ const showLinkInHandle = useShowLinkInHandle() const setShowLinkInHandle = useSetShowLinkInHandle() + const terminologyPreference = useTerminologyPreference() + const setTerminologyPreference = useSetTerminologyPreference() + const [gates, setGatesView] = useState(Object.assign({ alt_share_icon: false, debug_show_feedcontext: false, @@ -651,6 +658,63 @@ {customAppViewDid && _(` Currently ${customAppViewDid}`)} + + + + + + Terminology + + + + + + + Choose your preferred terminology for posts throughout the app. + + + + + + setTerminologyPreference('skeet')} + style={[a.w_full]}> + + Use "skeet(s)" + + + + + + + setTerminologyPreference('post')} + style={[a.w_full]}> + + Use "post(s)" + + + + + + + setTerminologyPreference('spell')} + style={[a.w_full]}> + + Use "spell(s)" + + + diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts --- a/src/state/persisted/schema.ts +++ b/src/state/persisted/schema.ts @@ -169,6 +169,7 @@ hideUnreplyablePosts: z.boolean().optional(), showExternalShareButtons: z.boolean().optional(), + terminologyPreference: z.enum(['skeet', 'post', 'spell']).optional(), /** @deprecated */ mutedThreads: z.array(z.string()), @@ -272,6 +273,7 @@ highQualityImages: false, hideUnreplyablePosts: false, showExternalShareButtons: false, + terminologyPreference: 'skeet', } export function tryParse(rawData: string): Schema | undefined { diff --git a/src/state/preferences/index.tsx b/src/state/preferences/index.tsx --- a/src/state/preferences/index.tsx +++ b/src/state/preferences/index.tsx @@ -37,6 +37,7 @@ import {Provider as RepostCarouselProvider} from './repost-carousel-enabled' import {Provider as ShowLinkInHandleProvider} from './show-link-in-handle' import {Provider as SubtitlesProvider} from './subtitles' +import {Provider as TerminologyPreferenceProvider} from './terminology-preference' import {Provider as TrendingSettingsProvider} from './trending' import {Provider as UsedStarterPacksProvider} from './used-starter-packs' @@ -59,6 +60,10 @@ export {useLabelDefinitions} from './label-defs' export {useLanguagePrefs, useLanguagePrefsApi} from './languages' export {useSetSubtitlesEnabled, useSubtitlesEnabled} from './subtitles' +export { + useTerminologyPreference, + useSetTerminologyPreference, +} from './terminology-preference' export function Provider({children}: React.PropsWithChildren<{}>) { return ( @@ -101,7 +106,9 @@ - {children} + + {children} + diff --git a/src/state/preferences/terminology-preference.tsx b/src/state/preferences/terminology-preference.tsx new file mode 100644 --- /dev/null +++ b/src/state/preferences/terminology-preference.tsx @@ -0,0 +1,52 @@ +import React from 'react' + +import * as persisted from '#/state/persisted' + +type StateContext = persisted.Schema['terminologyPreference'] +type SetContext = (v: persisted.Schema['terminologyPreference']) => void + +const stateContext = React.createContext( + persisted.defaults.terminologyPreference, +) +const setContext = React.createContext( + (_: persisted.Schema['terminologyPreference']) => {}, +) + +export function Provider({children}: React.PropsWithChildren<{}>) { + const [state, setState] = React.useState( + persisted.get('terminologyPreference'), + ) + + const setStateWrapped = React.useCallback( + (terminologyPreference: persisted.Schema['terminologyPreference']) => { + setState(terminologyPreference) + persisted.write('terminologyPreference', terminologyPreference) + }, + [setState], + ) + + React.useEffect(() => { + return persisted.onUpdate( + 'terminologyPreference', + nextTerminologyPreference => { + setState(nextTerminologyPreference) + }, + ) + }, [setStateWrapped]) + + return ( + + + {children} + + + ) +} + +export function useTerminologyPreference() { + return React.useContext(stateContext) +} + +export function useSetTerminologyPreference() { + return React.useContext(setContext) +} -- tangled.sh