2022-02-12 14:51:01 +01:00
|
|
|
import React, {
|
|
|
|
createContext,
|
|
|
|
useContext,
|
|
|
|
useEffect,
|
|
|
|
useRef,
|
|
|
|
useState
|
|
|
|
} from 'react'
|
2021-01-02 17:55:08 +01:00
|
|
|
import { Appearance } from 'react-native'
|
2020-11-29 18:08:31 +01:00
|
|
|
import { useSelector } from 'react-redux'
|
2022-02-12 14:51:01 +01:00
|
|
|
import { ColorDefinitions, getColors, Theme } from '@utils/styles/themes'
|
|
|
|
import {
|
|
|
|
getSettingsDarkTheme,
|
|
|
|
getSettingsTheme,
|
|
|
|
SettingsState
|
|
|
|
} from '@utils/slices/settingsSlice'
|
2021-01-02 17:55:08 +01:00
|
|
|
import { throttle } from 'lodash'
|
2020-11-23 00:07:32 +01:00
|
|
|
|
2020-11-29 18:08:31 +01:00
|
|
|
type ContextType = {
|
2020-11-23 00:07:32 +01:00
|
|
|
mode: 'light' | 'dark'
|
2022-02-12 14:51:01 +01:00
|
|
|
theme: Theme
|
|
|
|
colors: { [key in ColorDefinitions]: string }
|
2020-11-29 18:08:31 +01:00
|
|
|
}
|
|
|
|
|
2021-03-27 00:02:32 +01:00
|
|
|
const ManageThemeContext = createContext<ContextType>({
|
2020-11-29 18:08:31 +01:00
|
|
|
mode: 'light',
|
2022-02-12 14:51:01 +01:00
|
|
|
theme: 'light',
|
|
|
|
colors: getColors('light')
|
2020-11-23 00:07:32 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
export const useTheme = () => useContext(ManageThemeContext)
|
|
|
|
|
2021-01-12 00:12:44 +01:00
|
|
|
const useColorSchemeDelay = (delay = 500) => {
|
2021-01-02 17:55:08 +01:00
|
|
|
const [colorScheme, setColorScheme] = React.useState(
|
|
|
|
Appearance.getColorScheme()
|
|
|
|
)
|
|
|
|
const onColorSchemeChange = React.useCallback(
|
|
|
|
throttle(
|
|
|
|
({ colorScheme }) => {
|
|
|
|
setColorScheme(colorScheme)
|
|
|
|
},
|
|
|
|
delay,
|
|
|
|
{
|
|
|
|
leading: false
|
|
|
|
}
|
|
|
|
),
|
|
|
|
[]
|
|
|
|
)
|
|
|
|
React.useEffect(() => {
|
2022-02-04 00:43:22 +01:00
|
|
|
const listener = Appearance.addChangeListener(onColorSchemeChange)
|
2021-01-02 17:55:08 +01:00
|
|
|
return () => {
|
|
|
|
onColorSchemeChange.cancel()
|
2022-02-04 00:43:22 +01:00
|
|
|
listener.remove()
|
2021-01-02 17:55:08 +01:00
|
|
|
}
|
|
|
|
}, [])
|
|
|
|
return colorScheme
|
|
|
|
}
|
|
|
|
|
2022-02-12 14:51:01 +01:00
|
|
|
const determineTheme = (
|
|
|
|
osTheme: 'light' | 'dark' | null | undefined,
|
|
|
|
userTheme: SettingsState['theme'],
|
|
|
|
darkTheme: SettingsState['darkTheme']
|
|
|
|
): 'light' | 'dark_lighter' | 'dark_darker' => {
|
|
|
|
enum DarkTheme {
|
|
|
|
lighter = 'dark_lighter',
|
|
|
|
darker = 'dark_darker'
|
|
|
|
}
|
|
|
|
const determineDarkTheme = DarkTheme[darkTheme]
|
|
|
|
switch (userTheme) {
|
|
|
|
case 'auto':
|
|
|
|
switch (osTheme) {
|
|
|
|
case 'dark':
|
|
|
|
return determineDarkTheme
|
|
|
|
default:
|
|
|
|
return 'light'
|
|
|
|
}
|
|
|
|
case 'light':
|
|
|
|
return 'light'
|
|
|
|
case 'dark':
|
|
|
|
return determineDarkTheme
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-23 00:07:32 +01:00
|
|
|
const ThemeManager: React.FC = ({ children }) => {
|
2021-01-02 17:55:08 +01:00
|
|
|
const osTheme = useColorSchemeDelay()
|
2020-11-29 18:08:31 +01:00
|
|
|
const userTheme = useSelector(getSettingsTheme)
|
2022-02-12 14:51:01 +01:00
|
|
|
const darkTheme = useSelector(getSettingsDarkTheme)
|
2020-11-29 18:08:31 +01:00
|
|
|
|
2022-02-12 14:51:01 +01:00
|
|
|
const mode = useRef(userTheme === 'auto' ? osTheme || 'light' : userTheme)
|
|
|
|
const [theme, setTheme] = useState<Theme>(
|
|
|
|
determineTheme(osTheme, userTheme, darkTheme)
|
|
|
|
)
|
2020-11-23 00:07:32 +01:00
|
|
|
|
|
|
|
useEffect(() => {
|
2022-02-12 14:51:01 +01:00
|
|
|
mode.current = userTheme === 'auto' ? osTheme || 'light' : userTheme
|
|
|
|
}, [userTheme])
|
|
|
|
useEffect(() => {
|
|
|
|
setTheme(determineTheme(osTheme, userTheme, darkTheme))
|
|
|
|
}, [osTheme, userTheme, darkTheme])
|
2020-11-23 00:07:32 +01:00
|
|
|
|
|
|
|
return (
|
|
|
|
<ManageThemeContext.Provider
|
|
|
|
value={{
|
2022-02-12 14:51:01 +01:00
|
|
|
mode: mode.current,
|
|
|
|
theme,
|
|
|
|
colors: getColors(theme)
|
2020-11-23 00:07:32 +01:00
|
|
|
}}
|
|
|
|
>
|
|
|
|
{children}
|
|
|
|
</ManageThemeContext.Provider>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default ThemeManager
|