Pull language methods into api context (#1847)
* Pull language methods into api context * Rename for consistency
This commit is contained in:
parent
f18b15241a
commit
bd531f2344
7 changed files with 105 additions and 93 deletions
|
@ -2,7 +2,7 @@ import React from 'react'
|
|||
import {Provider as LanguagesProvider} from './languages'
|
||||
import {Provider as AltTextRequiredProvider} from '../preferences/alt-text-required'
|
||||
|
||||
export {useLanguagePrefs, useSetLanguagePrefs} from './languages'
|
||||
export {useLanguagePrefs, useLanguagePrefsApi} from './languages'
|
||||
export {
|
||||
useRequireAltTextEnabled,
|
||||
useSetRequireAltTextEnabled,
|
||||
|
|
|
@ -2,24 +2,36 @@ import React from 'react'
|
|||
import * as persisted from '#/state/persisted'
|
||||
|
||||
type SetStateCb = (
|
||||
v: persisted.Schema['languagePrefs'],
|
||||
s: persisted.Schema['languagePrefs'],
|
||||
) => 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>(
|
||||
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<{}>) {
|
||||
const [state, setState] = React.useState(persisted.get('languagePrefs'))
|
||||
|
||||
const setStateWrapped = React.useCallback(
|
||||
(fn: SetStateCb) => {
|
||||
const v = fn(persisted.get('languagePrefs'))
|
||||
setState(v)
|
||||
persisted.write('languagePrefs', v)
|
||||
const s = fn(persisted.get('languagePrefs'))
|
||||
setState(s)
|
||||
persisted.write('languagePrefs', s)
|
||||
},
|
||||
[setState],
|
||||
)
|
||||
|
@ -30,11 +42,75 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
|
|||
})
|
||||
}, [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 (
|
||||
<stateContext.Provider value={state}>
|
||||
<setContext.Provider value={setStateWrapped}>
|
||||
{children}
|
||||
</setContext.Provider>
|
||||
<apiContext.Provider value={api}>{children}</apiContext.Provider>
|
||||
</stateContext.Provider>
|
||||
)
|
||||
}
|
||||
|
@ -43,32 +119,14 @@ export function useLanguagePrefs() {
|
|||
return React.useContext(stateContext)
|
||||
}
|
||||
|
||||
export function useSetLanguagePrefs() {
|
||||
return React.useContext(setContext)
|
||||
export function useLanguagePrefsApi() {
|
||||
return React.useContext(apiContext)
|
||||
}
|
||||
|
||||
export function getContentLanguages() {
|
||||
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[] {
|
||||
// filter out empty strings if exist
|
||||
return postLanguage.split(',').filter(Boolean)
|
||||
|
@ -77,46 +135,3 @@ export function toPostLanguages(postLanguage: string): string[] {
|
|||
export function hasPostLanguage(postLanguage: string, code2: string): boolean {
|
||||
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),
|
||||
}))
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue