Move language preferences to new persistence + context (#1837)
This commit is contained in:
parent
e75b2d508b
commit
5843e212c0
15 changed files with 233 additions and 190 deletions
|
@ -50,6 +50,12 @@ import {SelectLangBtn} from './select-language/SelectLangBtn'
|
|||
import {EmojiPickerButton} from './text-input/web/EmojiPicker.web'
|
||||
import {insertMentionAt} from 'lib/strings/mention-manip'
|
||||
import {useRequireAltTextEnabled} from '#/state/shell'
|
||||
import {
|
||||
useLanguagePrefs,
|
||||
useSetLanguagePrefs,
|
||||
toPostLanguages,
|
||||
savePostLanguageToHistory,
|
||||
} from '#/state/preferences/languages'
|
||||
|
||||
type Props = ComposerOpts
|
||||
export const ComposePost = observer(function ComposePost({
|
||||
|
@ -63,6 +69,8 @@ export const ComposePost = observer(function ComposePost({
|
|||
const {isDesktop, isMobile} = useWebMediaQueries()
|
||||
const store = useStores()
|
||||
const requireAltTextEnabled = useRequireAltTextEnabled()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const setLangPrefs = useSetLanguagePrefs()
|
||||
const textInput = useRef<TextInputRef>(null)
|
||||
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
||||
const [isProcessing, setIsProcessing] = useState(false)
|
||||
|
@ -212,7 +220,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
labels,
|
||||
onStateChange: setProcessingState,
|
||||
knownHandles: autocompleteView.knownHandles,
|
||||
langs: store.preferences.postLanguages,
|
||||
langs: toPostLanguages(langPrefs.postLanguage),
|
||||
})
|
||||
} catch (e: any) {
|
||||
if (extLink) {
|
||||
|
@ -234,7 +242,7 @@ export const ComposePost = observer(function ComposePost({
|
|||
if (!replyTo) {
|
||||
store.me.mainFeed.onPostCreated()
|
||||
}
|
||||
store.preferences.savePostLanguageToHistory()
|
||||
savePostLanguageToHistory(setLangPrefs)
|
||||
onPost?.()
|
||||
onClose()
|
||||
Toast.show(`Your ${replyTo ? 'reply' : 'post'} has been published`)
|
||||
|
|
|
@ -15,10 +15,18 @@ import {usePalette} from 'lib/hooks/usePalette'
|
|||
import {useStores} from 'state/index'
|
||||
import {isNative} from 'platform/detection'
|
||||
import {codeToLanguageName} from '../../../../locale/helpers'
|
||||
import {
|
||||
useLanguagePrefs,
|
||||
useSetLanguagePrefs,
|
||||
toPostLanguages,
|
||||
hasPostLanguage,
|
||||
} from '#/state/preferences/languages'
|
||||
|
||||
export const SelectLangBtn = observer(function SelectLangBtn() {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const setLangPrefs = useSetLanguagePrefs()
|
||||
|
||||
const onPressMore = useCallback(async () => {
|
||||
if (isNative) {
|
||||
|
@ -29,8 +37,7 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
|
|||
store.shell.openModal({name: 'post-languages-settings'})
|
||||
}, [store])
|
||||
|
||||
const postLanguagesPref = store.preferences.postLanguages
|
||||
const postLanguagePref = store.preferences.postLanguage
|
||||
const postLanguagesPref = toPostLanguages(langPrefs.postLanguage)
|
||||
const items: DropdownItem[] = useMemo(() => {
|
||||
let arr: DropdownItemButton[] = []
|
||||
|
||||
|
@ -49,13 +56,14 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
|
|||
|
||||
arr.push({
|
||||
icon:
|
||||
langCodes.every(code => store.preferences.hasPostLanguage(code)) &&
|
||||
langCodes.length === postLanguagesPref.length
|
||||
langCodes.every(code =>
|
||||
hasPostLanguage(langPrefs.postLanguage, code),
|
||||
) && langCodes.length === postLanguagesPref.length
|
||||
? ['fas', 'circle-dot']
|
||||
: ['far', 'circle'],
|
||||
label: langName,
|
||||
onPress() {
|
||||
store.preferences.setPostLanguage(commaSeparatedLangCodes)
|
||||
setLangPrefs(v => ({...v, postLanguage: commaSeparatedLangCodes}))
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@ -65,11 +73,11 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
|
|||
* Re-join here after sanitization bc postLanguageHistory is an array of
|
||||
* comma-separated strings too
|
||||
*/
|
||||
add(postLanguagePref)
|
||||
add(langPrefs.postLanguage)
|
||||
}
|
||||
|
||||
// comma-separted strings of lang codes that have been used in the past
|
||||
for (const lang of store.preferences.postLanguageHistory) {
|
||||
for (const lang of langPrefs.postLanguageHistory) {
|
||||
add(lang)
|
||||
}
|
||||
|
||||
|
@ -82,7 +90,7 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
|
|||
onPress: onPressMore,
|
||||
},
|
||||
]
|
||||
}, [store.preferences, onPressMore, postLanguagePref, postLanguagesPref])
|
||||
}, [onPressMore, langPrefs, setLangPrefs, postLanguagesPref])
|
||||
|
||||
return (
|
||||
<DropdownButton
|
||||
|
|
|
@ -9,11 +9,18 @@ import {deviceLocales} from 'platform/detection'
|
|||
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
||||
import {LanguageToggle} from './LanguageToggle'
|
||||
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
||||
import {
|
||||
useLanguagePrefs,
|
||||
useSetLanguagePrefs,
|
||||
toggleContentLanguage,
|
||||
} from '#/state/preferences/languages'
|
||||
|
||||
export const snapPoints = ['100%']
|
||||
|
||||
export function Component({}: {}) {
|
||||
const store = useStores()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const setLangPrefs = useSetLanguagePrefs()
|
||||
const pal = usePalette('default')
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const onPressDone = React.useCallback(() => {
|
||||
|
@ -29,23 +36,23 @@ export function Component({}: {}) {
|
|||
// sort so that device & selected languages are on top, then alphabetically
|
||||
langs.sort((a, b) => {
|
||||
const hasA =
|
||||
store.preferences.hasContentLanguage(a.code2) ||
|
||||
langPrefs.contentLanguages.includes(a.code2) ||
|
||||
deviceLocales.includes(a.code2)
|
||||
const hasB =
|
||||
store.preferences.hasContentLanguage(b.code2) ||
|
||||
langPrefs.contentLanguages.includes(b.code2) ||
|
||||
deviceLocales.includes(b.code2)
|
||||
if (hasA === hasB) return a.name.localeCompare(b.name)
|
||||
if (hasA) return -1
|
||||
return 1
|
||||
})
|
||||
return langs
|
||||
}, [store])
|
||||
}, [langPrefs])
|
||||
|
||||
const onPress = React.useCallback(
|
||||
(code2: string) => {
|
||||
store.preferences.toggleContentLanguage(code2)
|
||||
toggleContentLanguage(langPrefs, setLangPrefs, code2)
|
||||
},
|
||||
[store],
|
||||
[langPrefs, setLangPrefs],
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
|
@ -3,7 +3,7 @@ import {StyleSheet} from 'react-native'
|
|||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {observer} from 'mobx-react-lite'
|
||||
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||
import {useStores} from 'state/index'
|
||||
import {useLanguagePrefs, toPostLanguages} from '#/state/preferences/languages'
|
||||
|
||||
export const LanguageToggle = observer(function LanguageToggleImpl({
|
||||
code2,
|
||||
|
@ -17,17 +17,17 @@ export const LanguageToggle = observer(function LanguageToggleImpl({
|
|||
langType: 'contentLanguages' | 'postLanguages'
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
|
||||
const isSelected = store.preferences[langType].includes(code2)
|
||||
const values =
|
||||
langType === 'contentLanguages'
|
||||
? langPrefs.contentLanguages
|
||||
: toPostLanguages(langPrefs.postLanguage)
|
||||
const isSelected = values.includes(code2)
|
||||
|
||||
// enforce a max of 3 selections for post languages
|
||||
let isDisabled = false
|
||||
if (
|
||||
langType === 'postLanguages' &&
|
||||
store.preferences[langType].length >= 3 &&
|
||||
!isSelected
|
||||
) {
|
||||
if (langType === 'postLanguages' && values.length >= 3 && !isSelected) {
|
||||
isDisabled = true
|
||||
}
|
||||
|
||||
|
|
|
@ -10,11 +10,19 @@ import {deviceLocales} from 'platform/detection'
|
|||
import {LANGUAGES, LANGUAGES_MAP_CODE2} from '../../../../locale/languages'
|
||||
import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
||||
import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||
import {
|
||||
useLanguagePrefs,
|
||||
useSetLanguagePrefs,
|
||||
hasPostLanguage,
|
||||
togglePostLanguage,
|
||||
} from '#/state/preferences/languages'
|
||||
|
||||
export const snapPoints = ['100%']
|
||||
|
||||
export const Component = observer(function PostLanguagesSettingsImpl() {
|
||||
const store = useStores()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const setLangPrefs = useSetLanguagePrefs()
|
||||
const pal = usePalette('default')
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const onPressDone = React.useCallback(() => {
|
||||
|
@ -30,23 +38,23 @@ export const Component = observer(function PostLanguagesSettingsImpl() {
|
|||
// sort so that device & selected languages are on top, then alphabetically
|
||||
langs.sort((a, b) => {
|
||||
const hasA =
|
||||
store.preferences.hasPostLanguage(a.code2) ||
|
||||
hasPostLanguage(langPrefs.postLanguage, a.code2) ||
|
||||
deviceLocales.includes(a.code2)
|
||||
const hasB =
|
||||
store.preferences.hasPostLanguage(b.code2) ||
|
||||
hasPostLanguage(langPrefs.postLanguage, b.code2) ||
|
||||
deviceLocales.includes(b.code2)
|
||||
if (hasA === hasB) return a.name.localeCompare(b.name)
|
||||
if (hasA) return -1
|
||||
return 1
|
||||
})
|
||||
return langs
|
||||
}, [store])
|
||||
}, [langPrefs])
|
||||
|
||||
const onPress = React.useCallback(
|
||||
(code2: string) => {
|
||||
store.preferences.togglePostLanguage(code2)
|
||||
togglePostLanguage(langPrefs, setLangPrefs, code2)
|
||||
},
|
||||
[store],
|
||||
[langPrefs, setLangPrefs],
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -70,14 +78,11 @@ export const Component = observer(function PostLanguagesSettingsImpl() {
|
|||
</Text>
|
||||
<ScrollView style={styles.scrollContainer}>
|
||||
{languages.map(lang => {
|
||||
const isSelected = store.preferences.hasPostLanguage(lang.code2)
|
||||
const isSelected = hasPostLanguage(langPrefs.postLanguage, lang.code2)
|
||||
|
||||
// enforce a max of 3 selections for post languages
|
||||
let isDisabled = false
|
||||
if (
|
||||
store.preferences.postLanguage.split(',').length >= 3 &&
|
||||
!isSelected
|
||||
) {
|
||||
if (langPrefs.postLanguage.split(',').length >= 3 && !isSelected) {
|
||||
isDisabled = true
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
|||
import {MAX_POST_LINES} from 'lib/constants'
|
||||
import {logger} from '#/logger'
|
||||
import {useMutedThreads, useToggleThreadMute} from '#/state/muted-threads'
|
||||
import {useLanguagePrefs} from '#/state/preferences'
|
||||
|
||||
export const PostThreadItem = observer(function PostThreadItem({
|
||||
item,
|
||||
|
@ -54,6 +55,7 @@ export const PostThreadItem = observer(function PostThreadItem({
|
|||
const store = useStores()
|
||||
const mutedThreads = useMutedThreads()
|
||||
const toggleThreadMute = useToggleThreadMute()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const [deleted, setDeleted] = React.useState(false)
|
||||
const [limitLines, setLimitLines] = React.useState(
|
||||
countLines(item.richText?.text) >= MAX_POST_LINES,
|
||||
|
@ -85,15 +87,15 @@ export const PostThreadItem = observer(function PostThreadItem({
|
|||
|
||||
const translatorUrl = getTranslatorLink(
|
||||
record?.text || '',
|
||||
store.preferences.primaryLanguage,
|
||||
langPrefs.primaryLanguage,
|
||||
)
|
||||
const needsTranslation = useMemo(
|
||||
() =>
|
||||
Boolean(
|
||||
store.preferences.primaryLanguage &&
|
||||
!isPostInLanguage(item.post, [store.preferences.primaryLanguage]),
|
||||
langPrefs.primaryLanguage &&
|
||||
!isPostInLanguage(item.post, [langPrefs.primaryLanguage]),
|
||||
),
|
||||
[item.post, store.preferences.primaryLanguage],
|
||||
[item.post, langPrefs.primaryLanguage],
|
||||
)
|
||||
|
||||
const onPressReply = React.useCallback(() => {
|
||||
|
|
|
@ -34,6 +34,7 @@ import {MAX_POST_LINES} from 'lib/constants'
|
|||
import {countLines} from 'lib/strings/helpers'
|
||||
import {logger} from '#/logger'
|
||||
import {useMutedThreads, useToggleThreadMute} from '#/state/muted-threads'
|
||||
import {useLanguagePrefs} from '#/state/preferences'
|
||||
|
||||
export const Post = observer(function PostImpl({
|
||||
view,
|
||||
|
@ -109,6 +110,7 @@ const PostLoaded = observer(function PostLoadedImpl({
|
|||
const store = useStores()
|
||||
const mutedThreads = useMutedThreads()
|
||||
const toggleThreadMute = useToggleThreadMute()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const [limitLines, setLimitLines] = React.useState(
|
||||
countLines(item.richText?.text) >= MAX_POST_LINES,
|
||||
)
|
||||
|
@ -125,7 +127,7 @@ const PostLoaded = observer(function PostLoadedImpl({
|
|||
|
||||
const translatorUrl = getTranslatorLink(
|
||||
record?.text || '',
|
||||
store.preferences.primaryLanguage,
|
||||
langPrefs.primaryLanguage,
|
||||
)
|
||||
|
||||
const onPressReply = React.useCallback(() => {
|
||||
|
|
|
@ -34,6 +34,7 @@ import {MAX_POST_LINES} from 'lib/constants'
|
|||
import {countLines} from 'lib/strings/helpers'
|
||||
import {logger} from '#/logger'
|
||||
import {useMutedThreads, useToggleThreadMute} from '#/state/muted-threads'
|
||||
import {useLanguagePrefs} from '#/state/preferences'
|
||||
|
||||
export const FeedItem = observer(function FeedItemImpl({
|
||||
item,
|
||||
|
@ -50,6 +51,7 @@ export const FeedItem = observer(function FeedItemImpl({
|
|||
showReplyLine?: boolean
|
||||
}) {
|
||||
const store = useStores()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const pal = usePalette('default')
|
||||
const mutedThreads = useMutedThreads()
|
||||
const toggleThreadMute = useToggleThreadMute()
|
||||
|
@ -75,7 +77,7 @@ export const FeedItem = observer(function FeedItemImpl({
|
|||
}, [record?.reply])
|
||||
const translatorUrl = getTranslatorLink(
|
||||
record?.text || '',
|
||||
store.preferences.primaryLanguage,
|
||||
langPrefs.primaryLanguage,
|
||||
)
|
||||
|
||||
const onPressReply = React.useCallback(() => {
|
||||
|
|
|
@ -17,6 +17,7 @@ import {useFocusEffect} from '@react-navigation/native'
|
|||
import {ViewHeader} from '../com/util/ViewHeader'
|
||||
import {CenteredView} from 'view/com/util/Views'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {useLanguagePrefs} from '#/state/preferences'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'AppPasswords'>
|
||||
export const AppPasswords = withAuthRequired(
|
||||
|
@ -161,6 +162,7 @@ function AppPassword({
|
|||
}) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const {contentLanguages} = useLanguagePrefs()
|
||||
|
||||
const onDelete = React.useCallback(async () => {
|
||||
store.shell.openModal({
|
||||
|
@ -174,8 +176,6 @@ function AppPassword({
|
|||
})
|
||||
}, [store, name])
|
||||
|
||||
const {contentLanguages} = store.preferences
|
||||
|
||||
const primaryLocale =
|
||||
contentLanguages.length > 0 ? contentLanguages[0] : 'en-US'
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import {useFocusEffect} from '@react-navigation/native'
|
|||
import {LANGUAGES} from 'lib/../locale/languages'
|
||||
import RNPickerSelect, {PickerSelectProps} from 'react-native-picker-select'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {useLanguagePrefs, useSetLanguagePrefs} from '#/state/preferences'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'>
|
||||
|
||||
|
@ -27,6 +28,8 @@ export const LanguageSettingsScreen = observer(function LanguageSettingsImpl(
|
|||
) {
|
||||
const pal = usePalette('default')
|
||||
const store = useStores()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const setLangPrefs = useSetLanguagePrefs()
|
||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||
const {screen, track} = useAnalytics()
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
|
@ -45,21 +48,23 @@ export const LanguageSettingsScreen = observer(function LanguageSettingsImpl(
|
|||
|
||||
const onChangePrimaryLanguage = React.useCallback(
|
||||
(value: Parameters<PickerSelectProps['onValueChange']>[0]) => {
|
||||
store.preferences.setPrimaryLanguage(value)
|
||||
if (langPrefs.primaryLanguage !== value) {
|
||||
setLangPrefs(v => ({...v, primaryLanguage: value}))
|
||||
}
|
||||
},
|
||||
[store.preferences],
|
||||
[langPrefs, setLangPrefs],
|
||||
)
|
||||
|
||||
const myLanguages = React.useMemo(() => {
|
||||
return (
|
||||
store.preferences.contentLanguages
|
||||
langPrefs.contentLanguages
|
||||
.map(lang => LANGUAGES.find(l => l.code2 === lang))
|
||||
.filter(Boolean)
|
||||
// @ts-ignore
|
||||
.map(l => l.name)
|
||||
.join(', ')
|
||||
)
|
||||
}, [store.preferences.contentLanguages])
|
||||
}, [langPrefs.contentLanguages])
|
||||
|
||||
return (
|
||||
<CenteredView
|
||||
|
@ -82,7 +87,7 @@ export const LanguageSettingsScreen = observer(function LanguageSettingsImpl(
|
|||
|
||||
<View style={{position: 'relative'}}>
|
||||
<RNPickerSelect
|
||||
value={store.preferences.primaryLanguage}
|
||||
value={langPrefs.primaryLanguage}
|
||||
onValueChange={onChangePrimaryLanguage}
|
||||
items={LANGUAGES.filter(l => Boolean(l.code2)).map(l => ({
|
||||
label: l.name,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue