83 lines
2.2 KiB
JavaScript
83 lines
2.2 KiB
JavaScript
import React, { useReducer, useMemo, useContext } from "react";
|
|
import PropTypes from "prop-types";
|
|
import { ThemeProvider as MuiThemeProvider } from "@material-ui/styles";
|
|
import { localStorage } from "@flare/js-utils";
|
|
import { getThemes } from "../themes";
|
|
|
|
const ApplicationThemeContext = React.createContext();
|
|
const LOCAL_STORAGE_COLOR_SCHEME_KEY = "network-resurrector-color-scheme";
|
|
|
|
const COLOR_SCHEME = {
|
|
LIGHT: "light",
|
|
DARK: "dark"
|
|
};
|
|
|
|
const colorScheme = localStorage.getItem(LOCAL_STORAGE_COLOR_SCHEME_KEY);
|
|
const prefersDarkMode = window.matchMedia(
|
|
"(prefers-color-scheme: dark)"
|
|
).matches;
|
|
|
|
const initialState = {
|
|
scheme:
|
|
colorScheme ?? (prefersDarkMode ? COLOR_SCHEME.DARK : COLOR_SCHEME.LIGHT)
|
|
};
|
|
|
|
const reducer = (state = initialState, action) => {
|
|
switch (action.type) {
|
|
case "onColorSchemeChanged": {
|
|
return {
|
|
...state,
|
|
scheme: action.scheme
|
|
};
|
|
}
|
|
default: {
|
|
return state;
|
|
}
|
|
}
|
|
};
|
|
|
|
const dispatchActions = dispatch => ({
|
|
onColorSchemeChanged: scheme => {
|
|
dispatch({ type: "onColorSchemeChanged", scheme });
|
|
localStorage.setItem(LOCAL_STORAGE_COLOR_SCHEME_KEY, scheme);
|
|
}
|
|
});
|
|
|
|
const useApplicationTheme = () => {
|
|
const { state, actions } = useContext(ApplicationThemeContext);
|
|
const { onColorSchemeChanged } = actions;
|
|
|
|
const { scheme } = state;
|
|
const onDarkModeChanged = active =>
|
|
onColorSchemeChanged(active ? COLOR_SCHEME.DARK : COLOR_SCHEME.LIGHT);
|
|
|
|
return { isDark: scheme === COLOR_SCHEME.DARK, onDarkModeChanged };
|
|
};
|
|
|
|
const ThemeProvider = ({ children }) => {
|
|
const [state, dispatch] = useReducer(reducer, initialState);
|
|
const actions = useMemo(() => dispatchActions(dispatch), [dispatch]);
|
|
const themes = useMemo(
|
|
() => getThemes(state.scheme === COLOR_SCHEME.DARK),
|
|
[state.scheme]
|
|
);
|
|
|
|
return (
|
|
<ApplicationThemeContext.Provider
|
|
value={{
|
|
state,
|
|
actions
|
|
}}
|
|
>
|
|
<MuiThemeProvider theme={themes.default}>{children}</MuiThemeProvider>
|
|
</ApplicationThemeContext.Provider>
|
|
);
|
|
};
|
|
|
|
ThemeProvider.propTypes = {
|
|
children: PropTypes.node.isRequired
|
|
};
|
|
|
|
export { ThemeProvider, ApplicationThemeContext, useApplicationTheme };
|
|
export default ThemeProvider;
|