Pull language methods into api context (#1847)
* Pull language methods into api context * Rename for consistencyzio/stable
parent
f18b15241a
commit
bd531f2344
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||||
import {Provider as LanguagesProvider} from './languages'
|
import {Provider as LanguagesProvider} from './languages'
|
||||||
import {Provider as AltTextRequiredProvider} from '../preferences/alt-text-required'
|
import {Provider as AltTextRequiredProvider} from '../preferences/alt-text-required'
|
||||||
|
|
||||||
export {useLanguagePrefs, useSetLanguagePrefs} from './languages'
|
export {useLanguagePrefs, useLanguagePrefsApi} from './languages'
|
||||||
export {
|
export {
|
||||||
useRequireAltTextEnabled,
|
useRequireAltTextEnabled,
|
||||||
useSetRequireAltTextEnabled,
|
useSetRequireAltTextEnabled,
|
||||||
|
|
|
@ -2,24 +2,36 @@ import React from 'react'
|
||||||
import * as persisted from '#/state/persisted'
|
import * as persisted from '#/state/persisted'
|
||||||
|
|
||||||
type SetStateCb = (
|
type SetStateCb = (
|
||||||
v: persisted.Schema['languagePrefs'],
|
s: persisted.Schema['languagePrefs'],
|
||||||
) => persisted.Schema['languagePrefs']
|
) => persisted.Schema['languagePrefs']
|
||||||
type StateContext = persisted.Schema['languagePrefs']
|
type StateContext = persisted.Schema['languagePrefs']
|
||||||
type SetContext = (fn: SetStateCb) => void
|
type ApiContext = {
|
||||||
|
setPrimaryLanguage: (code2: string) => void
|
||||||
|
setPostLanguage: (commaSeparatedLangCodes: string) => void
|
||||||
|
toggleContentLanguage: (code2: string) => void
|
||||||
|
togglePostLanguage: (code2: string) => void
|
||||||
|
savePostLanguageToHistory: () => void
|
||||||
|
}
|
||||||
|
|
||||||
const stateContext = React.createContext<StateContext>(
|
const stateContext = React.createContext<StateContext>(
|
||||||
persisted.defaults.languagePrefs,
|
persisted.defaults.languagePrefs,
|
||||||
)
|
)
|
||||||
const setContext = React.createContext<SetContext>((_: SetStateCb) => {})
|
const apiContext = React.createContext<ApiContext>({
|
||||||
|
setPrimaryLanguage: (_: string) => {},
|
||||||
|
setPostLanguage: (_: string) => {},
|
||||||
|
toggleContentLanguage: (_: string) => {},
|
||||||
|
togglePostLanguage: (_: string) => {},
|
||||||
|
savePostLanguageToHistory: () => {},
|
||||||
|
})
|
||||||
|
|
||||||
export function Provider({children}: React.PropsWithChildren<{}>) {
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
const [state, setState] = React.useState(persisted.get('languagePrefs'))
|
const [state, setState] = React.useState(persisted.get('languagePrefs'))
|
||||||
|
|
||||||
const setStateWrapped = React.useCallback(
|
const setStateWrapped = React.useCallback(
|
||||||
(fn: SetStateCb) => {
|
(fn: SetStateCb) => {
|
||||||
const v = fn(persisted.get('languagePrefs'))
|
const s = fn(persisted.get('languagePrefs'))
|
||||||
setState(v)
|
setState(s)
|
||||||
persisted.write('languagePrefs', v)
|
persisted.write('languagePrefs', s)
|
||||||
},
|
},
|
||||||
[setState],
|
[setState],
|
||||||
)
|
)
|
||||||
|
@ -30,11 +42,75 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
||||||
})
|
})
|
||||||
}, [setStateWrapped])
|
}, [setStateWrapped])
|
||||||
|
|
||||||
|
const api = React.useMemo(
|
||||||
|
() => ({
|
||||||
|
setPrimaryLanguage(code2: string) {
|
||||||
|
setStateWrapped(s => ({...s, primaryLanguage: code2}))
|
||||||
|
},
|
||||||
|
setPostLanguage(commaSeparatedLangCodes: string) {
|
||||||
|
setStateWrapped(s => ({...s, postLanguage: commaSeparatedLangCodes}))
|
||||||
|
},
|
||||||
|
toggleContentLanguage(code2: string) {
|
||||||
|
setStateWrapped(s => {
|
||||||
|
const exists = s.contentLanguages.includes(code2)
|
||||||
|
const next = exists
|
||||||
|
? s.contentLanguages.filter(lang => lang !== code2)
|
||||||
|
: s.contentLanguages.concat(code2)
|
||||||
|
return {
|
||||||
|
...s,
|
||||||
|
contentLanguages: next,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
togglePostLanguage(code2: string) {
|
||||||
|
setStateWrapped(s => {
|
||||||
|
const exists = hasPostLanguage(state.postLanguage, code2)
|
||||||
|
let next = s.postLanguage
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
next = toPostLanguages(s.postLanguage)
|
||||||
|
.filter(lang => lang !== code2)
|
||||||
|
.join(',')
|
||||||
|
} else {
|
||||||
|
// sort alphabetically for deterministic comparison in context menu
|
||||||
|
next = toPostLanguages(s.postLanguage)
|
||||||
|
.concat([code2])
|
||||||
|
.sort((a, b) => a.localeCompare(b))
|
||||||
|
.join(',')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...s,
|
||||||
|
postLanguage: next,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Saves whatever language codes are currently selected into a history array,
|
||||||
|
* which is then used to populate the language selector menu.
|
||||||
|
*/
|
||||||
|
savePostLanguageToHistory() {
|
||||||
|
// filter out duplicate `this.postLanguage` if exists, and prepend
|
||||||
|
// value to start of array
|
||||||
|
setStateWrapped(s => ({
|
||||||
|
...s,
|
||||||
|
postLanguageHistory: [s.postLanguage]
|
||||||
|
.concat(
|
||||||
|
s.postLanguageHistory.filter(
|
||||||
|
commaSeparatedLangCodes =>
|
||||||
|
commaSeparatedLangCodes !== s.postLanguage,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.slice(0, 6),
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[state, setStateWrapped],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<stateContext.Provider value={state}>
|
<stateContext.Provider value={state}>
|
||||||
<setContext.Provider value={setStateWrapped}>
|
<apiContext.Provider value={api}>{children}</apiContext.Provider>
|
||||||
{children}
|
|
||||||
</setContext.Provider>
|
|
||||||
</stateContext.Provider>
|
</stateContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -43,32 +119,14 @@ export function useLanguagePrefs() {
|
||||||
return React.useContext(stateContext)
|
return React.useContext(stateContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useSetLanguagePrefs() {
|
export function useLanguagePrefsApi() {
|
||||||
return React.useContext(setContext)
|
return React.useContext(apiContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getContentLanguages() {
|
export function getContentLanguages() {
|
||||||
return persisted.get('languagePrefs').contentLanguages
|
return persisted.get('languagePrefs').contentLanguages
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggleContentLanguage(
|
|
||||||
state: StateContext,
|
|
||||||
setState: SetContext,
|
|
||||||
code2: string,
|
|
||||||
) {
|
|
||||||
if (state.contentLanguages.includes(code2)) {
|
|
||||||
setState(v => ({
|
|
||||||
...v,
|
|
||||||
contentLanguages: v.contentLanguages.filter(lang => lang !== code2),
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
setState(v => ({
|
|
||||||
...v,
|
|
||||||
contentLanguages: v.contentLanguages.concat(code2),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toPostLanguages(postLanguage: string): string[] {
|
export function toPostLanguages(postLanguage: string): string[] {
|
||||||
// filter out empty strings if exist
|
// filter out empty strings if exist
|
||||||
return postLanguage.split(',').filter(Boolean)
|
return postLanguage.split(',').filter(Boolean)
|
||||||
|
@ -77,46 +135,3 @@ export function toPostLanguages(postLanguage: string): string[] {
|
||||||
export function hasPostLanguage(postLanguage: string, code2: string): boolean {
|
export function hasPostLanguage(postLanguage: string, code2: string): boolean {
|
||||||
return toPostLanguages(postLanguage).includes(code2)
|
return toPostLanguages(postLanguage).includes(code2)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function togglePostLanguage(
|
|
||||||
state: StateContext,
|
|
||||||
setState: SetContext,
|
|
||||||
code2: string,
|
|
||||||
) {
|
|
||||||
if (hasPostLanguage(state.postLanguage, code2)) {
|
|
||||||
setState(v => ({
|
|
||||||
...v,
|
|
||||||
postLanguage: toPostLanguages(v.postLanguage)
|
|
||||||
.filter(lang => lang !== code2)
|
|
||||||
.join(','),
|
|
||||||
}))
|
|
||||||
} else {
|
|
||||||
// sort alphabetically for deterministic comparison in context menu
|
|
||||||
setState(v => ({
|
|
||||||
...v,
|
|
||||||
postLanguage: toPostLanguages(v.postLanguage)
|
|
||||||
.concat([code2])
|
|
||||||
.sort((a, b) => a.localeCompare(b))
|
|
||||||
.join(','),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves whatever language codes are currently selected into a history array,
|
|
||||||
* which is then used to populate the language selector menu.
|
|
||||||
*/
|
|
||||||
export function savePostLanguageToHistory(setState: SetContext) {
|
|
||||||
// filter out duplicate `this.postLanguage` if exists, and prepend
|
|
||||||
// value to start of array
|
|
||||||
setState(v => ({
|
|
||||||
...v,
|
|
||||||
postLanguageHistory: [v.postLanguage]
|
|
||||||
.concat(
|
|
||||||
v.postLanguageHistory.filter(
|
|
||||||
commaSeparatedLangCodes => commaSeparatedLangCodes !== v.postLanguage,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.slice(0, 6),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
|
@ -53,9 +53,8 @@ import {useModals, useModalControls} from '#/state/modals'
|
||||||
import {useRequireAltTextEnabled} from '#/state/preferences'
|
import {useRequireAltTextEnabled} from '#/state/preferences'
|
||||||
import {
|
import {
|
||||||
useLanguagePrefs,
|
useLanguagePrefs,
|
||||||
useSetLanguagePrefs,
|
useLanguagePrefsApi,
|
||||||
toPostLanguages,
|
toPostLanguages,
|
||||||
savePostLanguageToHistory,
|
|
||||||
} from '#/state/preferences/languages'
|
} from '#/state/preferences/languages'
|
||||||
|
|
||||||
type Props = ComposerOpts
|
type Props = ComposerOpts
|
||||||
|
@ -73,7 +72,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
const store = useStores()
|
const store = useStores()
|
||||||
const requireAltTextEnabled = useRequireAltTextEnabled()
|
const requireAltTextEnabled = useRequireAltTextEnabled()
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
const setLangPrefs = useSetLanguagePrefs()
|
const setLangPrefs = useLanguagePrefsApi()
|
||||||
const textInput = useRef<TextInputRef>(null)
|
const textInput = useRef<TextInputRef>(null)
|
||||||
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
const [isKeyboardVisible] = useIsKeyboardVisible({iosUseWillEvents: true})
|
||||||
const [isProcessing, setIsProcessing] = useState(false)
|
const [isProcessing, setIsProcessing] = useState(false)
|
||||||
|
@ -245,7 +244,7 @@ export const ComposePost = observer(function ComposePost({
|
||||||
if (!replyTo) {
|
if (!replyTo) {
|
||||||
store.me.mainFeed.onPostCreated()
|
store.me.mainFeed.onPostCreated()
|
||||||
}
|
}
|
||||||
savePostLanguageToHistory(setLangPrefs)
|
setLangPrefs.savePostLanguageToHistory()
|
||||||
onPost?.()
|
onPost?.()
|
||||||
onClose()
|
onClose()
|
||||||
Toast.show(`Your ${replyTo ? 'reply' : 'post'} has been published`)
|
Toast.show(`Your ${replyTo ? 'reply' : 'post'} has been published`)
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {codeToLanguageName} from '../../../../locale/helpers'
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
import {
|
import {
|
||||||
useLanguagePrefs,
|
useLanguagePrefs,
|
||||||
useSetLanguagePrefs,
|
useLanguagePrefsApi,
|
||||||
toPostLanguages,
|
toPostLanguages,
|
||||||
hasPostLanguage,
|
hasPostLanguage,
|
||||||
} from '#/state/preferences/languages'
|
} from '#/state/preferences/languages'
|
||||||
|
@ -26,7 +26,7 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {openModal} = useModalControls()
|
const {openModal} = useModalControls()
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
const setLangPrefs = useSetLanguagePrefs()
|
const setLangPrefs = useLanguagePrefsApi()
|
||||||
|
|
||||||
const onPressMore = useCallback(async () => {
|
const onPressMore = useCallback(async () => {
|
||||||
if (isNative) {
|
if (isNative) {
|
||||||
|
@ -63,7 +63,7 @@ export const SelectLangBtn = observer(function SelectLangBtn() {
|
||||||
: ['far', 'circle'],
|
: ['far', 'circle'],
|
||||||
label: langName,
|
label: langName,
|
||||||
onPress() {
|
onPress() {
|
||||||
setLangPrefs(v => ({...v, postLanguage: commaSeparatedLangCodes}))
|
setLangPrefs.setPostLanguage(commaSeparatedLangCodes)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,7 @@ import {ConfirmLanguagesButton} from './ConfirmLanguagesButton'
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
import {
|
import {
|
||||||
useLanguagePrefs,
|
useLanguagePrefs,
|
||||||
useSetLanguagePrefs,
|
useLanguagePrefsApi,
|
||||||
toggleContentLanguage,
|
|
||||||
} from '#/state/preferences/languages'
|
} from '#/state/preferences/languages'
|
||||||
|
|
||||||
export const snapPoints = ['100%']
|
export const snapPoints = ['100%']
|
||||||
|
@ -20,7 +19,7 @@ export const snapPoints = ['100%']
|
||||||
export function Component({}: {}) {
|
export function Component({}: {}) {
|
||||||
const {closeModal} = useModalControls()
|
const {closeModal} = useModalControls()
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
const setLangPrefs = useSetLanguagePrefs()
|
const setLangPrefs = useLanguagePrefsApi()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {isMobile} = useWebMediaQueries()
|
const {isMobile} = useWebMediaQueries()
|
||||||
const onPressDone = React.useCallback(() => {
|
const onPressDone = React.useCallback(() => {
|
||||||
|
@ -50,9 +49,9 @@ export function Component({}: {}) {
|
||||||
|
|
||||||
const onPress = React.useCallback(
|
const onPress = React.useCallback(
|
||||||
(code2: string) => {
|
(code2: string) => {
|
||||||
toggleContentLanguage(langPrefs, setLangPrefs, code2)
|
setLangPrefs.toggleContentLanguage(code2)
|
||||||
},
|
},
|
||||||
[langPrefs, setLangPrefs],
|
[setLangPrefs],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -12,9 +12,8 @@ import {ToggleButton} from 'view/com/util/forms/ToggleButton'
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
import {
|
import {
|
||||||
useLanguagePrefs,
|
useLanguagePrefs,
|
||||||
useSetLanguagePrefs,
|
useLanguagePrefsApi,
|
||||||
hasPostLanguage,
|
hasPostLanguage,
|
||||||
togglePostLanguage,
|
|
||||||
} from '#/state/preferences/languages'
|
} from '#/state/preferences/languages'
|
||||||
|
|
||||||
export const snapPoints = ['100%']
|
export const snapPoints = ['100%']
|
||||||
|
@ -22,7 +21,7 @@ export const snapPoints = ['100%']
|
||||||
export const Component = observer(function PostLanguagesSettingsImpl() {
|
export const Component = observer(function PostLanguagesSettingsImpl() {
|
||||||
const {closeModal} = useModalControls()
|
const {closeModal} = useModalControls()
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
const setLangPrefs = useSetLanguagePrefs()
|
const setLangPrefs = useLanguagePrefsApi()
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const {isMobile} = useWebMediaQueries()
|
const {isMobile} = useWebMediaQueries()
|
||||||
const onPressDone = React.useCallback(() => {
|
const onPressDone = React.useCallback(() => {
|
||||||
|
@ -52,9 +51,9 @@ export const Component = observer(function PostLanguagesSettingsImpl() {
|
||||||
|
|
||||||
const onPress = React.useCallback(
|
const onPress = React.useCallback(
|
||||||
(code2: string) => {
|
(code2: string) => {
|
||||||
togglePostLanguage(langPrefs, setLangPrefs, code2)
|
setLangPrefs.togglePostLanguage(code2)
|
||||||
},
|
},
|
||||||
[langPrefs, setLangPrefs],
|
[setLangPrefs],
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {LANGUAGES} from 'lib/../locale/languages'
|
||||||
import RNPickerSelect, {PickerSelectProps} from 'react-native-picker-select'
|
import RNPickerSelect, {PickerSelectProps} from 'react-native-picker-select'
|
||||||
import {useSetMinimalShellMode} from '#/state/shell'
|
import {useSetMinimalShellMode} from '#/state/shell'
|
||||||
import {useModalControls} from '#/state/modals'
|
import {useModalControls} from '#/state/modals'
|
||||||
import {useLanguagePrefs, useSetLanguagePrefs} from '#/state/preferences'
|
import {useLanguagePrefs, useLanguagePrefsApi} from '#/state/preferences'
|
||||||
|
|
||||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'>
|
type Props = NativeStackScreenProps<CommonNavigatorParams, 'LanguageSettings'>
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ export const LanguageSettingsScreen = observer(function LanguageSettingsImpl(
|
||||||
) {
|
) {
|
||||||
const pal = usePalette('default')
|
const pal = usePalette('default')
|
||||||
const langPrefs = useLanguagePrefs()
|
const langPrefs = useLanguagePrefs()
|
||||||
const setLangPrefs = useSetLanguagePrefs()
|
const setLangPrefs = useLanguagePrefsApi()
|
||||||
const {isTabletOrDesktop} = useWebMediaQueries()
|
const {isTabletOrDesktop} = useWebMediaQueries()
|
||||||
const {screen, track} = useAnalytics()
|
const {screen, track} = useAnalytics()
|
||||||
const setMinimalShellMode = useSetMinimalShellMode()
|
const setMinimalShellMode = useSetMinimalShellMode()
|
||||||
|
@ -49,7 +49,7 @@ export const LanguageSettingsScreen = observer(function LanguageSettingsImpl(
|
||||||
const onChangePrimaryLanguage = React.useCallback(
|
const onChangePrimaryLanguage = React.useCallback(
|
||||||
(value: Parameters<PickerSelectProps['onValueChange']>[0]) => {
|
(value: Parameters<PickerSelectProps['onValueChange']>[0]) => {
|
||||||
if (langPrefs.primaryLanguage !== value) {
|
if (langPrefs.primaryLanguage !== value) {
|
||||||
setLangPrefs(v => ({...v, primaryLanguage: value}))
|
setLangPrefs.setPrimaryLanguage(value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[langPrefs, setLangPrefs],
|
[langPrefs, setLangPrefs],
|
||||||
|
|
Loading…
Reference in New Issue