Parcourir la source

refactor: Upgrade to the new UI (#521)

Co-authored-by: MystiPanda <mystipanda@proton.me>
Amnesiash il y a 1 an
Parent
commit
0cda07106b
39 fichiers modifiés avec 437 ajouts et 176 suppressions
  1. 2 0
      src/assets/image/itemicon/connections.svg
  2. 8 0
      src/assets/image/itemicon/logs.svg
  3. 15 0
      src/assets/image/itemicon/profiles.svg
  4. 3 0
      src/assets/image/itemicon/proxies.svg
  5. 15 0
      src/assets/image/itemicon/rules.svg
  6. 3 0
      src/assets/image/itemicon/settings.svg
  7. 3 0
      src/assets/image/itemicon/test.svg
  8. 11 0
      src/assets/image/logo.bak.svg
  9. 0 11
      src/assets/image/logo.svg
  10. 12 0
      src/assets/image/logo_dark.svg
  11. 3 3
      src/assets/styles/index.scss
  12. 40 27
      src/assets/styles/layout.scss
  13. 5 7
      src/assets/styles/page.scss
  14. 6 5
      src/components/base/base-page.tsx
  15. 57 0
      src/components/base/base-switch.tsx
  16. 1 0
      src/components/base/index.ts
  17. 30 10
      src/components/layout/layout-item.tsx
  18. 1 1
      src/components/layout/layout-traffic.tsx
  19. 6 2
      src/components/layout/use-custom-theme.ts
  20. 13 11
      src/components/profile/profile-box.tsx
  21. 9 6
      src/components/profile/profile-item.tsx
  22. 1 2
      src/components/profile/profile-viewer.tsx
  23. 3 4
      src/components/proxy/provider-button.tsx
  24. 28 19
      src/components/proxy/proxy-item-mini.tsx
  25. 25 8
      src/components/proxy/proxy-item.tsx
  26. 40 12
      src/components/proxy/proxy-render.tsx
  27. 3 3
      src/components/rule/provider-button.tsx
  28. 2 2
      src/components/setting/mods/layout-viewer.tsx
  29. 1 2
      src/components/setting/mods/misc-viewer.tsx
  30. 15 3
      src/components/setting/mods/setting-comp.tsx
  31. 1 2
      src/components/setting/mods/sysproxy-viewer.tsx
  32. 1 2
      src/components/setting/mods/tun-viewer.tsx
  33. 1 2
      src/components/setting/setting-clash.tsx
  34. 2 2
      src/components/setting/setting-system.tsx
  35. 4 9
      src/components/test/test-box.tsx
  36. 12 4
      src/pages/_layout.tsx
  37. 7 0
      src/pages/_routers.tsx
  38. 18 12
      src/pages/_theme.tsx
  39. 30 5
      src/pages/settings.tsx

Fichier diff supprimé car celui-ci est trop grand
+ 2 - 0
src/assets/image/itemicon/connections.svg


Fichier diff supprimé car celui-ci est trop grand
+ 8 - 0
src/assets/image/itemicon/logs.svg


+ 15 - 0
src/assets/image/itemicon/profiles.svg

@@ -0,0 +1,15 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="url(#paint0_linear_293_142)"/>
+<g clip-path="url(#clip0_293_142)">
+<path d="M24.5167 13C24.7587 13.0001 24.9978 13.0529 25.2173 13.1547C25.4369 13.2566 25.6316 13.405 25.788 13.5897C25.9444 13.7744 26.0587 13.9909 26.1229 14.2243C26.1872 14.4576 26.1998 14.7021 26.16 14.9408L24.7717 23.2742C24.7068 23.6633 24.5059 24.0168 24.2049 24.2718C23.9038 24.5268 23.5221 24.6667 23.1275 24.6667H12.8725C12.478 24.6667 12.0962 24.5268 11.7952 24.2718C11.4941 24.0168 11.2933 23.6633 11.2284 23.2742L9.84003 14.9408C9.80022 14.7021 9.81287 14.4576 9.87711 14.2243C9.94135 13.9909 10.0556 13.7744 10.212 13.5897C10.3684 13.405 10.5632 13.2566 10.7827 13.1547C11.0023 13.0529 11.2413 13.0001 11.4834 13H24.5167ZM23 10.5C23.221 10.5 23.433 10.5878 23.5893 10.7441C23.7456 10.9004 23.8334 11.1123 23.8334 11.3333C23.8334 11.5543 23.7456 11.7663 23.5893 11.9226C23.433 12.0789 23.221 12.1667 23 12.1667H13C12.779 12.1667 12.5671 12.0789 12.4108 11.9226C12.2545 11.7663 12.1667 11.5543 12.1667 11.3333C12.1667 11.1123 12.2545 10.9004 12.4108 10.7441C12.5671 10.5878 12.779 10.5 13 10.5H23Z" fill="white"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_293_142" x1="31" y1="27.5" x2="6.5" y2="7" gradientUnits="userSpaceOnUse">
+<stop stop-color="#6038CB"/>
+<stop offset="1" stop-color="#704ADC"/>
+</linearGradient>
+<clipPath id="clip0_293_142">
+<rect width="20" height="20" fill="white" transform="translate(8 8)"/>
+</clipPath>
+</defs>
+</svg>

Fichier diff supprimé car celui-ci est trop grand
+ 3 - 0
src/assets/image/itemicon/proxies.svg


+ 15 - 0
src/assets/image/itemicon/rules.svg

@@ -0,0 +1,15 @@
+<svg width="36" height="36" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
+<rect width="36" height="36" rx="18" fill="url(#paint0_linear_294_182)"/>
+<g clip-path="url(#clip0_294_182)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M24.7759 10.6333C24.307 10.1647 23.6713 9.90137 23.0084 9.90137C22.3454 9.90137 21.7097 10.1647 21.2409 10.6333L20.6517 11.2233L24.7767 15.3483L25.365 14.7592C25.5972 14.527 25.7814 14.2514 25.9071 13.9481C26.0327 13.6447 26.0974 13.3196 26.0974 12.9913C26.0974 12.6629 26.0327 12.3378 25.9071 12.0344C25.7814 11.7311 25.5972 11.4555 25.365 11.2233L24.7759 10.6333ZM23.5975 16.5267L19.4725 12.4017L11.8975 19.9775C11.7318 20.1433 11.616 20.3524 11.5634 20.5808L10.7059 24.2933C10.6739 24.4312 10.6776 24.5748 10.7165 24.7109C10.7554 24.8469 10.8284 24.9707 10.9284 25.0708C11.0284 25.1708 11.1523 25.2437 11.2883 25.2827C11.4243 25.3216 11.568 25.3253 11.7059 25.2933L15.4192 24.4367C15.6474 24.3839 15.8561 24.2681 16.0217 24.1025L23.5975 16.5267Z" fill="white"/>
+</g>
+<defs>
+<linearGradient id="paint0_linear_294_182" x1="31" y1="27.5" x2="6.5" y2="7" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FB4293"/>
+<stop offset="1" stop-color="#F957A1"/>
+</linearGradient>
+<clipPath id="clip0_294_182">
+<rect width="20" height="20" fill="white" transform="translate(8 8)"/>
+</clipPath>
+</defs>
+</svg>

Fichier diff supprimé car celui-ci est trop grand
+ 3 - 0
src/assets/image/itemicon/settings.svg


Fichier diff supprimé car celui-ci est trop grand
+ 3 - 0
src/assets/image/itemicon/test.svg


Fichier diff supprimé car celui-ci est trop grand
+ 11 - 0
src/assets/image/logo.bak.svg


Fichier diff supprimé car celui-ci est trop grand
+ 0 - 11
src/assets/image/logo.svg


Fichier diff supprimé car celui-ci est trop grand
+ 12 - 0
src/assets/image/logo_dark.svg


+ 3 - 3
src/assets/styles/index.scss

@@ -13,10 +13,10 @@ body {
 
 :root {
   --primary-main: #5b5c9d;
-  --text-primary: #637381;
+  --text-primary: #1f1f1f;
   --selection-color: #f5f5f5;
-  --scroller-color: #90939980;
-  --background-color: #ffffff;
+  --scroller-color: #8c8c8c;
+  --background-color: #f5f5f5;
   --background-color-alpha: rgba(24, 103, 192, 0.1);
   --border-radius: 8px;
 }

+ 40 - 27
src/assets/styles/layout.scss

@@ -5,33 +5,44 @@
   overflow: hidden;
 
   &__left {
-    flex: 1 0 15%;
+    flex: 1 0 228px;
     display: flex;
     height: 100%;
-    max-width: 225px;
-    min-width: 125px;
+    width: 100%;
+    // max-width: 225px;
+    // min-width: 225px;
     padding: 16px 0 8px;
-    position: relative;
+    // position: relative;
     flex-direction: column;
+    align-self: stretch;
     box-sizing: border-box;
     user-select: none;
     -webkit-user-select: none;
     -moz-user-select: none;
     -ms-user-select: none;
     overflow: hidden;
-    background-color: var(--background-color-alpha);
+    border-right: 1px solid var(--divider-color);
+    // background-color: var(--background-color-alpha);
 
-    $maxLogo: 100px;
+    // $maxLogo: 100px;
 
     .the-logo {
-      position: relative;
-      flex: 0 1 $maxLogo;
-      width: 100%;
-      max-width: $maxLogo + 32px;
-      max-height: $maxLogo;
-      margin: 0 auto;
-      padding: 0 16px;
-      text-align: center;
+      // position: relative;
+      flex: 1 0 58px;
+      // width: 100%;
+      display: flex;
+      height: 100%;
+      padding: 0px 20px;
+      flex-direction: column;
+      justify-content: center;
+      align-items: flex-start;
+      align-self: stretch;
+      border-bottom: 1px solid var(--divider-color);
+      // max-width: $maxLogo + 32px;
+      // max-height: $maxLogo;
+      // margin: 0 auto;
+      // padding: 0 auto;
+      // text-align: center;
       box-sizing: border-box;
 
       img,
@@ -39,11 +50,11 @@
         width: 100%;
         height: 100%;
         pointer-events: none;
-        fill: var(--primary-main);
+        // fill: var(--primary-main);
 
-        #bg {
-          fill: var(--background-color);
-        }
+        // #bg {
+        //   fill: var(--background-color);
+        // }
       }
 
       .the-newbtn {
@@ -65,21 +76,22 @@
 
       > div {
         margin: 0 auto;
+        // padding: 0 20px;
       }
     }
   }
 
   &__right {
     position: relative;
-    flex: 1 1 75%;
+    flex: 1 1 100%;
     height: 100%;
-    background-color: var(--background-color-alpha);
+    // background-color: var(--background-color-alpha);
 
     .the-bar {
       position: absolute;
       top: 0px;
       right: 0px;
-      height: 36px;
+      height: 24px;
       display: flex;
       align-items: center;
       box-sizing: border-box;
@@ -100,15 +112,16 @@
 .windows,
 .unknown {
   &.layout {
-    $maxLogo: 115px;
+    .layout__left {
+      padding-top: 24px;
+    }
+
     .layout__left .the-logo {
-      flex: 0 1 $maxLogo;
-      max-width: $maxLogo + 32px;
-      max-height: $maxLogo;
+      flex: 1 0 58px;
     }
 
     .layout__right .the-content {
-      top: 30px;
+      top: 24px;
     }
   }
 }
@@ -119,7 +132,7 @@
       padding-top: 24px;
     }
     .layout__right .the-content {
-      top: 20px;
+      top: 24px;
     }
   }
 }

