Răsfoiți Sursa

refactor: dark mode

kahosan 1 an în urmă
părinte
comite
e9abe5b705
3 a modificat fișierele cu 69 adăugiri și 36 ștergeri
  1. 11 17
      web/src/components/HeaderBar.js
  2. 36 0
      web/src/context/Theme/index.js
  3. 22 19
      web/src/index.js

+ 11 - 17
web/src/components/HeaderBar.js

@@ -1,6 +1,7 @@
 import React, { useContext, useEffect, useState } from 'react';
 import { Link, useNavigate } from 'react-router-dom';
 import { UserContext } from '../context/User';
+import { useSetTheme, useTheme } from '../context/Theme';
 
 import { API, getLogo, getSystemName, showSuccess } from '../helpers';
 import '../index.css';
@@ -34,10 +35,8 @@ const HeaderBar = () => {
   let navigate = useNavigate();
 
   const [showSidebar, setShowSidebar] = useState(false);
-  const [dark, setDark] = useState(false);
   const systemName = getSystemName();
   const logo = getLogo();
-  var themeMode = localStorage.getItem('theme-mode');
   const currentDate = new Date();
   // enable fireworks on new year(1.1 and 2.9-2.24)
   const isNewYear =
@@ -66,26 +65,19 @@ const HeaderBar = () => {
     }, 3000);
   };
 
+  const theme = useTheme();
+  const setTheme = useSetTheme();
+
   useEffect(() => {
-    if (themeMode === 'dark') {
-      switchMode(true);
+    if (theme === 'dark') {
+      document.body.setAttribute('theme-mode', 'dark');
     }
+
     if (isNewYear) {
       console.log('Happy New Year!');
     }
   }, []);
 
-  const switchMode = (model) => {
-    const body = document.body;
-    if (!model) {
-      body.removeAttribute('theme-mode');
-      localStorage.setItem('theme-mode', 'light');
-    } else {
-      body.setAttribute('theme-mode', 'dark');
-      localStorage.setItem('theme-mode', 'dark');
-    }
-    setDark(model);
-  };
   return (
     <>
       <Layout>
@@ -132,9 +124,11 @@ const HeaderBar = () => {
                 <Switch
                   checkedText='🌞'
                   size={'large'}
-                  checked={dark}
+                  checked={theme === 'dark'}
                   uncheckedText='🌙'
-                  onChange={switchMode}
+                  onChange={(checked) => {
+                    setTheme(checked);
+                  }}
                 />
                 {userState.user ? (
                   <>

+ 36 - 0
web/src/context/Theme/index.js

@@ -0,0 +1,36 @@
+import { createContext, useCallback, useContext, useState } from 'react';
+
+const ThemeContext = createContext(null);
+export const useTheme = () => useContext(ThemeContext);
+
+const SetThemeContext = createContext(null);
+export const useSetTheme = () => useContext(SetThemeContext);
+
+export const ThemeProvider = ({ children }) => {
+  const [theme, _setTheme] = useState(() => {
+    try {
+      return localStorage.getItem('theme-mode') || null;
+    } catch {
+      return null;
+    }
+  });
+
+  const setTheme = useCallback((input) => {
+    _setTheme(input ? 'dark' : 'light');
+
+    const body = document.body;
+    if (!input) {
+      body.removeAttribute('theme-mode');
+      localStorage.setItem('theme-mode', 'light');
+    } else {
+      body.setAttribute('theme-mode', 'dark');
+      localStorage.setItem('theme-mode', 'dark');
+    }
+  }, []);
+
+  return (
+    <SetThemeContext.Provider value={setTheme}>
+      <ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
+    </SetThemeContext.Provider>
+  );
+};

+ 22 - 19
web/src/index.js

@@ -12,6 +12,7 @@ import 'react-toastify/dist/ReactToastify.css';
 import { StatusProvider } from './context/Status';
 import { Layout } from '@douyinfe/semi-ui';
 import SiderBar from './components/SiderBar';
+import { ThemeProvider } from './context/Theme';
 
 // initialization
 
@@ -22,27 +23,29 @@ root.render(
     <StatusProvider>
       <UserProvider>
         <BrowserRouter>
-          <Layout>
-            <Sider>
-              <SiderBar />
-            </Sider>
+          <ThemeProvider>
             <Layout>
-              <Header>
-                <HeaderBar />
-              </Header>
-              <Content
-                style={{
-                  padding: '24px',
-                }}
-              >
-                <App />
-              </Content>
-              <Layout.Footer>
-                <Footer></Footer>
-              </Layout.Footer>
+              <Sider>
+                <SiderBar />
+              </Sider>
+              <Layout>
+                <Header>
+                  <HeaderBar />
+                </Header>
+                <Content
+                  style={{
+                    padding: '24px',
+                  }}
+                >
+                  <App />
+                </Content>
+                <Layout.Footer>
+                  <Footer></Footer>
+                </Layout.Footer>
+              </Layout>
+              <ToastContainer />
             </Layout>
-            <ToastContainer />
-          </Layout>
+          </ThemeProvider>
         </BrowserRouter>
       </UserProvider>
     </StatusProvider>