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(() =>
24 persisted.get('colorMode'),
25 )
26 const [darkTheme, setDarkTheme] = React.useState(() =>
27 persisted.get('darkTheme'),
28 )
29
30 const stateContextValue = React.useMemo(
31 () => ({
32 colorMode,
33 darkTheme,
34 }),
35 [colorMode, darkTheme],
36 )
37
38 const setContextValue = React.useMemo(
39 () => ({
40 setColorMode: (_colorMode: persisted.Schema['colorMode']) => {
41 setColorMode(_colorMode)
42 persisted.write('colorMode', _colorMode)
43 },
44 setDarkTheme: (_darkTheme: persisted.Schema['darkTheme']) => {
45 setDarkTheme(_darkTheme)
46 persisted.write('darkTheme', _darkTheme)
47 },
48 }),
49 [],
50 )
51
52 React.useEffect(() => {
53 const unsub1 = persisted.onUpdate('darkTheme', nextDarkTheme => {
54 setDarkTheme(nextDarkTheme)
55 })
56 const unsub2 = persisted.onUpdate('colorMode', nextColorMode => {
57 setColorMode(nextColorMode)
58 })
59 return () => {
60 unsub1()
61 unsub2()
62 }
63 }, [])
64
65 return (
66 <stateContext.Provider value={stateContextValue}>
67 <setContext.Provider value={setContextValue}>
68 {children}
69 </setContext.Provider>
70 </stateContext.Provider>
71 )
72}
73
74export function useThemePrefs() {
75 return React.useContext(stateContext)
76}
77
78export function useSetThemePrefs() {
79 return React.useContext(setContext)
80}