added theme dark mode toggle in settings
parent
dfcabbe0ce
commit
4e58eebd4e
|
@ -13,6 +13,7 @@
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@flare/js-utils": "^1.0.3",
|
||||||
"@flare/tuitio-client-react": "^1.0.1",
|
"@flare/tuitio-client-react": "^1.0.1",
|
||||||
"@material-ui/core": "^4.11.2",
|
"@material-ui/core": "^4.11.2",
|
||||||
"@material-ui/icons": "^4.11.2",
|
"@material-ui/icons": "^4.11.2",
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useContext, useEffect, useCallback } from "react";
|
||||||
import {
|
import {
|
||||||
ApplicationStateContext,
|
ApplicationStateContext,
|
||||||
ApplicationDispatchContext
|
ApplicationDispatchContext
|
||||||
} from "../../../state/ApplicationContexts";
|
} from "../../../state/contexts";
|
||||||
import useApi from "../../../api";
|
import useApi from "../../../api";
|
||||||
import MachinesList from "./MachinesList";
|
import MachinesList from "./MachinesList";
|
||||||
import PageTitle from "../../../components/common/PageTitle";
|
import PageTitle from "../../../components/common/PageTitle";
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import LanguageContainer from "./language/LanguageContainer";
|
import LanguageContainer from "./language/LanguageContainer";
|
||||||
|
import ThemeSettings from "./ThemeSettings";
|
||||||
|
|
||||||
const SettingsContainer = () => {
|
const SettingsContainer = () => {
|
||||||
return <LanguageContainer />;
|
return (
|
||||||
|
<>
|
||||||
|
<LanguageContainer />
|
||||||
|
<ThemeSettings />
|
||||||
|
</>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SettingsContainer;
|
export default SettingsContainer;
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import React from "react";
|
||||||
|
import { useApplicationTheme } from "../../../providers/ThemeProvider";
|
||||||
|
import { Switch } from "@material-ui/core";
|
||||||
|
|
||||||
|
const ThemeSettings = () => {
|
||||||
|
const { isDark, onDarkModeChanged } = useApplicationTheme();
|
||||||
|
|
||||||
|
const handleChange = event => {
|
||||||
|
const { checked } = event.target;
|
||||||
|
onDarkModeChanged(checked);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Switch
|
||||||
|
checked={isDark}
|
||||||
|
onChange={handleChange}
|
||||||
|
color="primary"
|
||||||
|
name="app-theme-switch"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ThemeSettings;
|
|
@ -1,7 +1,6 @@
|
||||||
import React, { Suspense } from "react";
|
import React, { Suspense } from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import { ThemeProvider } from "@material-ui/styles";
|
import ThemeProvider from "./providers/ThemeProvider";
|
||||||
import Themes from "./themes";
|
|
||||||
import CssBaseline from "@material-ui/core/CssBaseline";
|
import CssBaseline from "@material-ui/core/CssBaseline";
|
||||||
import App from "./components/App";
|
import App from "./components/App";
|
||||||
import { TuitioProvider } from "@flare/tuitio-client-react";
|
import { TuitioProvider } from "@flare/tuitio-client-react";
|
||||||
|
@ -12,7 +11,7 @@ import "./utils/i18n";
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<TuitioProvider tuitioUrl={process.env.REACT_APP_TUITIO_URL}>
|
<TuitioProvider tuitioUrl={process.env.REACT_APP_TUITIO_URL}>
|
||||||
<ApplicationStateProvider>
|
<ApplicationStateProvider>
|
||||||
<ThemeProvider theme={Themes.default}>
|
<ThemeProvider>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<Suspense fallback={<div>Loading...</div>}>
|
<Suspense fallback={<div>Loading...</div>}>
|
||||||
<ToastProvider>
|
<ToastProvider>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from "prop-types";
|
||||||
import {
|
import {
|
||||||
ApplicationStateContext,
|
ApplicationStateContext,
|
||||||
ApplicationDispatchContext
|
ApplicationDispatchContext
|
||||||
} from "../state/ApplicationContexts";
|
} from "../state/contexts";
|
||||||
import {
|
import {
|
||||||
reducer,
|
reducer,
|
||||||
dispatchActions as reducerDispatchActions
|
dispatchActions as reducerDispatchActions
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
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;
|
|
@ -1,12 +1,7 @@
|
||||||
import defaultTheme from "./default";
|
import defaultTheme from "./default";
|
||||||
import { createTheme } from "@material-ui/core/styles";
|
import { createTheme } from "@material-ui/core/styles";
|
||||||
|
|
||||||
const prefersDarkMode = false;
|
|
||||||
|
|
||||||
const overrides = {
|
const overrides = {
|
||||||
palette: {
|
|
||||||
type: prefersDarkMode ? "dark" : "light"
|
|
||||||
},
|
|
||||||
typography: {
|
typography: {
|
||||||
h1: {
|
h1: {
|
||||||
fontSize: "3rem"
|
fontSize: "3rem"
|
||||||
|
@ -29,12 +24,16 @@ const overrides = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const themes = {
|
const getThemes = darkMode => {
|
||||||
default: createTheme({
|
const type = darkMode ? "dark" : "light";
|
||||||
...defaultTheme,
|
|
||||||
...overrides,
|
return {
|
||||||
palette: { ...defaultTheme.palette, ...overrides.palette }
|
default: createTheme({
|
||||||
})
|
...defaultTheme,
|
||||||
|
...overrides,
|
||||||
|
palette: { ...defaultTheme.palette, type }
|
||||||
|
})
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default themes;
|
export { getThemes };
|
||||||
|
|
Loading…
Reference in New Issue