From 48f1b745fe86fd2d58bb8fc0439087d67153d96d Mon Sep 17 00:00:00 2001 From: BZLibby Date: Thu, 23 Feb 2023 17:23:49 -0600 Subject: [PATCH 1/4] add dark mode with toggle and system preference --- gui/src/components/OnnxWeb.tsx | 104 +++++++++++++++++----------- gui/src/components/tab/Settings.tsx | 11 ++- gui/src/state.ts | 8 +++ 3 files changed, 80 insertions(+), 43 deletions(-) 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) => ({ From d61268b3a00b3421ccbae3fcd5c117b2f608f2f2 Mon Sep 17 00:00:00 2001 From: BZLibby Date: Thu, 23 Feb 2023 17:23:49 -0600 Subject: [PATCH 2/4] add dark mode with toggle and system preference --- gui/src/components/OnnxWeb.tsx | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/gui/src/components/OnnxWeb.tsx b/gui/src/components/OnnxWeb.tsx index a98da733..a3aa6667 100644 --- a/gui/src/components/OnnxWeb.tsx +++ b/gui/src/components/OnnxWeb.tsx @@ -1,10 +1,14 @@ import { doesExist, mustExist } from '@apextoaster/js-utils'; +import { doesExist, mustExist } from '@apextoaster/js-utils'; import { TabContext, TabList, TabPanel } from '@mui/lab'; import { Box, Container, Divider, PaletteMode, Tab, useMediaQuery, CssBaseline } from '@mui/material'; import { createTheme, ThemeProvider } from '@mui/material/styles'; +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 { useStore } from 'zustand'; import { ModelControl } from './control/ModelControl.js'; import { ImageHistory } from './ImageHistory.js'; @@ -15,6 +19,7 @@ import { Inpaint } from './tab/Inpaint.js'; import { Settings } from './tab/Settings.js'; import { Txt2Img } from './tab/Txt2Img.js'; import { Upscale } from './tab/Upscale.js'; +import { StateContext } from '../state.js'; import { getTab, TAB_LABELS } from './utils.js'; import { StateContext } from '../state.js'; @@ -50,6 +55,37 @@ export function OnnxWeb() { [prefersDarkMode, state.theme], ); + /* 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 ( From 6bb815cccf402a9a9a5f0f31f6fd670655835fa3 Mon Sep 17 00:00:00 2001 From: BZLibby Date: Wed, 5 Apr 2023 19:31:37 -0500 Subject: [PATCH 3/4] use system theme when the theme is not set --- gui/src/components/OnnxWeb.tsx | 79 ++++------------------------- gui/src/components/tab/Settings.tsx | 25 +++++---- gui/src/components/utils.ts | 10 ++++ gui/src/strings/de.ts | 1 + gui/src/strings/en.ts | 1 + gui/src/strings/es.ts | 1 + gui/src/strings/fr.ts | 1 + gui/src/utils.ts | 2 +- 8 files changed, 41 insertions(+), 79 deletions(-) diff --git a/gui/src/components/OnnxWeb.tsx b/gui/src/components/OnnxWeb.tsx index a3aa6667..c6df1eee 100644 --- a/gui/src/components/OnnxWeb.tsx +++ b/gui/src/components/OnnxWeb.tsx @@ -1,88 +1,29 @@ -import { doesExist, mustExist } from '@apextoaster/js-utils'; -import { doesExist, mustExist } from '@apextoaster/js-utils'; -import { TabContext, TabList, TabPanel } from '@mui/lab'; -import { Box, Container, Divider, PaletteMode, Tab, useMediaQuery, CssBaseline } from '@mui/material'; -import { createTheme, ThemeProvider } from '@mui/material/styles'; +import { mustExist } from '@apextoaster/js-utils'; +import { TabContext, TabList } from '@mui/lab'; import { Box, Container, Divider, PaletteMode, Tab, useMediaQuery, CssBaseline } from '@mui/material'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import * as React from 'react'; +import { useContext, useMemo } from 'react'; import { useHash } from 'react-use/lib/useHash'; -import { useStore } from 'zustand'; import { useStore } from 'zustand'; import { ModelControl } from './control/ModelControl.js'; import { ImageHistory } from './ImageHistory.js'; import { Logo } from './Logo.js'; -import { Blend } from './tab/Blend.js'; -import { Img2Img } from './tab/Img2Img.js'; -import { Inpaint } from './tab/Inpaint.js'; -import { Settings } from './tab/Settings.js'; -import { Txt2Img } from './tab/Txt2Img.js'; -import { Upscale } from './tab/Upscale.js'; -import { StateContext } from '../state.js'; -import { getTab, TAB_LABELS } from './utils.js'; import { StateContext } from '../state.js'; +import { getTheme, getTab, TAB_LABELS } from './utils.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 state = useStore(mustExist(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 - }, - }); + const theme = useMemo( + () => createTheme({ + palette: { + mode: getTheme(state.theme, prefersDarkMode) as PaletteMode } - }, - [prefersDarkMode, state.theme], - ); - - /* 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], ); diff --git a/gui/src/components/tab/Settings.tsx b/gui/src/components/tab/Settings.tsx index 195dab46..25677ad2 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, Brightness4, Brightness7 } from '@mui/icons-material'; -import { Alert, Button, Stack, Switch, TextField } from '@mui/material'; +import { Refresh } from '@mui/icons-material'; +import { Alert, Button, FormControlLabel, Stack, Switch, TextField, useMediaQuery } from '@mui/material'; import * as React from 'react'; import { useContext, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -8,6 +8,7 @@ import { useStore } from 'zustand'; import { getApiRoot } from '../../config.js'; import { ConfigContext, StateContext, STATE_KEY } from '../../state.js'; +import { getTheme } from '../../utils.js'; import { NumericField } from '../input/NumericField.js'; function removeBlobs(key: string, value: unknown): unknown { @@ -28,8 +29,10 @@ function removeBlobs(key: string, value: unknown): unknown { } export function Settings() { + const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); const config = mustExist(useContext(ConfigContext)); const state = useStore(mustExist(useContext(StateContext))); + const theme = getTheme(state.theme, prefersDarkMode); const [json, setJson] = useState(JSON.stringify(state, removeBlobs)); const [root, setRoot] = useState(getApiRoot(config)); @@ -80,13 +83,17 @@ export function Settings() { {t('setting.loadState')} - { - if (state.theme === 'light') { - state.setTheme('dark'); - } else { - state.setTheme('light'); - } - }} /> + { + if (theme === 'light') { + state.setTheme('dark'); + } else { + state.setTheme('light'); + } + }} + /> + } label={t('setting.darkMode')} /> diff --git a/gui/src/components/utils.ts b/gui/src/components/utils.ts index db59ffbd..9a7731e7 100644 --- a/gui/src/components/utils.ts +++ b/gui/src/components/utils.ts @@ -17,3 +17,13 @@ export function getTab(hash: string): string { return TAB_LABELS[0]; } + +export function getTheme(currentTheme: string, preferDark: boolean): string { + if (currentTheme === '') { + if (preferDark) { + return 'dark'; + } + return 'light'; + } + return currentTheme; +} \ No newline at end of file diff --git a/gui/src/strings/de.ts b/gui/src/strings/de.ts index 0dcd148f..1f9919b4 100644 --- a/gui/src/strings/de.ts +++ b/gui/src/strings/de.ts @@ -151,6 +151,7 @@ export const I18N_STRINGS_DE = { scheduler: 'Standardplaner', server: 'API-Server', state: 'Kundenstatus', + darkMode: 'Dunkelmodus', }, tab: { blend: 'Mischung', diff --git a/gui/src/strings/en.ts b/gui/src/strings/en.ts index f21e9daf..02972dd1 100644 --- a/gui/src/strings/en.ts +++ b/gui/src/strings/en.ts @@ -202,6 +202,7 @@ export const I18N_STRINGS_EN = { scheduler: 'Default Scheduler', server: 'API Server', state: 'Client State', + darkMode: 'Dark Mode', }, scheduler: { 'ddim': 'DDIM', diff --git a/gui/src/strings/es.ts b/gui/src/strings/es.ts index 71ce3921..b79fad19 100644 --- a/gui/src/strings/es.ts +++ b/gui/src/strings/es.ts @@ -151,6 +151,7 @@ export const I18N_STRINGS_ES = { scheduler: 'Programador predeterminado', server: 'Servidor API', state: 'Estado del cliente', + darkMode: 'Modo Oscuro', }, tab: { blend: 'Mezclar', diff --git a/gui/src/strings/fr.ts b/gui/src/strings/fr.ts index 7fbd4e0c..9cf773e7 100644 --- a/gui/src/strings/fr.ts +++ b/gui/src/strings/fr.ts @@ -151,6 +151,7 @@ export const I18N_STRINGS_FR = { scheduler: '', server: '', state: '', + darkMode: 'Mode Sombre', }, tab: { blend: '', diff --git a/gui/src/utils.ts b/gui/src/utils.ts index 6fbdbab9..2aaf6779 100644 --- a/gui/src/utils.ts +++ b/gui/src/utils.ts @@ -25,4 +25,4 @@ export function trimHash(val: string): string { } return val; -} +} \ No newline at end of file From 229caa0c4a90ef5202ae155ff1d74d28f9503aeb Mon Sep 17 00:00:00 2001 From: BZLibby Date: Sun, 16 Apr 2023 12:32:16 -0500 Subject: [PATCH 4/4] fixed tabs and imports --- gui/src/components/OnnxWeb.tsx | 37 +++++++++++++++++++++++------ gui/src/components/tab/Settings.tsx | 2 +- gui/src/components/utils.ts | 2 +- gui/src/utils.ts | 2 +- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/gui/src/components/OnnxWeb.tsx b/gui/src/components/OnnxWeb.tsx index c6df1eee..8fec1da6 100644 --- a/gui/src/components/OnnxWeb.tsx +++ b/gui/src/components/OnnxWeb.tsx @@ -1,16 +1,22 @@ import { mustExist } from '@apextoaster/js-utils'; -import { TabContext, TabList } from '@mui/lab'; +import { TabContext, TabList, TabPanel } from '@mui/lab'; import { Box, Container, Divider, PaletteMode, Tab, useMediaQuery, CssBaseline } from '@mui/material'; import { createTheme, ThemeProvider } from '@mui/material/styles'; import * as React from 'react'; import { useContext, useMemo } from 'react'; import { useHash } from 'react-use/lib/useHash'; - import { useStore } from 'zustand'; + +import { StateContext } from '../state.js'; import { ModelControl } from './control/ModelControl.js'; import { ImageHistory } from './ImageHistory.js'; import { Logo } from './Logo.js'; -import { StateContext } from '../state.js'; +import { Blend } from './tab/Blend.js'; +import { Img2Img } from './tab/Img2Img.js'; +import { Inpaint } from './tab/Inpaint.js'; +import { Settings } from './tab/Settings.js'; +import { Txt2Img } from './tab/Txt2Img.js'; +import { Upscale } from './tab/Upscale.js'; import { getTheme, getTab, TAB_LABELS } from './utils.js'; export function OnnxWeb() { @@ -39,6 +45,7 @@ export function OnnxWeb() { + { @@ -46,11 +53,27 @@ export function OnnxWeb() { }}> {TAB_LABELS.map((name) => )} - - - + + + + + + + + + + + + + + + + + + + @@ -58,4 +81,4 @@ export function OnnxWeb() { ); -} \ No newline at end of file +} diff --git a/gui/src/components/tab/Settings.tsx b/gui/src/components/tab/Settings.tsx index 25677ad2..5f09c1a2 100644 --- a/gui/src/components/tab/Settings.tsx +++ b/gui/src/components/tab/Settings.tsx @@ -8,7 +8,7 @@ import { useStore } from 'zustand'; import { getApiRoot } from '../../config.js'; import { ConfigContext, StateContext, STATE_KEY } from '../../state.js'; -import { getTheme } from '../../utils.js'; +import { getTheme } from '../utils.js'; import { NumericField } from '../input/NumericField.js'; function removeBlobs(key: string, value: unknown): unknown { diff --git a/gui/src/components/utils.ts b/gui/src/components/utils.ts index 9a7731e7..2dc64cd1 100644 --- a/gui/src/components/utils.ts +++ b/gui/src/components/utils.ts @@ -26,4 +26,4 @@ export function getTheme(currentTheme: string, preferDark: boolean): string { return 'light'; } return currentTheme; -} \ No newline at end of file +} diff --git a/gui/src/utils.ts b/gui/src/utils.ts index 2aaf6779..6fbdbab9 100644 --- a/gui/src/utils.ts +++ b/gui/src/utils.ts @@ -25,4 +25,4 @@ export function trimHash(val: string): string { } return val; -} \ No newline at end of file +}