Bluesky app fork with some witchin' additions 馃挮
at feat/tealfm 189 lines 7.0 kB view raw
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}