diff --git a/gui/src/components/OnnxWeb.tsx b/gui/src/components/OnnxWeb.tsx index 6eee4329..a98da733 100644 --- a/gui/src/components/OnnxWeb.tsx +++ b/gui/src/components/OnnxWeb.tsx @@ -1,9 +1,11 @@ -import { doesExist } from '@apextoaster/js-utils'; +import { doesExist, mustExist } from '@apextoaster/js-utils'; import { TabContext, TabList, TabPanel } from '@mui/lab'; -import { Box, Container, Divider, Tab } from '@mui/material'; +import { Box, Container, Divider, PaletteMode, Tab, useMediaQuery, CssBaseline } from '@mui/material'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; import * as React from 'react'; import { useHash } from 'react-use/lib/useHash'; +import { useStore } from 'zustand'; import { ModelControl } from './control/ModelControl.js'; import { ImageHistory } from './ImageHistory.js'; import { Logo } from './Logo.js'; @@ -14,49 +16,69 @@ import { Settings } from './tab/Settings.js'; import { Txt2Img } from './tab/Txt2Img.js'; import { Upscale } from './tab/Upscale.js'; import { getTab, TAB_LABELS } from './utils.js'; +import { StateContext } from '../state.js'; export function OnnxWeb() { + /* checks for system light/dark mode preference */ + const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); + const state = useStore(mustExist(React.useContext(StateContext))); + + const theme = React.useMemo( + () => { + if (state.theme === '') { + if (prefersDarkMode) { + return createTheme({ + palette: { + mode: 'dark' + }, + }); + } else { + return createTheme({ + palette: { + mode: 'light' + }, + }); + } + } else { + return createTheme({ + palette: { + mode: state.theme as PaletteMode + }, + }); + } + }, + [prefersDarkMode, state.theme], + ); + const [hash, setHash] = useHash(); return ( - - - - - - - - - - { - setHash(idx); - }}> - {TAB_LABELS.map((name) => )} - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + { + setHash(idx); + }}> + {TAB_LABELS.map((name) => )} + + + + + + + + + + + + ); -} +} \ No newline at end of file diff --git a/gui/src/components/tab/Settings.tsx b/gui/src/components/tab/Settings.tsx index 030a8880..195dab46 100644 --- a/gui/src/components/tab/Settings.tsx +++ b/gui/src/components/tab/Settings.tsx @@ -1,6 +1,6 @@ import { doesExist, mustExist } from '@apextoaster/js-utils'; -import { Refresh } from '@mui/icons-material'; -import { Alert, Button, Stack, TextField } from '@mui/material'; +import { Refresh, Brightness4, Brightness7 } from '@mui/icons-material'; +import { Alert, Button, Stack, Switch, TextField } from '@mui/material'; import * as React from 'react'; import { useContext, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -80,6 +80,13 @@ export function Settings() { {t('setting.loadState')} + { + if (state.theme === 'light') { + state.setTheme('dark'); + } else { + state.setTheme('light'); + } + }} /> diff --git a/gui/src/state.ts b/gui/src/state.ts index d9e8cbbd..4ec024b2 100644 --- a/gui/src/state.ts +++ b/gui/src/state.ts @@ -43,8 +43,10 @@ interface BrushSlice { interface DefaultSlice { defaults: TabState; + theme: string; setDefaults(param: Partial): void; + setTheme(theme: string): void; } interface HistorySlice { @@ -488,6 +490,7 @@ export function createStateSlices(server: ServerParams) { defaults: { ...base, }, + theme: '', setDefaults(params) { set((prev) => ({ defaults: { @@ -496,6 +499,11 @@ export function createStateSlices(server: ServerParams) { } })); }, + setTheme(theme) { + set((prev) => ({ + theme, + })); + } }); const createModelSlice: Slice = (set) => ({