about summary refs log tree commit diff
path: root/src/state/preferences
diff options
context:
space:
mode:
Diffstat (limited to 'src/state/preferences')
-rw-r--r--src/state/preferences/index.tsx2
-rw-r--r--src/state/preferences/languages.tsx159
2 files changed, 88 insertions, 73 deletions
diff --git a/src/state/preferences/index.tsx b/src/state/preferences/index.tsx
index 50cb86c65..1f4348cfc 100644
--- a/src/state/preferences/index.tsx
+++ b/src/state/preferences/index.tsx
@@ -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,
diff --git a/src/state/preferences/languages.tsx b/src/state/preferences/languages.tsx
index 49b63550d..95cf67417 100644
--- a/src/state/preferences/languages.tsx
+++ b/src/state/preferences/languages.tsx
@@ -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),
-  }))
-}