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(persisted.get('colorMode'))
30 const [darkTheme, setDarkTheme] = React.useState(persisted.get('darkTheme'))
31 const [colorScheme, setColorScheme] = React.useState(
32 persisted.get('colorScheme'),
33 )
34 const [hue, setHue] = React.useState(persisted.get('hue'))
35
36 const stateContextValue = React.useMemo(
37 () => ({
38 colorMode,
39 darkTheme,
40 colorScheme,
41 hue,
42 }),
43 [colorMode, darkTheme, colorScheme, hue],
44 )
45
46 const setContextValue = React.useMemo(
47 () => ({
48 setColorMode: (_colorMode: persisted.Schema['colorMode']) => {
49 setColorMode(_colorMode)
50 persisted.write('colorMode', _colorMode)
51 },
52 setDarkTheme: (_darkTheme: persisted.Schema['darkTheme']) => {
53 setDarkTheme(_darkTheme)
54 persisted.write('darkTheme', _darkTheme)
55 },
56 setColorScheme: (_colorScheme: persisted.Schema['colorScheme']) => {
57 setColorScheme(_colorScheme)
58 persisted.write('colorScheme', _colorScheme)
59 },
60 setHue: (_hue: persisted.Schema['hue']) => {
61 setHue(_hue)
62 persisted.write('hue', _hue)
63 },
64 }),
65 [],
66 )
67
68 React.useEffect(() => {
69 const unsub1 = persisted.onUpdate('darkTheme', nextDarkTheme => {
70 setDarkTheme(nextDarkTheme)
71 })
72 const unsub2 = persisted.onUpdate('colorMode', nextColorMode => {
73 setColorMode(nextColorMode)
74 })
75 const unsub3 = persisted.onUpdate('colorScheme', nextColorScheme => {
76 setColorScheme(nextColorScheme)
77 })
78 const unsub4 = persisted.onUpdate('hue', nextHue => {
79 setHue(nextHue)
80 })
81 return () => {
82 unsub1()
83 unsub2()
84 unsub3()
85 unsub4()
86 }
87 }, [])
88
89 return (
90 <stateContext.Provider value={stateContextValue}>
91 <setContext.Provider value={setContextValue}>
92 {children}
93 </setContext.Provider>
94 </stateContext.Provider>
95 )
96}
97
98export function useThemePrefs() {
99 return React.useContext(stateContext)
100}
101
102export function useSetThemePrefs() {
103 return React.useContext(setContext)
104}