forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {Fragment, useCallback} from 'react'
2import {View} from 'react-native'
3import {Trans} from '@lingui/react/macro'
4
5import {
6 type CommonNavigatorParams,
7 type NativeStackScreenProps,
8} from '#/lib/routes/types'
9import {
10 type EmbedPlayerSource,
11 embedPlayerSources,
12 externalEmbedLabels,
13} from '#/lib/strings/embed-player'
14import {
15 useExternalEmbedsPrefs,
16 useSetExternalEmbedPref,
17} from '#/state/preferences'
18import {atoms as a, native} from '#/alf'
19import {Admonition} from '#/components/Admonition'
20import * as Toggle from '#/components/forms/Toggle'
21import * as Layout from '#/components/Layout'
22import * as SettingsList from './components/SettingsList'
23
24type Props = NativeStackScreenProps<
25 CommonNavigatorParams,
26 'PreferencesExternalEmbeds'
27>
28export function ExternalMediaPreferencesScreen({}: Props) {
29 return (
30 <Layout.Screen testID="externalMediaPreferencesScreen">
31 <Layout.Header.Outer>
32 <Layout.Header.BackButton />
33 <Layout.Header.Content>
34 <Layout.Header.TitleText>
35 <Trans>External Media Preferences</Trans>
36 </Layout.Header.TitleText>
37 </Layout.Header.Content>
38 <Layout.Header.Slot />
39 </Layout.Header.Outer>
40 <Layout.Content>
41 <SettingsList.Container>
42 <SettingsList.Item>
43 <Admonition type="info" style={[a.flex_1]}>
44 <Trans>
45 External media may allow websites to collect information about
46 you and your device. No information is sent or requested until
47 you press the "play" button.
48 </Trans>
49 </Admonition>
50 </SettingsList.Item>
51 <SettingsList.Group iconInset={false}>
52 <SettingsList.ItemText>
53 <Trans>Enable media players for</Trans>
54 </SettingsList.ItemText>
55 <View style={[a.mt_sm, a.w_full]}>
56 {native(<SettingsList.Divider style={[a.my_0]} />)}
57 <PrefSelector source="all" label="All" />
58 <SettingsList.Divider />
59 {Object.entries(externalEmbedLabels)
60 // TODO: Remove special case when we disable the old integration.
61 .filter(([key]) => key !== 'tenor')
62 .map(([key, label]) => (
63 <Fragment key={key}>
64 <PrefSelector
65 source={key as EmbedPlayerSource}
66 label={label}
67 key={key}
68 />
69 {native(<SettingsList.Divider style={[a.my_0]} />)}
70 </Fragment>
71 ))}
72 </View>
73 </SettingsList.Group>
74 </SettingsList.Container>
75 </Layout.Content>
76 </Layout.Screen>
77 )
78}
79
80function PrefSelector({
81 source,
82 label,
83}: {
84 source: EmbedPlayerSource | 'all'
85 label: string
86}) {
87 const setExternalEmbedPref = useSetExternalEmbedPref()
88 const sources = useExternalEmbedsPrefs()
89
90 const isChecked =
91 source === 'all'
92 ? embedPlayerSources
93 .filter(key => key !== 'tenor')
94 .every(key => sources?.[key] === 'show')
95 : sources?.[source] === 'show'
96
97 const handleChange = useCallback(() => {
98 if (source === 'all') {
99 const newValue = isChecked ? 'hide' : 'show'
100 for (const key of embedPlayerSources) {
101 if (key !== 'tenor') {
102 setExternalEmbedPref(key, newValue)
103 }
104 }
105 } else {
106 setExternalEmbedPref(source, isChecked ? 'hide' : 'show')
107 }
108 }, [source, isChecked, setExternalEmbedPref])
109
110 return (
111 <Toggle.Item
112 name={label}
113 label={label}
114 type="checkbox"
115 value={isChecked}
116 onChange={handleChange}
117 style={[
118 a.flex_1,
119 a.py_md,
120 native([a.justify_between, a.flex_row_reverse]),
121 ]}>
122 <Toggle.Platform />
123 <Toggle.LabelText style={[a.text_md]}>{label}</Toggle.LabelText>
124 </Toggle.Item>
125 )
126}