diff options
Diffstat (limited to 'src/state')
-rw-r--r-- | src/state/modals/index.tsx | 8 | ||||
-rw-r--r-- | src/state/persisted/legacy.ts | 1 | ||||
-rw-r--r-- | src/state/persisted/schema.ts | 16 | ||||
-rw-r--r-- | src/state/preferences/external-embeds-prefs.tsx | 54 | ||||
-rw-r--r-- | src/state/preferences/index.tsx | 9 |
5 files changed, 87 insertions, 1 deletions
diff --git a/src/state/modals/index.tsx b/src/state/modals/index.tsx index 81a220d1b..8c32c472a 100644 --- a/src/state/modals/index.tsx +++ b/src/state/modals/index.tsx @@ -6,6 +6,7 @@ import {Image as RNImage} from 'react-native-image-crop-picker' import {ImageModel} from '#/state/models/media/image' import {GalleryModel} from '#/state/models/media/gallery' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' +import {EmbedPlayerSource} from '#/lib/strings/embed-player.ts' import {ThreadgateSetting} from '../queries/threadgate' export interface ConfirmModal { @@ -180,6 +181,12 @@ export interface LinkWarningModal { href: string } +export interface EmbedConsentModal { + name: 'embed-consent' + source: EmbedPlayerSource + onAccept: () => void +} + export type Modal = // Account | AddAppPasswordModal @@ -223,6 +230,7 @@ export type Modal = // Generic | ConfirmModal | LinkWarningModal + | EmbedConsentModal const ModalContext = React.createContext<{ isModalActive: boolean diff --git a/src/state/persisted/legacy.ts b/src/state/persisted/legacy.ts index cdb542f5a..334ef1d92 100644 --- a/src/state/persisted/legacy.ts +++ b/src/state/persisted/legacy.ts @@ -109,6 +109,7 @@ export function transform(legacy: Partial<LegacySchema>): Schema { step: legacy.onboarding?.step || defaults.onboarding.step, }, hiddenPosts: defaults.hiddenPosts, + externalEmbeds: defaults.externalEmbeds, } } diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts index 27b1f26bd..6a26cedae 100644 --- a/src/state/persisted/schema.ts +++ b/src/state/persisted/schema.ts @@ -1,6 +1,8 @@ import {z} from 'zod' import {deviceLocales} from '#/platform/detection' +const externalEmbedOptions = ['show', 'hide'] as const + // only data needed for rendering account page const accountSchema = z.object({ service: z.string(), @@ -30,6 +32,19 @@ export const schema = z.object({ appLanguage: z.string(), }), requireAltTextEnabled: z.boolean(), // should move to server + externalEmbeds: z + .object({ + giphy: z.enum(externalEmbedOptions).optional(), + tenor: z.enum(externalEmbedOptions).optional(), + youtube: z.enum(externalEmbedOptions).optional(), + youtubeShorts: z.enum(externalEmbedOptions).optional(), + twitch: z.enum(externalEmbedOptions).optional(), + vimeo: z.enum(externalEmbedOptions).optional(), + spotify: z.enum(externalEmbedOptions).optional(), + appleMusic: z.enum(externalEmbedOptions).optional(), + soundcloud: z.enum(externalEmbedOptions).optional(), + }) + .optional(), mutedThreads: z.array(z.string()), // should move to server invites: z.object({ copiedInvites: z.array(z.string()), @@ -60,6 +75,7 @@ export const defaults: Schema = { appLanguage: deviceLocales[0] || 'en', }, requireAltTextEnabled: false, + externalEmbeds: {}, mutedThreads: [], invites: { copiedInvites: [], diff --git a/src/state/preferences/external-embeds-prefs.tsx b/src/state/preferences/external-embeds-prefs.tsx new file mode 100644 index 000000000..0f6385fe8 --- /dev/null +++ b/src/state/preferences/external-embeds-prefs.tsx @@ -0,0 +1,54 @@ +import React from 'react' +import * as persisted from '#/state/persisted' +import {EmbedPlayerSource} from 'lib/strings/embed-player' + +type StateContext = persisted.Schema['externalEmbeds'] +type SetContext = (source: EmbedPlayerSource, value: 'show' | 'hide') => void + +const stateContext = React.createContext<StateContext>( + persisted.defaults.externalEmbeds, +) +const setContext = React.createContext<SetContext>({} as SetContext) + +export function Provider({children}: React.PropsWithChildren<{}>) { + const [state, setState] = React.useState(persisted.get('externalEmbeds')) + + const setStateWrapped = React.useCallback( + (source: EmbedPlayerSource, value: 'show' | 'hide') => { + setState(prev => { + persisted.write('externalEmbeds', { + ...prev, + [source]: value, + }) + + return { + ...prev, + [source]: value, + } + }) + }, + [setState], + ) + + React.useEffect(() => { + return persisted.onUpdate(() => { + setState(persisted.get('externalEmbeds')) + }) + }, [setStateWrapped]) + + return ( + <stateContext.Provider value={state}> + <setContext.Provider value={setStateWrapped}> + {children} + </setContext.Provider> + </stateContext.Provider> + ) +} + +export function useExternalEmbedsPrefs() { + return React.useContext(stateContext) +} + +export function useSetExternalEmbedPref() { + return React.useContext(setContext) +} diff --git a/src/state/preferences/index.tsx b/src/state/preferences/index.tsx index 5ec659031..cc2d9244c 100644 --- a/src/state/preferences/index.tsx +++ b/src/state/preferences/index.tsx @@ -2,19 +2,26 @@ import React from 'react' import {Provider as LanguagesProvider} from './languages' import {Provider as AltTextRequiredProvider} from '../preferences/alt-text-required' import {Provider as HiddenPostsProvider} from '../preferences/hidden-posts' +import {Provider as ExternalEmbedsProvider} from './external-embeds-prefs' export {useLanguagePrefs, useLanguagePrefsApi} from './languages' export { useRequireAltTextEnabled, useSetRequireAltTextEnabled, } from './alt-text-required' +export { + useExternalEmbedsPrefs, + useSetExternalEmbedPref, +} from './external-embeds-prefs' export * from './hidden-posts' export function Provider({children}: React.PropsWithChildren<{}>) { return ( <LanguagesProvider> <AltTextRequiredProvider> - <HiddenPostsProvider>{children}</HiddenPostsProvider> + <ExternalEmbedsProvider> + <HiddenPostsProvider>{children}</HiddenPostsProvider> + </ExternalEmbedsProvider> </AltTextRequiredProvider> </LanguagesProvider> ) |