forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import React from 'react'
2
3import * as persisted from '#/state/persisted'
4
5type StateContext = {
6 colorMode: persisted.Schema['colorMode']
7 darkTheme: persisted.Schema['darkTheme']
8}
9type SetContext = {
10 setColorMode: (v: persisted.Schema['colorMode']) => void
11 setDarkTheme: (v: persisted.Schema['darkTheme']) => void
12}
13
14const stateContext = React.createContext<StateContext>({
15 colorMode: 'system',
16 darkTheme: 'dark',
17})
18stateContext.displayName = 'ColorModeStateContext'
19const setContext = React.createContext<SetContext>({} as SetContext)
20setContext.displayName = 'ColorModeSetContext'
21
22export function Provider({children}: React.PropsWithChildren<{}>) {
23 const [colorMode, setColorMode] = React.useState(persisted.get('colorMode'))
24 const [darkTheme, setDarkTheme] = React.useState(persisted.get('darkTheme'))
25
26 const stateContextValue = React.useMemo(
27 () => ({
28 colorMode,
29 darkTheme,
30 }),
31 [colorMode, darkTheme],
32 )
33
34 const setContextValue = React.useMemo(
35 () => ({
36 setColorMode: (_colorMode: persisted.Schema['colorMode']) => {
37 setColorMode(_colorMode)
38 persisted.write('colorMode', _colorMode)
39 },
40 setDarkTheme: (_darkTheme: persisted.Schema['darkTheme']) => {
41 setDarkTheme(_darkTheme)
42 persisted.write('darkTheme', _darkTheme)
43 },
44 }),
45 [],
46 )
47
48 React.useEffect(() => {
49 const unsub1 = persisted.onUpdate('darkTheme', nextDarkTheme => {
50 setDarkTheme(nextDarkTheme)
51 })
52 const unsub2 = persisted.onUpdate('colorMode', nextColorMode => {
53 setColorMode(nextColorMode)
54 })
55 return () => {
56 unsub1()
57 unsub2()
58 }
59 }, [])
60
61 return (
62 <stateContext.Provider value={stateContextValue}>
63 <setContext.Provider value={setContextValue}>
64 {children}
65 </setContext.Provider>
66 </stateContext.Provider>
67 )
68}
69
70export function useThemePrefs() {
71 return React.useContext(stateContext)
72}
73
74export function useSetThemePrefs() {
75 return React.useContext(setContext)
76}