From d382997506dda54c3789b5dfb97a0b505ad582f8 Mon Sep 17 00:00:00 2001 From: Minamiyama Date: Sat, 20 Apr 2024 17:56:46 +0800 Subject: [PATCH 1/2] FEAT: theme switch --- xinference/web/ui/src/App.js | 33 +++++++++-------- xinference/web/ui/src/components/MenuSide.js | 4 ++- xinference/web/ui/src/components/Title.js | 7 +--- .../web/ui/src/components/themeButton.js | 21 +++++++++++ .../web/ui/src/components/themeContext.js | 36 +++++++++++++++++++ xinference/web/ui/src/theme.js | 9 +++-- 6 files changed, 83 insertions(+), 27 deletions(-) create mode 100644 xinference/web/ui/src/components/themeButton.js create mode 100644 xinference/web/ui/src/components/themeContext.js diff --git a/xinference/web/ui/src/App.js b/xinference/web/ui/src/App.js index eb587a1c4a..54149fec3c 100644 --- a/xinference/web/ui/src/App.js +++ b/xinference/web/ui/src/App.js @@ -1,4 +1,4 @@ -import { CssBaseline, ThemeProvider } from '@mui/material' +import { CssBaseline } from '@mui/material' import Snackbar from '@mui/material/Snackbar' import React, { useEffect, useState } from 'react' import { useCookies } from 'react-cookie' @@ -7,12 +7,11 @@ import { HashRouter } from 'react-router-dom' import { Alert } from './components/alertComponent' import { ApiContextProvider } from './components/apiContext' import AuthAlertDialog from './components/authAlertDialog' +import { ThemeProvider } from './components/themeContext' import { getEndpoint } from './components/utils' import WraperRoutes from './router/index' -import { useMode } from './theme' function App() { - const [theme] = useMode() const [cookie, setCookie, removeCookie] = useCookies(['token']) const [msg, setMsg] = useState('') @@ -55,25 +54,25 @@ function App() { return (
- - - {msg} - - - - + + + + {msg} + + + - - + +
) } diff --git a/xinference/web/ui/src/components/MenuSide.js b/xinference/web/ui/src/components/MenuSide.js index 429f454032..a0cd66517f 100644 --- a/xinference/web/ui/src/components/MenuSide.js +++ b/xinference/web/ui/src/components/MenuSide.js @@ -21,6 +21,7 @@ import { useEffect, useState } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import icon from '../media/icon.webp' +import ThemeButton from './themeButton' const navItems = [ { @@ -124,7 +125,7 @@ const MenuSide = () => { - + @@ -188,6 +189,7 @@ const MenuSide = () => { + ) } diff --git a/xinference/web/ui/src/components/Title.js b/xinference/web/ui/src/components/Title.js index c622c7e46e..3f260c532d 100644 --- a/xinference/web/ui/src/components/Title.js +++ b/xinference/web/ui/src/components/Title.js @@ -19,12 +19,7 @@ const Title = ({ title }) => { return ( - + {title} {isValidBearerToken(cookie.token) && ( diff --git a/xinference/web/ui/src/components/themeButton.js b/xinference/web/ui/src/components/themeButton.js new file mode 100644 index 0000000000..75e2fc3e9d --- /dev/null +++ b/xinference/web/ui/src/components/themeButton.js @@ -0,0 +1,21 @@ +import DarkModeIcon from '@mui/icons-material/DarkMode' +import LightModeIcon from '@mui/icons-material/LightMode' +import { Box, IconButton } from '@mui/material' +import React from 'react' + +import { useThemeContext } from './themeContext' + +const ThemeButton = ({ sx }) => { + const { themeMode, toggleTheme } = useThemeContext() + + console.log('主题:', useThemeContext) + return ( + + + {themeMode === 'light' ? : } + + + ) +} + +export default ThemeButton diff --git a/xinference/web/ui/src/components/themeContext.js b/xinference/web/ui/src/components/themeContext.js new file mode 100644 index 0000000000..ebebf86924 --- /dev/null +++ b/xinference/web/ui/src/components/themeContext.js @@ -0,0 +1,36 @@ +import { ThemeProvider as MuiThemeProvider } from '@mui/material' +import { createContext, useContext, useState } from 'react' + +import { useMode } from '../theme' + +const ThemeContext = createContext() + +export function useThemeContext() { + return useContext(ThemeContext) +} + +export const ThemeProvider = ({ children }) => { + const themeKey = 'theme' + const systemPreference = window.matchMedia('(prefers-color-scheme: dark)') + .matches + ? 'dark' + : 'light' + const initialMode = localStorage.getItem(themeKey) || systemPreference + + const [themeMode, setThemeMode] = useState(initialMode) + const theme = useMode(themeMode)[0] + + const switchTheme = () => { + const nextTheme = themeMode === 'light' ? 'dark' : 'light' + setThemeMode(nextTheme) + localStorage.setItem(themeKey, nextTheme) + } + + return ( + + + {children} + + + ) +} diff --git a/xinference/web/ui/src/theme.js b/xinference/web/ui/src/theme.js index 4f4e175620..0a76e5bfa5 100644 --- a/xinference/web/ui/src/theme.js +++ b/xinference/web/ui/src/theme.js @@ -1,7 +1,7 @@ import { createTheme } from '@mui/material/styles' // mui theme settings -export const themeSettings = () => { +export const themeSettings = (mode) => { return { ERROR_COLOR: '#d8342c', typography: { @@ -32,10 +32,13 @@ export const themeSettings = () => { fontSize: 14, }, }, + palette: { + mode: mode, + }, } } -export const useMode = () => { - const theme = createTheme(themeSettings()) +export const useMode = (mode = 'light') => { + const theme = createTheme(themeSettings(mode)) return [theme] } From fceb9e0b8fcfbf83df0843deac64ec8b962acda0 Mon Sep 17 00:00:00 2001 From: Minamiyama Date: Sat, 20 Apr 2024 19:20:33 +0800 Subject: [PATCH 2/2] remove debug log --- xinference/web/ui/src/components/themeButton.js | 1 - 1 file changed, 1 deletion(-) diff --git a/xinference/web/ui/src/components/themeButton.js b/xinference/web/ui/src/components/themeButton.js index 75e2fc3e9d..f85f648f91 100644 --- a/xinference/web/ui/src/components/themeButton.js +++ b/xinference/web/ui/src/components/themeButton.js @@ -8,7 +8,6 @@ import { useThemeContext } from './themeContext' const ThemeButton = ({ sx }) => { const { themeMode, toggleTheme } = useThemeContext() - console.log('主题:', useThemeContext) return (