forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {useCallback, useMemo} from 'react'
2import {View} from 'react-native'
3import {msg, Trans} from '@lingui/macro'
4import {useLingui} from '@lingui/react'
5
6import {APP_LANGUAGES, LANGUAGES} from '#/lib/../locale/languages'
7import {
8 type CommonNavigatorParams,
9 type NativeStackScreenProps,
10} from '#/lib/routes/types'
11import {languageName, sanitizeAppLanguageSetting} from '#/locale/helpers'
12import {useModalControls} from '#/state/modals'
13import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences'
14import {atoms as a, useTheme, web} from '#/alf'
15import {Button, ButtonIcon, ButtonText} from '#/components/Button'
16import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check'
17import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/Plus'
18import * as Layout from '#/components/Layout'
19import * as Select from '#/components/Select'
20import {Text} from '#/components/Typography'
21import * as SettingsList from './components/SettingsList'
22
23const DEDUPED_LANGUAGES = LANGUAGES.filter(
24 (lang, i, arr) =>
25 lang.code2 && arr.findIndex(l => l.code2 === lang.code2) === i,
26)
27
28type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'>
29export function LanguageSettingsScreen({}: Props) {
30 const {_} = useLingui()
31 const langPrefs = useLanguagePrefs()
32 const setLangPrefs = useLanguagePrefsApi()
33 const t = useTheme()
34
35 const {openModal} = useModalControls()
36
37 const onPressContentLanguages = useCallback(() => {
38 openModal({name: 'content-languages-settings'})
39 }, [openModal])
40
41 const onChangePrimaryLanguage = useCallback(
42 (value: string) => {
43 if (!value) return
44 if (langPrefs.primaryLanguage !== value) {
45 setLangPrefs.setPrimaryLanguage(value)
46 }
47 },
48 [langPrefs, setLangPrefs],
49 )
50
51 const onChangeAppLanguage = useCallback(
52 (value: string) => {
53 if (!value) return
54 if (langPrefs.appLanguage !== value) {
55 setLangPrefs.setAppLanguage(sanitizeAppLanguageSetting(value))
56 }
57 },
58 [langPrefs, setLangPrefs],
59 )
60
61 const myLanguages = useMemo(() => {
62 return (
63 langPrefs.contentLanguages
64 .map(lang => LANGUAGES.find(l => l.code2 === lang))
65 .filter(Boolean)
66 // @ts-ignore
67 .map(l => languageName(l, langPrefs.appLanguage))
68 .join(', ')
69 )
70 }, [langPrefs.appLanguage, langPrefs.contentLanguages])
71
72 return (
73 <Layout.Screen testID="PreferencesLanguagesScreen">
74 <Layout.Header.Outer>
75 <Layout.Header.BackButton />
76 <Layout.Header.Content>
77 <Layout.Header.TitleText>
78 <Trans>Languages</Trans>
79 </Layout.Header.TitleText>
80 </Layout.Header.Content>
81 <Layout.Header.Slot />
82 </Layout.Header.Outer>
83 <Layout.Content>
84 <SettingsList.Container>
85 <SettingsList.Group iconInset={false}>
86 <SettingsList.ItemText>
87 <Trans>App Language</Trans>
88 </SettingsList.ItemText>
89 <View style={[a.gap_md, a.w_full]}>
90 <Text style={[a.leading_snug]}>
91 <Trans>
92 Select which language to use for the app's user interface.
93 </Trans>
94 </Text>
95 <Select.Root
96 value={sanitizeAppLanguageSetting(langPrefs.appLanguage)}
97 onValueChange={onChangeAppLanguage}>
98 <Select.Trigger label={_(msg`Select app language`)}>
99 <Select.ValueText />
100 <Select.Icon />
101 </Select.Trigger>
102 <Select.Content
103 label={_(msg`App language`)}
104 renderItem={({label, value}) => (
105 <Select.Item value={value} label={label}>
106 <Select.ItemIndicator />
107 <Select.ItemText>{label}</Select.ItemText>
108 </Select.Item>
109 )}
110 items={APP_LANGUAGES.map(l => ({
111 label: l.name,
112 value: l.code2,
113 }))}
114 />
115 </Select.Root>
116 </View>
117 </SettingsList.Group>
118 <SettingsList.Divider />
119 <SettingsList.Group iconInset={false}>
120 <SettingsList.ItemText>
121 <Trans>Primary Language</Trans>
122 </SettingsList.ItemText>
123 <View style={[a.gap_md, a.w_full]}>
124 <Text style={[a.leading_snug]}>
125 <Trans>
126 Select your preferred language for translations in your feed.
127 </Trans>
128 </Text>
129 <Select.Root
130 value={langPrefs.primaryLanguage}
131 onValueChange={onChangePrimaryLanguage}>
132 <Select.Trigger label={_(msg`Select primary language`)}>
133 <Select.ValueText />
134 <Select.Icon />
135 </Select.Trigger>
136 <Select.Content
137 label={_(msg`Primary language`)}
138 renderItem={({label, value}) => (
139 <Select.Item value={value} label={label}>
140 <Select.ItemIndicator />
141 <Select.ItemText>{label}</Select.ItemText>
142 </Select.Item>
143 )}
144 items={DEDUPED_LANGUAGES.map(l => ({
145 label: languageName(l, langPrefs.appLanguage),
146 value: l.code2,
147 }))}
148 />
149 </Select.Root>
150 </View>
151 </SettingsList.Group>
152 <SettingsList.Divider />
153 <SettingsList.Group iconInset={false}>
154 <SettingsList.ItemText>
155 <Trans>Content Languages</Trans>
156 </SettingsList.ItemText>
157 <View style={[a.gap_md]}>
158 <Text style={[a.leading_snug]}>
159 <Trans>
160 Select which languages you want your subscribed feeds to
161 include. If none are selected, all languages will be shown.
162 </Trans>
163 </Text>
164
165 <Button
166 label={_(msg`Select content languages`)}
167 size="small"
168 color="secondary"
169 shape="rectangular"
170 onPress={onPressContentLanguages}
171 style={[a.justify_start, web({maxWidth: 400})]}>
172 <ButtonIcon
173 icon={myLanguages.length > 0 ? CheckIcon : PlusIcon}
174 />
175 <ButtonText
176 style={[t.atoms.text, a.text_md, a.flex_1, a.text_left]}
177 numberOfLines={1}>
178 {myLanguages.length > 0
179 ? myLanguages
180 : _(msg`Select languages`)}
181 </ButtonText>
182 </Button>
183 </View>
184 </SettingsList.Group>
185 </SettingsList.Container>
186 </Layout.Content>
187 </Layout.Screen>
188 )
189}