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 colorScheme: persisted.Schema['colorScheme']
9 hue: persisted.Schema['hue']
10}
11type SetContext = {
12 setColorMode: (v: persisted.Schema['colorMode']) => void
13 setDarkTheme: (v: persisted.Schema['darkTheme']) => void
14 setColorScheme: (v: persisted.Schema['colorScheme']) => void
15 setHue: (v: persisted.Schema['hue']) => void
16}
17
18const stateContext = React.createContext<StateContext>({
19 colorMode: 'system',
20 darkTheme: 'dark',
21 colorScheme: 'witchsky',
22 hue: 0,
23})
24stateContext.displayName = 'ColorModeStateContext'
25const setContext = React.createContext<SetContext>({} as SetContext)
26setContext.displayName = 'ColorModeSetContext'
27
28export function Provider({children}: React.PropsWithChildren<{}>) {
29 const [colorMode, setColorMode] = React.useState(() =>
30 persisted.get('colorMode'),
31 )
32 const [darkTheme, setDarkTheme] = React.useState(() =>
33 persisted.get('darkTheme'),
34 )
35 const [colorScheme, setColorScheme] = React.useState(
36 persisted.get('colorScheme'),
37 )
38 const [hue, setHue] = React.useState(persisted.get('hue'))
39
40 const stateContextValue = React.useMemo(
41 () => ({
42 colorMode,
43 darkTheme,
44 colorScheme,
45 hue,
46 }),
47 [colorMode, darkTheme, colorScheme, hue],
48 )
49
50 const setContextValue = React.useMemo(
51 () => ({
52 setColorMode: (_colorMode: persisted.Schema['colorMode']) => {
53 setColorMode(_colorMode)
54 persisted.write('colorMode', _colorMode)
55 },
56 setDarkTheme: (_darkTheme: persisted.Schema['darkTheme']) => {
57 setDarkTheme(_darkTheme)
58 persisted.write('darkTheme', _darkTheme)
59 },
60 setColorScheme: (_colorScheme: persisted.Schema['colorScheme']) => {
61 setColorScheme(_colorScheme)
62 persisted.write('colorScheme', _colorScheme)
63 },
64 setHue: (_hue: persisted.Schema['hue']) => {
65 setHue(_hue)
66 persisted.write('hue', _hue)
67 },
68 }),
69 [],
70 )
71
72 React.useEffect(() => {
73 const unsub1 = persisted.onUpdate('darkTheme', nextDarkTheme => {
74 setDarkTheme(nextDarkTheme)
75 })
76 const unsub2 = persisted.onUpdate('colorMode', nextColorMode => {
77 setColorMode(nextColorMode)
78 })
79 const unsub3 = persisted.onUpdate('colorScheme', nextColorScheme => {
80 setColorScheme(nextColorScheme)
81 })
82 const unsub4 = persisted.onUpdate('hue', nextHue => {
83 setHue(nextHue)
84 })
85 return () => {
86 unsub1()
87 unsub2()
88 unsub3()
89 unsub4()
90 }
91 }, [])
92
93 return (
94 <stateContext.Provider value={stateContextValue}>
95 <setContext.Provider value={setContextValue}>
96 {children}
97 </setContext.Provider>
98 </stateContext.Provider>
99 )
100}
101
102export function useThemePrefs() {
103 return React.useContext(stateContext)
104}
105
106export function useSetThemePrefs() {
107 return React.useContext(setContext)
108}