Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 237 lines 9.1 kB view raw
1import {useCallback, useMemo, useState} from 'react' 2import {View} from 'react-native' 3import {msg} from '@lingui/core/macro' 4import {useLingui} from '@lingui/react' 5import {Trans} from '@lingui/react/macro' 6 7import { 8 type CommonNavigatorParams, 9 type NativeStackScreenProps, 10} from '#/lib/routes/types' 11import {languageName, sanitizeAppLanguageSetting} from '#/locale/helpers' 12import {APP_LANGUAGES, LANGUAGES} from '#/locale/languages' 13import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences' 14import {atoms as a, web} from '#/alf' 15import {Admonition} from '#/components/Admonition' 16import {Button} from '#/components/Button' 17import {useDialogControl} from '#/components/Dialog' 18import {LanguageSelectDialog} from '#/components/dialogs/LanguageSelectDialog' 19import * as Toggle from '#/components/forms/Toggle' 20import {PlusLarge_Stroke2_Corner0_Rounded as PlusIcon} from '#/components/icons/Plus' 21import * as Layout from '#/components/Layout' 22import * as Select from '#/components/Select' 23import {Text} from '#/components/Typography' 24import * as SettingsList from './components/SettingsList' 25 26const DEDUPED_LANGUAGES = LANGUAGES.filter( 27 (lang, i, arr) => 28 lang.code2 && arr.findIndex(l => l.code2 === lang.code2) === i, 29) 30 31type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'> 32export function LanguageSettingsScreen({}: Props) { 33 const {_} = useLingui() 34 const langPrefs = useLanguagePrefs() 35 const setLangPrefs = useLanguagePrefsApi() 36 37 const contentLanguagePrefsControl = useDialogControl() 38 39 const onChangePrimaryLanguage = useCallback( 40 (value: string) => { 41 if (!value) return 42 if (langPrefs.primaryLanguage !== value) { 43 setLangPrefs.setPrimaryLanguage(value) 44 } 45 }, 46 [langPrefs, setLangPrefs], 47 ) 48 49 const onChangeAppLanguage = useCallback( 50 (value: string) => { 51 if (!value) return 52 if (langPrefs.appLanguage !== value) { 53 setLangPrefs.setAppLanguage(sanitizeAppLanguageSetting(value)) 54 } 55 }, 56 [langPrefs, setLangPrefs], 57 ) 58 59 const [recentLanguages, setRecentLanguages] = useState<string[]>( 60 langPrefs.contentLanguages, 61 ) 62 63 const possibleLanguages = useMemo(() => { 64 return [ 65 ...new Set([ 66 ...recentLanguages, 67 ...langPrefs.contentLanguages, 68 ...langPrefs.primaryLanguage, 69 ]), 70 ] 71 .map(lang => LANGUAGES.find(l => l.code2 === lang)) 72 .filter(x => !!x) 73 }, [recentLanguages, langPrefs.contentLanguages, langPrefs.primaryLanguage]) 74 75 return ( 76 <Layout.Screen testID="PreferencesLanguagesScreen"> 77 <Layout.Header.Outer> 78 <Layout.Header.BackButton /> 79 <Layout.Header.Content> 80 <Layout.Header.TitleText> 81 <Trans>Languages</Trans> 82 </Layout.Header.TitleText> 83 </Layout.Header.Content> 84 <Layout.Header.Slot /> 85 </Layout.Header.Outer> 86 <Layout.Content> 87 <SettingsList.Container> 88 <SettingsList.Group iconInset={false}> 89 <SettingsList.ItemText> 90 <Trans>App language</Trans> 91 </SettingsList.ItemText> 92 <View style={[a.gap_md, a.w_full]}> 93 <Text style={[a.leading_snug]}> 94 <Trans> 95 Select which language to use for the app's user interface. 96 </Trans> 97 </Text> 98 <Select.Root 99 value={sanitizeAppLanguageSetting(langPrefs.appLanguage)} 100 onValueChange={onChangeAppLanguage}> 101 <Select.Trigger label={_(msg`Select app language`)}> 102 <Select.ValueText /> 103 <Select.Icon /> 104 </Select.Trigger> 105 <Select.Content 106 label={_(msg`App language`)} 107 renderItem={({label, value}) => ( 108 <Select.Item value={value} label={label}> 109 <Select.ItemIndicator /> 110 <Select.ItemText>{label}</Select.ItemText> 111 </Select.Item> 112 )} 113 items={APP_LANGUAGES.map(l => ({ 114 label: l.name, 115 value: l.code2, 116 }))} 117 /> 118 </Select.Root> 119 </View> 120 </SettingsList.Group> 121 <SettingsList.Divider /> 122 <SettingsList.Group iconInset={false}> 123 <SettingsList.ItemText> 124 <Trans>Primary language</Trans> 125 </SettingsList.ItemText> 126 <View style={[a.gap_md, a.w_full]}> 127 <Text style={[a.leading_snug]}> 128 <Trans> 129 Select your preferred language for translations in your feed. 130 </Trans> 131 </Text> 132 <Select.Root 133 value={langPrefs.primaryLanguage} 134 onValueChange={onChangePrimaryLanguage}> 135 <Select.Trigger label={_(msg`Select primary language`)}> 136 <Select.ValueText /> 137 <Select.Icon /> 138 </Select.Trigger> 139 <Select.Content 140 label={_(msg`Primary language`)} 141 renderItem={({label, value}) => ( 142 <Select.Item value={value} label={label}> 143 <Select.ItemIndicator /> 144 <Select.ItemText>{label}</Select.ItemText> 145 </Select.Item> 146 )} 147 items={DEDUPED_LANGUAGES.map(l => ({ 148 label: languageName(l, langPrefs.appLanguage), 149 value: l.code2, 150 })).sort((a, b) => 151 a.label.localeCompare(b.label, langPrefs.appLanguage), 152 )} 153 /> 154 </Select.Root> 155 </View> 156 </SettingsList.Group> 157 <SettingsList.Divider /> 158 <SettingsList.Group iconInset={false}> 159 <SettingsList.ItemText> 160 <Trans>Content languages</Trans> 161 </SettingsList.ItemText> 162 <View style={[a.gap_md]}> 163 <Text style={[a.leading_snug]}> 164 <Trans> 165 Select which languages you want your subscribed feeds to 166 include. If none are selected, all languages will be shown. 167 </Trans> 168 </Text> 169 170 {langPrefs.contentLanguages.length === 0 && ( 171 <Admonition type="info"> 172 <Trans>All languages will be shown in your feeds.</Trans> 173 </Admonition> 174 )} 175 176 <View style={[a.w_full, web({maxWidth: 400})]}> 177 <Toggle.Group 178 label={_(msg`Select content languages`)} 179 values={langPrefs.contentLanguages} 180 onChange={setLangPrefs.setContentLanguages}> 181 <Toggle.PanelGroup> 182 {possibleLanguages.map((language, index) => { 183 const name = languageName(language, langPrefs.appLanguage) 184 return ( 185 <Toggle.Item 186 key={language.code2} 187 name={language.code2} 188 label={name}> 189 {({selected}) => ( 190 <Toggle.Panel 191 active={selected} 192 adjacent={index === 0 ? 'trailing' : 'both'}> 193 <Toggle.Checkbox /> 194 <Toggle.PanelText>{name}</Toggle.PanelText> 195 </Toggle.Panel> 196 )} 197 </Toggle.Item> 198 ) 199 })} 200 <Button 201 label={_(msg`Add more languages…`)} 202 onPress={contentLanguagePrefsControl.open}> 203 <Toggle.Panel adjacent="leading"> 204 <Toggle.PanelIcon icon={PlusIcon} /> 205 <Toggle.PanelText> 206 <Trans>Add more languages</Trans> 207 </Toggle.PanelText> 208 </Toggle.Panel> 209 </Button> 210 </Toggle.PanelGroup> 211 </Toggle.Group> 212 </View> 213 214 <LanguageSelectDialog 215 control={contentLanguagePrefsControl} 216 titleText={<Trans>Select content languages</Trans>} 217 subtitleText={ 218 <Trans> 219 If none are selected, all languages will be shown in your 220 feeds. 221 </Trans> 222 } 223 currentLanguages={langPrefs.contentLanguages} 224 onSelectLanguages={languages => { 225 setLangPrefs.setContentLanguages(languages) 226 setRecentLanguages(recent => [ 227 ...new Set([...recent, ...languages]), 228 ]) 229 }} 230 /> 231 </View> 232 </SettingsList.Group> 233 </SettingsList.Container> 234 </Layout.Content> 235 </Layout.Screen> 236 ) 237}