* Add fast path for guaranteed noop updates * Change persisted.onUpdate() API to take a key * Implement granular broadcast listeners
74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
import React from 'react'
|
|
|
|
import * as persisted from '#/state/persisted'
|
|
|
|
type StateContext = {
|
|
colorMode: persisted.Schema['colorMode']
|
|
darkTheme: persisted.Schema['darkTheme']
|
|
}
|
|
type SetContext = {
|
|
setColorMode: (v: persisted.Schema['colorMode']) => void
|
|
setDarkTheme: (v: persisted.Schema['darkTheme']) => void
|
|
}
|
|
|
|
const stateContext = React.createContext<StateContext>({
|
|
colorMode: 'system',
|
|
darkTheme: 'dark',
|
|
})
|
|
const setContext = React.createContext<SetContext>({} as SetContext)
|
|
|
|
export function Provider({children}: React.PropsWithChildren<{}>) {
|
|
const [colorMode, setColorMode] = React.useState(persisted.get('colorMode'))
|
|
const [darkTheme, setDarkTheme] = React.useState(persisted.get('darkTheme'))
|
|
|
|
const stateContextValue = React.useMemo(
|
|
() => ({
|
|
colorMode,
|
|
darkTheme,
|
|
}),
|
|
[colorMode, darkTheme],
|
|
)
|
|
|
|
const setContextValue = React.useMemo(
|
|
() => ({
|
|
setColorMode: (_colorMode: persisted.Schema['colorMode']) => {
|
|
setColorMode(_colorMode)
|
|
persisted.write('colorMode', _colorMode)
|
|
},
|
|
setDarkTheme: (_darkTheme: persisted.Schema['darkTheme']) => {
|
|
setDarkTheme(_darkTheme)
|
|
persisted.write('darkTheme', _darkTheme)
|
|
},
|
|
}),
|
|
[],
|
|
)
|
|
|
|
React.useEffect(() => {
|
|
const unsub1 = persisted.onUpdate('darkTheme', nextDarkTheme => {
|
|
setDarkTheme(nextDarkTheme)
|
|
})
|
|
const unsub2 = persisted.onUpdate('colorMode', nextColorMode => {
|
|
setColorMode(nextColorMode)
|
|
})
|
|
return () => {
|
|
unsub1()
|
|
unsub2()
|
|
}
|
|
}, [])
|
|
|
|
return (
|
|
<stateContext.Provider value={stateContextValue}>
|
|
<setContext.Provider value={setContextValue}>
|
|
{children}
|
|
</setContext.Provider>
|
|
</stateContext.Provider>
|
|
)
|
|
}
|
|
|
|
export function useThemePrefs() {
|
|
return React.useContext(stateContext)
|
|
}
|
|
|
|
export function useSetThemePrefs() {
|
|
return React.useContext(setContext)
|
|
}
|