1
0
Fork 0

add dark mode with toggle and system preference

This commit is contained in:
BZLibby 2023-02-23 17:23:49 -06:00
parent fcc04982b1
commit 48f1b745fe
3 changed files with 80 additions and 43 deletions

View File

@ -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 { 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 * as React from 'react';
import { useHash } from 'react-use/lib/useHash'; import { useHash } from 'react-use/lib/useHash';
import { useStore } from 'zustand';
import { ModelControl } from './control/ModelControl.js'; import { ModelControl } from './control/ModelControl.js';
import { ImageHistory } from './ImageHistory.js'; import { ImageHistory } from './ImageHistory.js';
import { Logo } from './Logo.js'; import { Logo } from './Logo.js';
@ -14,49 +16,69 @@ import { Settings } from './tab/Settings.js';
import { Txt2Img } from './tab/Txt2Img.js'; import { Txt2Img } from './tab/Txt2Img.js';
import { Upscale } from './tab/Upscale.js'; import { Upscale } from './tab/Upscale.js';
import { getTab, TAB_LABELS } from './utils.js'; import { getTab, TAB_LABELS } from './utils.js';
import { StateContext } from '../state.js';
export function OnnxWeb() { 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(); const [hash, setHash] = useHash();
return ( return (
<Container> <ThemeProvider theme={theme}>
<Box sx={{ my: 4 }}> <CssBaseline />
<Logo /> <Container>
</Box> <Box sx={{ my: 4 }}>
<Box sx={{ mx: 4, my: 4 }}> <Logo />
<ModelControl />
</Box>
<TabContext value={getTab(hash)}>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<TabList onChange={(_e, idx) => {
setHash(idx);
}}>
{TAB_LABELS.map((name) => <Tab key={name} label={name} value={name} />)}
</TabList>
</Box> </Box>
<TabPanel value='txt2img'> <Box sx={{ mx: 4, my: 4 }}>
<Txt2Img /> <ModelControl />
</TabPanel> </Box>
<TabPanel value='img2img'> <TabContext value={getTab(hash)}>
<Img2Img /> <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
</TabPanel> <TabList onChange={(_e, idx) => {
<TabPanel value='inpaint'> setHash(idx);
<Inpaint /> }}>
</TabPanel> {TAB_LABELS.map((name) => <Tab key={name} label={name} value={name} />)}
<TabPanel value='upscale'> </TabList>
<Upscale /> </Box>
</TabPanel> <Box sx={{ mx: 4, my: 4 }}>
<TabPanel value='blend'> <ModelControl />
<Blend /> </Box>
</TabPanel> </TabContext>
<TabPanel value='settings'> <Divider variant='middle' />
<Settings /> <Box sx={{ mx: 4, my: 4 }}>
</TabPanel> <ImageHistory />
</TabContext> </Box>
<Divider variant='middle' /> </Container>
<Box sx={{ mx: 4, my: 4 }}> </ThemeProvider>
<ImageHistory />
</Box>
</Container>
); );
} }

View File

@ -1,6 +1,6 @@
import { doesExist, mustExist } from '@apextoaster/js-utils'; import { doesExist, mustExist } from '@apextoaster/js-utils';
import { Refresh } from '@mui/icons-material'; import { Refresh, Brightness4, Brightness7 } from '@mui/icons-material';
import { Alert, Button, Stack, TextField } from '@mui/material'; import { Alert, Button, Stack, Switch, TextField } from '@mui/material';
import * as React from 'react'; import * as React from 'react';
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -80,6 +80,13 @@ export function Settings() {
{t('setting.loadState')} {t('setting.loadState')}
</Button> </Button>
</Stack> </Stack>
<Switch onClick={() => {
if (state.theme === 'light') {
state.setTheme('dark');
} else {
state.setTheme('light');
}
}} />
<Stack direction='row' spacing={2}> <Stack direction='row' spacing={2}>
<Button onClick={() => state.resetTxt2Img()} color='warning'>{t('setting.reset.txt2img')}</Button> <Button onClick={() => state.resetTxt2Img()} color='warning'>{t('setting.reset.txt2img')}</Button>
<Button onClick={() => state.resetImg2Img()} color='warning'>{t('setting.reset.img2img')}</Button> <Button onClick={() => state.resetImg2Img()} color='warning'>{t('setting.reset.img2img')}</Button>

View File

@ -43,8 +43,10 @@ interface BrushSlice {
interface DefaultSlice { interface DefaultSlice {
defaults: TabState<BaseImgParams>; defaults: TabState<BaseImgParams>;
theme: string;
setDefaults(param: Partial<BaseImgParams>): void; setDefaults(param: Partial<BaseImgParams>): void;
setTheme(theme: string): void;
} }
interface HistorySlice { interface HistorySlice {
@ -488,6 +490,7 @@ export function createStateSlices(server: ServerParams) {
defaults: { defaults: {
...base, ...base,
}, },
theme: '',
setDefaults(params) { setDefaults(params) {
set((prev) => ({ set((prev) => ({
defaults: { defaults: {
@ -496,6 +499,11 @@ export function createStateSlices(server: ServerParams) {
} }
})); }));
}, },
setTheme(theme) {
set((prev) => ({
theme,
}));
}
}); });
const createModelSlice: Slice<ModelSlice> = (set) => ({ const createModelSlice: Slice<ModelSlice> = (set) => ({