+ 5 - 7
src/assets/styles/page.scss

@@ -3,23 +3,23 @@
   height: 100%;
   display: flex;
   flex-direction: column;
-
   > header {
     flex: 0 0 58px;
     width: 100%;
     // max-width: 850px;
     margin: 0 auto;
-    padding-right: 8px;
+    padding: 0 20px;
     box-sizing: border-box;
     display: flex;
     align-items: center;
     justify-content: space-between;
+    border-bottom: 1px solid var(--divider-color);
   }
 
   .base-container {
     height: 100%;
     overflow: hidden;
-    border-top-left-radius: var(--border-radius);
+    // border-top-left-radius: var(--border-radius);
 
     > section {
       position: relative;
@@ -27,12 +27,11 @@
       width: 100%;
       height: 100%;
       overflow: auto;
-      padding: 10px 0;
+      padding: 16px 0;
       box-sizing: border-box;
       scrollbar-gutter: stable;
-
       .base-content {
-        width: calc(100% - 10px * 2);
+        width: calc(100% - 16px * 2);
         margin: 0 auto;
       }
     }
@@ -41,7 +40,6 @@
       > section {
         padding: 0;
         overflow: visible;
-
         .base-content {
           width: 100%;
         }

+ 6 - 5
src/components/base/base-page.tsx

@@ -21,7 +21,10 @@ export const BasePage: React.FC<Props> = (props) => {
     <BaseErrorBoundary>
       <div className="base-page">
         <header data-windrag style={{ userSelect: "none" }}>
-          <Typography variant="h4" component="h1" data-windrag>
+          <Typography
+            sx={{ fontSize: "20px", fontWeight: "700 " }}
+            data-windrag
+          >
             {title}
           </Typography>
 
@@ -30,13 +33,11 @@ export const BasePage: React.FC<Props> = (props) => {
 
         <div
           className={full ? "base-container no-padding" : "base-container"}
-          style={{ backgroundColor: isDark ? "#090909" : "#ffffff" }}
+          style={{ backgroundColor: isDark ? "#1e1f27" : "#ffffff" }}
         >
           <section
             style={{
-              backgroundColor: isDark
-                ? alpha(theme.palette.primary.main, 0.1)
-                : "",
+              backgroundColor: isDark ? "#1e1f27" : "var(--background-color)",
             }}
           >
             <div className="base-content" style={contentStyle}>

+ 57 - 0
src/components/base/base-switch.tsx

@@ -0,0 +1,57 @@
+import { styled } from "@mui/material/styles";
+import { default as MuiSwitch, SwitchProps } from "@mui/material/Switch";
+
+export const Switch = styled((props: SwitchProps) => (
+  <MuiSwitch
+    focusVisibleClassName=".Mui-focusVisible"
+    disableRipple
+    {...props}
+  />
+))(({ theme }) => ({
+  width: 42,
+  height: 26,
+  padding: 0,
+  "& .MuiSwitch-switchBase": {
+    padding: 0,
+    margin: 2,
+    transitionDuration: "300ms",
+    "&.Mui-checked": {
+      transform: "translateX(16px)",
+      color: "#fff",
+      "& + .MuiSwitch-track": {
+        backgroundColor: theme.palette.primary.main,
+        opacity: 1,
+        border: 0,
+      },
+      "&.Mui-disabled + .MuiSwitch-track": {
+        opacity: 0.5,
+      },
+    },
+    "&.Mui-focusVisible .MuiSwitch-thumb": {
+      color: "#33cf4d",
+      border: "6px solid #fff",
+    },
+    "&.Mui-disabled .MuiSwitch-thumb": {
+      color:
+        theme.palette.mode === "light"
+          ? theme.palette.grey[100]
+          : theme.palette.grey[600],
+    },
+    "&.Mui-disabled + .MuiSwitch-track": {
+      opacity: theme.palette.mode === "light" ? 0.7 : 0.3,
+    },
+  },
+  "& .MuiSwitch-thumb": {
+    boxSizing: "border-box",
+    width: 22,
+    height: 22,
+  },
+  "& .MuiSwitch-track": {
+    borderRadius: 26 / 2,
+    backgroundColor: theme.palette.mode === "light" ? "#E9E9EA" : "#39393D",
+    opacity: 1,
+    transition: theme.transitions.create(["background-color"], {
+      duration: 500,
+    }),
+  },
+}));

+ 1 - 0
src/components/base/index.ts

@@ -4,3 +4,4 @@ export { BaseEmpty } from "./base-empty";
 export { BaseLoading } from "./base-loading";
 export { BaseErrorBoundary } from "./base-error-boundary";
 export { Notice } from "./base-notice";
+export { Switch } from "./base-switch";

+ 30 - 10
src/components/layout/layout-item.tsx

@@ -1,32 +1,49 @@
-import { alpha, ListItem, ListItemButton, ListItemText } from "@mui/material";
+import {
+  alpha,
+  ListItem,
+  ListItemButton,
+  ListItemText,
+  ListItemAvatar,
+  Avatar,
+} from "@mui/material";
 import { useMatch, useResolvedPath, useNavigate } from "react-router-dom";
 import type { LinkProps } from "react-router-dom";
 
-export const LayoutItem = (props: LinkProps) => {
-  const { to, children } = props;
+interface Props {
+  to: string;
+  children: string;
+  img: string;
+}
+export const LayoutItem = (props: Props) => {
+  const { to, children, img } = props;
 
   const resolved = useResolvedPath(to);
   const match = useMatch({ path: resolved.pathname, end: true });
   const navigate = useNavigate();
 
   return (
-    <ListItem sx={{ py: 0.5, maxWidth: 250, mx: "auto", padding: "1px 0px" }}>
+    <ListItem sx={{ py: 0.5, maxWidth: 250, mx: "auto", padding: "4px 0px" }}>
       <ListItemButton
         selected={!!match}
         sx={[
           {
-            borderRadius: 3,
-            marginLeft: 1,
-            marginRight: 1,
-            textAlign: "center",
-            "& .MuiListItemText-primary": { color: "text.secondary" },
+            borderRadius: 2,
+            marginLeft: 1.5,
+            paddingLeft: 1,
+            paddingRight: 1,
+            marginRight: 1.5,
+            textAlign: "left",
+            "& .MuiListItemText-primary": {
+              color: "text.primary",
+              fontWeight: "700",
+            },
           },
           ({ palette: { mode, primary } }) => {
             const bgcolor =
               mode === "light"
                 ? alpha(primary.main, 0.15)
                 : alpha(primary.main, 0.35);
-            const color = mode === "light" ? primary.main : primary.light;
+            const color = mode === "light" ? "#1f1f1f" : "#ffffff";
 
             return {
               "&.Mui-selected": { bgcolor },
@@ -37,6 +54,9 @@ export const LayoutItem = (props: LinkProps) => {
         ]}
         onClick={() => navigate(to)}
       >
+        <ListItemAvatar sx={{ marginRight: -0.5 }}>
+          <Avatar src={img}></Avatar>
+        </ListItemAvatar>
         <ListItemText primary={children} />
       </ListItemButton>
     </ListItem>

+ 1 - 1
src/components/layout/layout-traffic.tsx

@@ -89,7 +89,7 @@ export const LayoutTraffic = () => {
 
   return (
     <Box
-      width="110px"
+      width="188px"
       position="relative"
       onClick={trafficRef.current?.toggleStyle}
     >

+ 6 - 2
src/components/layout/use-custom-theme.ts

@@ -1,6 +1,6 @@
 import { useEffect, useMemo } from "react";
 import { useRecoilState } from "recoil";
-import { alpha, createTheme, Theme } from "@mui/material";
+import { alpha, createTheme, Shadows, Theme } from "@mui/material";
 import { appWindow } from "@tauri-apps/api/window";
 import { atomThemeMode } from "@/services/states";
 import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
@@ -59,6 +59,7 @@ export const useCustomTheme = () => {
             paper: dt.background_color,
           },
         },
+        shadows: Array(25).fill("none") as Shadows,
         typography: {
           // todo
           fontFamily: setting.font_family
@@ -87,11 +88,14 @@ export const useCustomTheme = () => {
     }
 
     // css
-    const backgroundColor = mode === "light" ? "#ffffff" : "#0B121C";
+    const backgroundColor = mode === "light" ? "#f0f0f0" : "#2e303d";
     const selectColor = mode === "light" ? "#f5f5f5" : "#d5d5d5";
     const scrollColor = mode === "light" ? "#90939980" : "#54545480";
+    const dividerColor =
+      mode === "light" ? "rgba(0, 0, 0, 0.06)" : "rgba(255, 255, 255, 0.06)";
 
     const rootEle = document.documentElement;
+    rootEle.style.setProperty("--divider-color", dividerColor);
     rootEle.style.setProperty("--background-color", backgroundColor);
     rootEle.style.setProperty("--selection-color", selectColor);
     rootEle.style.setProperty("--scroller-color", scrollColor);

+ 13 - 11
src/components/profile/profile-box.tsx

@@ -2,41 +2,43 @@ import { alpha, Box, styled } from "@mui/material";
 
 export const ProfileBox = styled(Box)(
   ({ theme, "aria-selected": selected }) => {
-    const { mode, primary, text, grey, background } = theme.palette;
+    const { mode, primary, text } = theme.palette;
     const key = `${mode}-${!!selected}`;
 
-    const backgroundColor = {
-      "light-true": alpha(primary.main, 0.2),
-      "light-false": alpha(background.paper, 0.75),
-      "dark-true": alpha(primary.main, 0.45),
-      "dark-false": alpha(grey[700], 0.45),
-    }[key]!;
+    const backgroundColor = mode === "light" ? "#ffffff" : "#282A36";
 
     const color = {
       "light-true": text.secondary,
       "light-false": text.secondary,
-      "dark-true": alpha(text.secondary, 0.85),
+      "dark-true": alpha(text.secondary, 0.65),
       "dark-false": alpha(text.secondary, 0.65),
     }[key]!;
 
     const h2color = {
       "light-true": primary.main,
       "light-false": text.primary,
-      "dark-true": primary.light,
+      "dark-true": primary.main,
       "dark-false": text.primary,
     }[key]!;
 
+    const borderLeft = {
+      "light-true": `3px solid ${primary.main}`,
+      "light-false": "none",
+      "dark-true": `3px solid ${primary.main}`,
+      "dark-false": "none",
+    }[key];
+
     return {
       position: "relative",
       width: "100%",
       display: "block",
       cursor: "pointer",
       textAlign: "left",
-      borderRadius: theme.shape.borderRadius,
-      boxShadow: theme.shadows[2],
       padding: "8px 16px",
       boxSizing: "border-box",
       backgroundColor,
+      borderLeft,
+      borderRadius: "8px",
       color,
       "& h2": { color: h2color },
     };

+ 9 - 6
src/components/profile/profile-item.tsx

@@ -230,7 +230,14 @@ export const ProfileItem = (props: Props) => {
               {...attributes}
               {...listeners}
             >
-              <DragIndicator sx={{ cursor: "move", marginLeft: "-6px" }} />
+              <DragIndicator
+                sx={[
+                  { cursor: "move", marginLeft: "-6px" },
+                  ({ palette: { text } }) => {
+                    return { color: text.primary };
+                  },
+                ]}
+              />
             </Box>
 
             <Typography
@@ -303,11 +310,7 @@ export const ProfileItem = (props: Props) => {
             <span title="Updated Time">{parseExpire(updated)}</span>
           </Box>
         )}
-        <LinearProgress
-          variant="determinate"
-          value={progress}
-          color="inherit"
-        />
+        <LinearProgress variant="determinate" value={progress} />
       </ProfileBox>
 
       <Menu

+ 1 - 2
src/components/profile/profile-viewer.tsx

@@ -15,12 +15,11 @@ import {
   InputLabel,
   MenuItem,
   Select,
-  Switch,
   styled,
   TextField,
 } from "@mui/material";
 import { createProfile, patchProfile } from "@/services/cmds";
-import { BaseDialog, Notice } from "@/components/base";
+import { BaseDialog, Notice, Switch } from "@/components/base";
 import { version } from "@root/package.json";
 import { FileInput } from "./file-input";
 

+ 3 - 4
src/components/proxy/provider-button.tsx

@@ -113,12 +113,12 @@ export const ProviderButton = () => {
             return (
               <>
                 <ListItem
-                  sx={(theme) => ({
+                  sx={{
                     p: 0,
                     borderRadius: "10px",
-                    boxShadow: theme.shadows[2],
+                    border: "solid 2px var(--divider-color)",
                     mb: 1,
-                  })}
+                  }}
                   key={key}
                 >
                   <ListItemText
@@ -161,7 +161,6 @@ export const ProviderButton = () => {
                             <LinearProgress
                               variant="determinate"
                               value={progress}
-                              color="inherit"
                             />
                           </>
                         )}

+ 28 - 19
src/components/proxy/proxy-item-mini.tsx

@@ -50,30 +50,36 @@ export const ProxyItemMini = (props: Props) => {
       sx={[
         {
           height: 56,
-          borderRadius: 1,
+          borderRadius: 1.5,
           pl: 1.5,
           pr: 1,
           justifyContent: "space-between",
           alignItems: "center",
         },
         ({ palette: { mode, primary } }) => {
-          const bgcolor =
-            mode === "light"
-              ? alpha(primary.main, 0.15)
-              : alpha(primary.main, 0.35);
+          const bgcolor = mode === "light" ? "#ffffff" : "#24252f";
           const color = mode === "light" ? primary.main : primary.light;
           const showDelay = delay > 0;
-
-          const shadowColor =
-            mode === "light" ? "rgba(0,0,0,0.04)" : "rgba(255,255,255,0.08)";
+          const selectColor = mode === "light" ? primary.main : primary.light;
 
           return {
             "&:hover .the-check": { display: !showDelay ? "block" : "none" },
             "&:hover .the-delay": { display: showDelay ? "block" : "none" },
             "&:hover .the-icon": { display: "none" },
-            "&.Mui-selected": { bgcolor, boxShadow: `0 0 0 1px ${bgcolor}` },
-            "&.Mui-selected .MuiListItemText-secondary": { color },
-            boxShadow: `0 0 0 1px ${shadowColor}`,
+            "&:hover ": {
+              bgcolor:
+                mode === "light"
+                  ? alpha(primary.main, 0.15)
+                  : alpha(primary.main, 0.35),
+            },
+            "&.Mui-selected": {
+              width: `calc(100% + 3px)`,
+              marginLeft: `-3px`,
+              borderLeft: `3px solid ${selectColor}`,
+              bgcolor,
+            },
+            // "&.Mui-selected .MuiListItemText-secondary": { color },
+            backgroundColor: bgcolor,
           };
         },
       ]}
@@ -82,13 +88,15 @@ export const ProxyItemMini = (props: Props) => {
         <Typography
           variant="body2"
           component="div"
-          color="text.secondary"
+          color="text.primary"
           sx={{
             display: "block",
             textOverflow: "ellipsis",
             wordBreak: "break-all",
             overflow: "hidden",
             whiteSpace: "nowrap",
+            fontSize: "13px",
+            fontWeight: "700",
           }}
         >
           {proxy.name}
@@ -114,7 +122,8 @@ export const ProxyItemMini = (props: Props) => {
                   wordBreak: "break-all",
                   overflow: "hidden",
                   whiteSpace: "nowrap",
-                  fontSize: "0.75rem",
+                  fontSize: "11px",
+                  fontWeight: "700",
                   marginRight: "8px",
                 }}
               >
@@ -191,8 +200,8 @@ export const ProxyItemMini = (props: Props) => {
 };
 
 const Widget = styled(Box)(({ theme: { typography } }) => ({
-  padding: "3px 6px",
-  fontSize: 14,
+  padding: "2px 4px",
+  fontSize: 12,
   fontFamily: typography.fontFamily,
   borderRadius: "4px",
 }));
@@ -200,15 +209,15 @@ const Widget = styled(Box)(({ theme: { typography } }) => ({
 const TypeBox = styled(Box)(({ theme: { palette, typography } }) => ({
   display: "inline-block",
   border: "1px solid #ccc",
-  borderColor: alpha(palette.text.secondary, 0.36),
-  color: alpha(palette.text.secondary, 0.42),
+  borderColor: palette.mode === "light" ? "#d9d9d9" : "#424242",
+  color: palette.mode === "light" ? "#8c8c8c" : "#ffffff",
   borderRadius: 4,
   fontSize: 10,
   fontFamily: typography.fontFamily,
   marginRight: "4px",
   marginTop: "auto",
-  padding: "0 2px",
-  lineHeight: 1.25,
+  padding: "0 4px",
+  lineHeight: 1.5,
 }));
 
 const TypeTypo = styled(Box)(({ theme: { palette, typography } }) => ({

+ 25 - 8
src/components/proxy/proxy-item.tsx

@@ -11,6 +11,7 @@ import {
   styled,
   SxProps,
   Theme,
+  Typography,
 } from "@mui/material";
 import { BaseLoading } from "@/components/base";
 import delayManager from "@/services/delay";
@@ -78,19 +79,28 @@ export const ProxyItem = (props: Props) => {
         sx={[
           { borderRadius: 1 },
           ({ palette: { mode, primary } }) => {
-            const bgcolor =
-              mode === "light"
-                ? alpha(primary.main, 0.15)
-                : alpha(primary.main, 0.35);
-            const color = mode === "light" ? primary.main : primary.light;
+            const bgcolor = mode === "light" ? "#ffffff" : "#24252f";
+            const selectColor = mode === "light" ? primary.main : primary.light;
             const showDelay = delay > 0;
 
             return {
               "&:hover .the-check": { display: !showDelay ? "block" : "none" },
               "&:hover .the-delay": { display: showDelay ? "block" : "none" },
               "&:hover .the-icon": { display: "none" },
-              "&.Mui-selected": { bgcolor },
-              "&.Mui-selected .MuiListItemText-secondary": { color },
+              "&:hover ": {
+                bgcolor:
+                  mode === "light"
+                    ? alpha(primary.main, 0.15)
+                    : alpha(primary.main, 0.35),
+              },
+              "&.Mui-selected": {
+                borderLeft: `3px solid ${selectColor}`,
+                bgcolor,
+              },
+              // "&.Mui-selected .MuiListItemText-secondary": { bgcolor },
+              backgroundColor: bgcolor,
+              marginBottom: "8px",
+              height: "40px",
             };
           },
         ]}
@@ -99,7 +109,14 @@ export const ProxyItem = (props: Props) => {
           title={proxy.name}
           secondary={
             <>
-              <span style={{ marginRight: 4 }}>
+              <span
+                style={{
+                  marginRight: "8px",
+                  fontSize: "13px",
+                  color: "text.primary",
+                  fontWeight: "700",
+                }}
+              >
                 {proxy.name}
                 {showType && proxy.now && ` - ${proxy.now}`}
               </span>

+ 40 - 12
src/components/proxy/proxy-render.tsx

@@ -17,6 +17,8 @@ import { ProxyItem } from "./proxy-item";
 import { ProxyItemMini } from "./proxy-item-mini";
 import type { IRenderItem } from "./use-render-list";
 import { useVerge } from "@/hooks/use-verge";
+import { useRecoilState } from "recoil";
+import { atomThemeMode } from "@/services/states";
 
 interface RenderProps {
   item: IRenderItem;
@@ -33,11 +35,21 @@ export const ProxyRender = (props: RenderProps) => {
   const { type, group, headState, proxy, proxyCol } = item;
   const { verge } = useVerge();
   const enable_group_icon = verge?.enable_group_icon ?? true;
+  const [mode] = useRecoilState(atomThemeMode);
+  console.log(mode);
+  const isDark = mode === "light" ? false : true;
+  const itembackgroundcolor = isDark ? "#282A36" : "#ffffff";
 
   if (type === 0 && !group.hidden) {
     return (
       <ListItemButton
         dense
+        style={{
+          background: itembackgroundcolor,
+          height: "64px",
+          margin: "8px 16px",
+          borderRadius: "8px",
+        }}
         onClick={() => onHeadState(group.name, { open: !headState?.open })}
       >
         {enable_group_icon &&
@@ -45,8 +57,8 @@ export const ProxyRender = (props: RenderProps) => {
           group.icon.trim().startsWith("http") && (
             <img
               src={group.icon}
-              height="40px"
-              style={{ marginRight: "8px" }}
+              height="32px"
+              style={{ marginRight: "12px", borderRadius: "6px" }}
             />
           )}
         {enable_group_icon &&
@@ -54,8 +66,8 @@ export const ProxyRender = (props: RenderProps) => {
           group.icon.trim().startsWith("data") && (
             <img
               src={group.icon}
-              height="40px"
-              style={{ marginRight: "8px" }}
+              height="32px"
+              style={{ marginRight: "12px", borderRadius: "6px" }}
             />
           )}
         {enable_group_icon &&
@@ -63,13 +75,14 @@ export const ProxyRender = (props: RenderProps) => {
           group.icon.trim().startsWith("<svg") && (
             <img
               src={`data:image/svg+xml;base64,${btoa(group.icon)}`}
-              height="40px"
+              height="32px"
             />
           )}
         <ListItemText
-          primary={group.name}
+          primary={<StyledPrimary>{group.name}</StyledPrimary>}
           secondary={
             <ListItemTextChild
+              color="text.secondary"
               sx={{
                 overflow: "hidden",
                 display: "flex",
@@ -78,11 +91,18 @@ export const ProxyRender = (props: RenderProps) => {
               }}
             >
               <StyledTypeBox>{group.type}</StyledTypeBox>
-              <StyledSubtitle>{group.now}</StyledSubtitle>
+              <StyledSubtitle
+                sx={{
+                  color: isDark ? "#ffffff" : "#8c8c8c",
+                  fontWeight: "600",
+                }}
+              >
+                {group.now}
+              </StyledSubtitle>
             </ListItemTextChild>
           }
           secondaryTypographyProps={{
-            sx: { display: "flex", alignItems: "center" },
+            sx: { display: "flex", alignItems: "center", color: "#ccc" },
           }}
         />
         {headState?.open ? <ExpandLessRounded /> : <ExpandMoreRounded />}
@@ -164,8 +184,16 @@ export const ProxyRender = (props: RenderProps) => {
   return null;
 };
 
+const StyledPrimary = styled("span")`
+  font-size: 14px;
+  font-weight: 700;
+  line-height: 1.5;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+`;
 const StyledSubtitle = styled("span")`
-  font-size: 0.8rem;
+  font-size: 12px;
   overflow: hidden;
   text-overflow: ellipsis;
   white-space: nowrap;
@@ -182,7 +210,7 @@ const StyledTypeBox = styled(ListItemTextChild)(({ theme }) => ({
   color: alpha(theme.palette.primary.main, 0.8),
   borderRadius: 4,
   fontSize: 10,
-  padding: "0 2px",
-  lineHeight: 1.25,
-  marginRight: "4px",
+  padding: "0 4px",
+  lineHeight: 1.5,
+  marginRight: "8px",
 }));

+ 3 - 3
src/components/rule/provider-button.tsx

@@ -102,12 +102,12 @@ export const ProviderButton = () => {
             return (
               <>
                 <ListItem
-                  sx={(theme) => ({
+                  sx={{
                     p: 0,
                     borderRadius: "10px",
-                    boxShadow: theme.shadows[2],
+                    border: "solid 2px var(--divider-color)",
                     mb: 1,
-                  })}
+                  }}
                   key={key}
                 >
                   <ListItemText

+ 2 - 2
src/components/setting/mods/layout-viewer.tsx

@@ -1,8 +1,8 @@
 import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
 import { useTranslation } from "react-i18next";
-import { List, Switch, Button } from "@mui/material";
+import { List, Button } from "@mui/material";
 import { useVerge } from "@/hooks/use-verge";
-import { BaseDialog, DialogRef, Notice } from "@/components/base";
+import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
 import { SettingItem } from "./setting-comp";
 import { GuardState } from "./guard-state";
 import { open as openDialog } from "@tauri-apps/api/dialog";

+ 1 - 2
src/components/setting/mods/misc-viewer.tsx

@@ -7,11 +7,10 @@ import {
   ListItemText,
   MenuItem,
   Select,
-  Switch,
   TextField,
 } from "@mui/material";
 import { useVerge } from "@/hooks/use-verge";
-import { BaseDialog, DialogRef, Notice } from "@/components/base";
+import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
 
 export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
   const { t } = useTranslation();

+ 15 - 3
src/components/setting/mods/setting-comp.tsx

@@ -18,9 +18,11 @@ export const SettingItem: React.FC<ItemProps> = (props) => {
   const { label, extra, children, secondary } = props;
 
   const primary = !extra ? (
-    label
+    <Box sx={{ display: "flex", alignItems: "center", fontSize: "14px" }}>
+      <span>{label}</span>
+    </Box>
   ) : (
-    <Box sx={{ display: "flex", alignItems: "center" }}>
+    <Box sx={{ display: "flex", alignItems: "center", fontSize: "14px" }}>
       <span>{label}</span>
       {extra}
     </Box>
@@ -39,7 +41,17 @@ export const SettingList: React.FC<{
   children: ReactNode;
 }> = (props) => (
   <List>
-    <ListSubheader sx={{ background: "transparent" }} disableSticky>
+    <ListSubheader
+      sx={[
+        { background: "transparent", fontSize: "16px", fontWeight: "700" },
+        ({ palette }) => {
+          return {
+            color: palette.text.primary,
+          };
+        },
+      ]}
+      disableSticky
+    >
       {props.title}
     </ListSubheader>
 

+ 1 - 2
src/components/setting/mods/sysproxy-viewer.tsx

@@ -8,13 +8,12 @@ import {
   ListItem,
   ListItemText,
   styled,
-  Switch,
   TextField,
   Typography,
 } from "@mui/material";
 import { useVerge } from "@/hooks/use-verge";
 import { getSystemProxy } from "@/services/cmds";
-import { BaseDialog, DialogRef, Notice } from "@/components/base";
+import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
 
 export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
   const { t } = useTranslation();

+ 1 - 2
src/components/setting/mods/tun-viewer.tsx

@@ -8,11 +8,10 @@ import {
   Box,
   Typography,
   Button,
-  Switch,
   TextField,
 } from "@mui/material";
 import { useClash } from "@/hooks/use-clash";
-import { BaseDialog, DialogRef, Notice } from "@/components/base";
+import { BaseDialog, DialogRef, Notice, Switch } from "@/components/base";
 import { StackModeSwitch } from "./stack-mode-switch";
 
 export const TunViewer = forwardRef<DialogRef>((props, ref) => {

+ 1 - 2
src/components/setting/setting-clash.tsx

@@ -3,7 +3,6 @@ import { useTranslation } from "react-i18next";
 import { useLockFn } from "ahooks";
 import {
   TextField,
-  Switch,
   Select,
   MenuItem,
   Typography,
@@ -11,7 +10,7 @@ import {
   Tooltip,
 } from "@mui/material";
 import { ArrowForward, Settings, Shuffle } from "@mui/icons-material";
-import { DialogRef, Notice } from "@/components/base";
+import { DialogRef, Notice, Switch } from "@/components/base";
 import { useClash } from "@/hooks/use-clash";
 import { GuardState } from "./mods/guard-state";
 import { WebUIViewer } from "./mods/web-ui-viewer";

+ 2 - 2
src/components/setting/setting-system.tsx

@@ -1,11 +1,11 @@
 import useSWR from "swr";
 import { useRef } from "react";
 import { useTranslation } from "react-i18next";
-import { IconButton, Switch, Tooltip } from "@mui/material";
+import { IconButton, Tooltip } from "@mui/material";
 import { PrivacyTipRounded, Settings, InfoRounded } from "@mui/icons-material";
 import { checkService } from "@/services/cmds";
 import { useVerge } from "@/hooks/use-verge";
-import { DialogRef } from "@/components/base";
+import { DialogRef, Switch } from "@/components/base";
 import { SettingList, SettingItem } from "./mods/setting-comp";
 import { GuardState } from "./mods/guard-state";
 import { ServiceViewer } from "./mods/service-viewer";

+ 4 - 9
src/components/test/test-box.tsx

@@ -1,27 +1,22 @@
 import { alpha, Box, styled } from "@mui/material";
 
 export const TestBox = styled(Box)(({ theme, "aria-selected": selected }) => {
-  const { mode, primary, text, grey, background } = theme.palette;
+  const { mode, primary, text } = theme.palette;
   const key = `${mode}-${!!selected}`;
 
-  const backgroundColor = {
-    "light-true": alpha(primary.main, 0.2),
-    "light-false": alpha(background.paper, 0.75),
-    "dark-true": alpha(primary.main, 0.45),
-    "dark-false": alpha(grey[700], 0.45),
-  }[key]!;
+  const backgroundColor = mode === "light" ? "#ffffff" : "#282A36";
 
   const color = {
     "light-true": text.secondary,
     "light-false": text.secondary,
-    "dark-true": alpha(text.secondary, 0.85),
+    "dark-true": alpha(text.secondary, 0.65),
     "dark-false": alpha(text.secondary, 0.65),
   }[key]!;
 
   const h2color = {
     "light-true": primary.main,
     "light-false": text.primary,
-    "dark-true": primary.light,
+    "dark-true": primary.main,
     "dark-false": text.primary,
   }[key]!;
 

+ 12 - 4
src/pages/_layout.tsx

@@ -13,6 +13,9 @@ import { routers } from "./_routers";
 import { getAxios } from "@/services/api";
 import { useVerge } from "@/hooks/use-verge";
 import LogoSvg from "@/assets/image/logo.svg?react";
+import LogoSvg_dark from "@/assets/image/logo_dark.svg?react";
+import { atomThemeMode } from "@/services/states";
+import { useRecoilState } from "recoil";
 import { BaseErrorBoundary, Notice } from "@/components/base";
 import { LayoutItem } from "@/components/layout/layout-item";
 import { LayoutControl } from "@/components/layout/layout-control";
@@ -31,8 +34,10 @@ dayjs.extend(relativeTime);
 const OS = getSystem();
 
 const Layout = () => {
+  const [mode] = useRecoilState(atomThemeMode);
+  console.log(mode);
+  const isDark = mode === "light" ? false : true;
   const { t } = useTranslation();
-
   const { theme } = useCustomTheme();
 
   const { verge } = useVerge();
@@ -125,14 +130,17 @@ const Layout = () => {
         >
           <div className="layout__left" data-windrag>
             <div className="the-logo" data-windrag>
-              <LogoSvg />
-
+              {!isDark ? <LogoSvg /> : <LogoSvg_dark />}
               {!portableFlag && <UpdateButton className="the-newbtn" />}
             </div>
 
             <List className="the-menu">
               {routers.map((router) => (
-                <LayoutItem key={router.label} to={router.link}>
+                <LayoutItem
+                  key={router.label}
+                  to={router.link}
+                  img={router.img}
+                >
                   {t(router.label)}
                 </LayoutItem>
               ))}

+ 7 - 0
src/pages/_routers.tsx

@@ -10,36 +10,43 @@ export const routers = [
   {
     label: "Label-Proxies",
     link: "/",
+    img: "../../assets/image/itemicon/proxies.svg",
     ele: ProxiesPage,
   },
   {
     label: "Label-Profiles",
     link: "/profile",
+    img: "../../assets/image/itemicon/profiles.svg",
     ele: ProfilesPage,
   },
   {
     label: "Label-Connections",
     link: "/connections",
+    img: "../../assets/image/itemicon/connections.svg",
     ele: ConnectionsPage,
   },
   {
     label: "Label-Rules",
     link: "/rules",
+    img: "../../assets/image/itemicon/rules.svg",
     ele: RulesPage,
   },
   {
     label: "Label-Logs",
     link: "/logs",
+    img: "../../assets/image/itemicon/logs.svg",
     ele: LogsPage,
   },
   {
     label: "Label-Test",
     link: "/test",
+    img: "../../assets/image/itemicon/test.svg",
     ele: TestPage,
   },
   {
     label: "Label-Settings",
     link: "/settings",
+    img: "../../assets/image/itemicon/settings.svg",
     ele: SettingsPage,
   },
 ];

+ 18 - 12
src/pages/_theme.tsx

@@ -3,15 +3,15 @@ const OS = getSystem();
 
 // default theme setting
 export const defaultTheme = {
-  primary_color: "#1867c0",
-  secondary_color: "#3a88bb",
-  primary_text: "#1d1d1f",
-  secondary_text: "#424245",
-  info_color: "#0288d1",
-  error_color: "#d32f2f",
-  warning_color: "#ed6c02",
-  success_color: "#2e7d32",
-  background_color: "#ffffff",
+  primary_color: "#007AFF",
+  secondary_color: "#FFCC00",
+  primary_text: "#000000",
+  secondary_text: "rgba(60, 60, 67, 0.60)",
+  info_color: "#007AFF",
+  error_color: "#FF3B30",
+  warning_color: "#FF9500",
+  success_color: "#34C759",
+  background_color: "#f5f5f5",
   font_family: `"Roboto", "Helvetica", "Arial", sans-serif, ${
     OS === "windows" ? "twemoji mozilla" : ""
   }`,
@@ -20,7 +20,13 @@ export const defaultTheme = {
 // dark mode
 export const defaultDarkTheme = {
   ...defaultTheme,
-  primary_text: "#E8E8ED",
-  background_color: "#181818",
-  secondary_text: "#bbbbbb",
+  primary_color: "#0A84FF",
+  secondary_color: "#FF9F0A",
+  primary_text: "#ffffff",
+  background_color: "#2e303d",
+  secondary_text: "rgba(235, 235, 245, 0.60)",
+  info_color: "#0A84FF",
+  error_color: "#FF453A",
+  warning_color: "#FF9F0A",
+  success_color: "#30D158",
 };

+ 30 - 5
src/pages/settings.tsx

@@ -7,6 +7,9 @@ import { openWebUrl } from "@/services/cmds";
 import SettingVerge from "@/components/setting/setting-verge";
 import SettingClash from "@/components/setting/setting-clash";
 import SettingSystem from "@/components/setting/setting-system";
+import { atomThemeMode } from "@/services/states";
+import { useRecoilState } from "recoil";
+import { useCustomTheme } from "@/components/layout/use-custom-theme";
 
 const SettingPage = () => {
   const { t } = useTranslation();
@@ -19,12 +22,17 @@ const SettingPage = () => {
     return openWebUrl("https://github.com/clash-verge-rev/clash-verge-rev");
   });
 
+  const [mode] = useRecoilState(atomThemeMode);
+  console.log(mode);
+  const isDark = mode === "light" ? false : true;
+  const { theme } = useCustomTheme();
+
   return (
     <BasePage
       title={t("Settings")}
       header={
         <IconButton
-          size="small"
+          size="medium"
           color="inherit"
           title="@clash-verge-rev/clash-verge-rev"
           onClick={toGithubRepo}
@@ -33,17 +41,34 @@ const SettingPage = () => {
         </IconButton>
       }
     >
-      <Grid container spacing={{ xs: 1, lg: 1 }}>
+      <Grid container spacing={{ xs: 1.5, lg: 1.5 }}>
         <Grid item xs={12} md={6}>
-          <Box sx={{ borderRadius: 1, boxShadow: 2, marginBottom: 1 }}>
+          <Box
+            sx={{
+              borderRadius: 2,
+              marginBottom: 1.5,
+              backgroundColor: isDark ? "#282a36" : "#ffffff",
+            }}
+          >
             <SettingSystem onError={onError} />
           </Box>
-          <Box sx={{ borderRadius: 1, boxShadow: 2 }}>
+          <Box
+            sx={{
+              borderRadius: 2,
+              backgroundColor: isDark ? "#282a36" : "#ffffff",
+            }}
+          >
             <SettingClash onError={onError} />
           </Box>
         </Grid>
         <Grid item xs={12} md={6}>
-          <Box sx={{ borderRadius: 1, boxShadow: 2 }}>
+          <Box
+            sx={{
+              borderRadius: 2,
+              marginBottom: 1.5,
+              backgroundColor: isDark ? "#282a36" : "#ffffff",
+            }}
+          >
             <SettingVerge onError={onError} />
           </Box>
         </Grid>

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff