Explorar o código

fix: unified switch style

MystiPanda hai 10 meses
pai
achega
4cd7ccda57

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

@@ -11,6 +11,7 @@ export const Switch = styled((props: SwitchProps) => (
   width: 42,
   width: 42,
   height: 26,
   height: 26,
   padding: 0,
   padding: 0,
+  marginRight: 1,
   "& .MuiSwitch-switchBase": {
   "& .MuiSwitch-switchBase": {
     padding: 0,
     padding: 0,
     margin: 2,
     margin: 2,

+ 97 - 0
src/components/setting/mods/service-switcher.tsx

@@ -0,0 +1,97 @@
+import { KeyedMutator } from "swr";
+import { useState } from "react";
+import { useLockFn } from "ahooks";
+import { useTranslation } from "react-i18next";
+import { installService, uninstallService } from "@/services/cmds";
+import { Notice } from "@/components/base";
+import { LoadingButton } from "@mui/lab";
+
+interface Props {
+  status: "active" | "installed" | "unknown" | "uninstall";
+  mutate: KeyedMutator<"active" | "installed" | "unknown" | "uninstall">;
+  patchVerge: (value: Partial<IVergeConfig>) => Promise<void>;
+  onChangeData: (patch: Partial<IVergeConfig>) => void;
+}
+
+export const ServiceSwitcher = (props: Props) => {
+  const { status, mutate, patchVerge, onChangeData } = props;
+
+  const isActive = status === "active";
+  const isInstalled = status === "installed";
+  const isUninstall = status === "uninstall" || status === "unknown";
+
+  const { t } = useTranslation();
+  const [serviceLoading, setServiceLoading] = useState(false);
+  const [uninstallServiceLoaing, setUninstallServiceLoading] = useState(false);
+
+  const onInstallOrEnableService = useLockFn(async () => {
+    setServiceLoading(true);
+    try {
+      if (isUninstall) {
+        // install service
+        await installService();
+        await mutate();
+        setTimeout(() => {
+          mutate();
+        }, 2000);
+        Notice.success(t("Service Installed Successfully"));
+        setServiceLoading(false);
+      } else {
+        // enable or disable service
+        await patchVerge({ enable_service_mode: !isActive });
+        onChangeData({ enable_service_mode: !isActive });
+        await mutate();
+        setTimeout(() => {
+          mutate();
+        }, 2000);
+        setServiceLoading(false);
+      }
+    } catch (err: any) {
+      await mutate();
+      Notice.error(err.message || err.toString());
+      setServiceLoading(false);
+    }
+  });
+
+  const onUninstallService = useLockFn(async () => {
+    setUninstallServiceLoading(true);
+    try {
+      await uninstallService();
+      await mutate();
+      setTimeout(() => {
+        mutate();
+      }, 2000);
+      Notice.success(t("Service Uninstalled Successfully"));
+      setUninstallServiceLoading(false);
+    } catch (err: any) {
+      await mutate();
+      Notice.error(err.message || err.toString());
+      setUninstallServiceLoading(false);
+    }
+  });
+
+  return (
+    <>
+      <LoadingButton
+        size="small"
+        variant={isUninstall ? "outlined" : "contained"}
+        onClick={onInstallOrEnableService}
+        loading={serviceLoading}
+      >
+        {isActive ? t("Disable") : isInstalled ? t("Enable") : t("Install")}
+      </LoadingButton>
+      {isInstalled && (
+        <LoadingButton
+          size="small"
+          variant="outlined"
+          color="error"
+          sx={{ ml: 1 }}
+          onClick={onUninstallService}
+          loading={uninstallServiceLoaing}
+        >
+          {t("Uninstall")}
+        </LoadingButton>
+      )}
+    </>
+  );
+};

+ 0 - 129
src/components/setting/mods/service-viewer.tsx

@@ -1,129 +0,0 @@
-import useSWR from "swr";
-import { forwardRef, useImperativeHandle, useState } from "react";
-import { useLockFn } from "ahooks";
-import { useTranslation } from "react-i18next";
-import { Button, Stack, Typography } from "@mui/material";
-import {
-  checkService,
-  installService,
-  uninstallService,
-  patchVergeConfig,
-} from "@/services/cmds";
-import { BaseDialog, DialogRef, Notice } from "@/components/base";
-
-interface Props {
-  enable: boolean;
-}
-
-export const ServiceViewer = forwardRef<DialogRef, Props>((props, ref) => {
-  const { enable } = props;
-
-  const { t } = useTranslation();
-  const [open, setOpen] = useState(false);
-
-  const { data: status, mutate: mutateCheck } = useSWR(
-    "checkService",
-    checkService,
-    {
-      revalidateIfStale: false,
-      shouldRetryOnError: false,
-      focusThrottleInterval: 36e5, // 1 hour
-    }
-  );
-
-  useImperativeHandle(ref, () => ({
-    open: () => setOpen(true),
-    close: () => setOpen(false),
-  }));
-
-  const state = status != null ? status : "pending";
-
-  const onInstall = useLockFn(async () => {
-    try {
-      await installService();
-      await mutateCheck();
-      setOpen(false);
-      setTimeout(() => {
-        mutateCheck();
-      }, 2000);
-      Notice.success(t("Service Installed Successfully"));
-    } catch (err: any) {
-      mutateCheck();
-      Notice.error(err.message || err.toString());
-    }
-  });
-
-  const onUninstall = useLockFn(async () => {
-    try {
-      if (enable) {
-        await patchVergeConfig({ enable_service_mode: false });
-      }
-
-      await uninstallService();
-      mutateCheck();
-      setOpen(false);
-      Notice.success(t("Service Uninstalled Successfully"));
-    } catch (err: any) {
-      mutateCheck();
-      Notice.error(err.message || err.toString());
-    }
-  });
-
-  // fix unhandled error of the service mode
-  const onDisable = useLockFn(async () => {
-    try {
-      await patchVergeConfig({ enable_service_mode: false });
-      mutateCheck();
-      setOpen(false);
-    } catch (err: any) {
-      mutateCheck();
-      Notice.error(err.message || err.toString());
-    }
-  });
-
-  return (
-    <BaseDialog
-      open={open}
-      title={t("Service Mode")}
-      contentSx={{ width: 360, userSelect: "text" }}
-      disableFooter
-      onClose={() => setOpen(false)}
-    >
-      <Typography>
-        {t("Current State")}: {t(state)}
-      </Typography>
-
-      {(state === "unknown" || state === "uninstall") && (
-        <Typography>
-          {t(
-            "Information: Please make sure that the Clash Verge Service is installed and enabled"
-          )}
-        </Typography>
-      )}
-
-      <Stack
-        direction="row"
-        spacing={1}
-        sx={{ mt: 4, justifyContent: "flex-end" }}
-      >
-        {state === "uninstall" && enable && (
-          <Button variant="contained" onClick={onDisable}>
-            {t("Disable Service Mode")}
-          </Button>
-        )}
-
-        {state === "uninstall" && (
-          <Button variant="contained" onClick={onInstall}>
-            {t("Install")}
-          </Button>
-        )}
-
-        {(state === "active" || state === "installed") && (
-          <Button variant="outlined" onClick={onUninstall}>
-            {t("Uninstall")}
-          </Button>
-        )}
-      </Stack>
-    </BaseDialog>
-  );
-});

+ 10 - 87
src/components/setting/setting-system.tsx

@@ -1,22 +1,16 @@
 import useSWR from "swr";
 import useSWR from "swr";
-import { useRef, useState } from "react";
+import { useRef } from "react";
 import { useTranslation } from "react-i18next";
 import { useTranslation } from "react-i18next";
 import { SettingsRounded } from "@mui/icons-material";
 import { SettingsRounded } from "@mui/icons-material";
-import {
-  checkService,
-  installService,
-  uninstallService,
-} from "@/services/cmds";
+import { checkService } from "@/services/cmds";
 import { useVerge } from "@/hooks/use-verge";
 import { useVerge } from "@/hooks/use-verge";
 import { DialogRef, Notice, Switch } from "@/components/base";
 import { DialogRef, Notice, Switch } from "@/components/base";
 import { SettingList, SettingItem } from "./mods/setting-comp";
 import { SettingList, SettingItem } from "./mods/setting-comp";
 import { GuardState } from "./mods/guard-state";
 import { GuardState } from "./mods/guard-state";
-import { ServiceViewer } from "./mods/service-viewer";
+import { ServiceSwitcher } from "./mods/service-switcher";
 import { SysproxyViewer } from "./mods/sysproxy-viewer";
 import { SysproxyViewer } from "./mods/sysproxy-viewer";
 import { TunViewer } from "./mods/tun-viewer";
 import { TunViewer } from "./mods/tun-viewer";
 import { TooltipIcon } from "@/components/base/base-tooltip-icon";
 import { TooltipIcon } from "@/components/base/base-tooltip-icon";
-import { LoadingButton } from "@mui/lab";
-import { useLockFn } from "ahooks";
 
 
 interface Props {
 interface Props {
   onError?: (err: Error) => void;
   onError?: (err: Error) => void;
@@ -26,8 +20,6 @@ const SettingSystem = ({ onError }: Props) => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
   const { verge, mutateVerge, patchVerge } = useVerge();
   const { verge, mutateVerge, patchVerge } = useVerge();
-  const [serviceLoading, setServiceLoading] = useState(false);
-  const [uninstallServiceLoaing, setUninstallServiceLoading] = useState(false);
   // service mode
   // service mode
   const { data: serviceStatus, mutate: mutateServiceStatus } = useSWR(
   const { data: serviceStatus, mutate: mutateServiceStatus } = useSWR(
     "checkService",
     "checkService",
@@ -39,14 +31,12 @@ const SettingSystem = ({ onError }: Props) => {
     }
     }
   );
   );
 
 
-  const serviceRef = useRef<DialogRef>(null);
   const sysproxyRef = useRef<DialogRef>(null);
   const sysproxyRef = useRef<DialogRef>(null);
   const tunRef = useRef<DialogRef>(null);
   const tunRef = useRef<DialogRef>(null);
 
 
   const {
   const {
     enable_tun_mode,
     enable_tun_mode,
     enable_auto_launch,
     enable_auto_launch,
-    enable_service_mode,
     enable_silent_start,
     enable_silent_start,
     enable_system_proxy,
     enable_system_proxy,
   } = verge ?? {};
   } = verge ?? {};
@@ -56,58 +46,10 @@ const SettingSystem = ({ onError }: Props) => {
     mutateVerge({ ...verge, ...patch }, false);
     mutateVerge({ ...verge, ...patch }, false);
   };
   };
 
 
-  const onInstallOrEnableService = useLockFn(async () => {
-    setServiceLoading(true);
-    try {
-      if (serviceStatus === "uninstall" || serviceStatus === "unknown") {
-        // install service
-        await installService();
-        await mutateServiceStatus();
-        setTimeout(() => {
-          mutateServiceStatus();
-        }, 2000);
-        Notice.success(t("Service Installed Successfully"));
-        setServiceLoading(false);
-      } else {
-        // enable or disable service
-        const enable = serviceStatus === "active";
-        await patchVerge({ enable_service_mode: !enable });
-        onChangeData({ enable_service_mode: !enable });
-        await mutateServiceStatus();
-        setTimeout(() => {
-          mutateServiceStatus();
-        }, 2000);
-        setServiceLoading(false);
-      }
-    } catch (err: any) {
-      await mutateServiceStatus();
-      Notice.error(err.message || err.toString());
-      setServiceLoading(false);
-    }
-  });
-
-  const onUninstallService = useLockFn(async () => {
-    setUninstallServiceLoading(true);
-    try {
-      await uninstallService();
-      await mutateServiceStatus();
-      setTimeout(() => {
-        mutateServiceStatus();
-      }, 2000);
-      Notice.success(t("Service Uninstalled Successfully"));
-      setUninstallServiceLoading(false);
-    } catch (err: any) {
-      await mutateServiceStatus();
-      Notice.error(err.message || err.toString());
-      setUninstallServiceLoading(false);
-    }
-  });
-
   return (
   return (
     <SettingList title={t("System Setting")}>
     <SettingList title={t("System Setting")}>
       <SysproxyViewer ref={sysproxyRef} />
       <SysproxyViewer ref={sysproxyRef} />
       <TunViewer ref={tunRef} />
       <TunViewer ref={tunRef} />
-      <ServiceViewer ref={serviceRef} enable={!!enable_service_mode} />
 
 
       <SettingItem
       <SettingItem
         label={t("Tun Mode")}
         label={t("Tun Mode")}
@@ -133,7 +75,7 @@ const SettingSystem = ({ onError }: Props) => {
           }}
           }}
           onGuard={(e) => {
           onGuard={(e) => {
             if (serviceStatus !== "active" && e) {
             if (serviceStatus !== "active" && e) {
-              Notice.error(t("Please enable service mode first"));
+              Notice.error(t("Please Enable Service Mode"));
               return Promise.resolve();
               return Promise.resolve();
             } else {
             } else {
               return patchVerge({ enable_tun_mode: e });
               return patchVerge({ enable_tun_mode: e });
@@ -145,31 +87,12 @@ const SettingSystem = ({ onError }: Props) => {
       </SettingItem>
       </SettingItem>
 
 
       <SettingItem label={t("Service Mode")}>
       <SettingItem label={t("Service Mode")}>
-        <LoadingButton
-          size="small"
-          variant="contained"
-          sx={{ mr: serviceStatus !== "installed" ? -1 : 0 }}
-          onClick={onInstallOrEnableService}
-          loading={serviceLoading}
-        >
-          {serviceStatus === "active"
-            ? t("Disable")
-            : serviceStatus === "installed"
-            ? t("Enable")
-            : t("Install")}
-        </LoadingButton>
-        {serviceStatus === "installed" && (
-          <LoadingButton
-            size="small"
-            variant="outlined"
-            color="error"
-            sx={{ ml: 1, mr: -1 }}
-            onClick={onUninstallService}
-            loading={uninstallServiceLoaing}
-          >
-            {t("Uninstall")}
-          </LoadingButton>
-        )}
+        <ServiceSwitcher
+          status={serviceStatus ?? "unknown"}
+          mutate={mutateServiceStatus}
+          patchVerge={patchVerge}
+          onChangeData={onChangeData}
+        />
       </SettingItem>
       </SettingItem>
 
 
       <SettingItem
       <SettingItem

+ 1 - 1
src/locales/en.json

@@ -266,7 +266,7 @@
   "Restart": "Restart",
   "Restart": "Restart",
   "Release Version": "Release Version",
   "Release Version": "Release Version",
   "Alpha Version": "Alpha Version",
   "Alpha Version": "Alpha Version",
-  "Tun mode requires": "Tun mode requires",
+  "Please Enable Service Mode": "Please Install and Enable Service Mode First",
   "Grant": "Grant",
   "Grant": "Grant",
   "Open UWP tool": "Open UWP tool",
   "Open UWP tool": "Open UWP tool",
   "Open UWP tool Info": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction",
   "Open UWP tool Info": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction",

+ 1 - 1
src/locales/fa.json

@@ -261,7 +261,7 @@
   "Restart": "راه‌اندازی مجدد",
   "Restart": "راه‌اندازی مجدد",
   "Release Version": "نسخه نهایی",
   "Release Version": "نسخه نهایی",
   "Alpha Version": "نسخه آلفا",
   "Alpha Version": "نسخه آلفا",
-  "Tun mode requires": "Tun mode نیاز دارد",
+  "Please Install and Enable Service Mode First": "لطفاً ابتدا حالت سرویس را نصب و فعال کنید",
   "Grant": "اعطا",
   "Grant": "اعطا",
   "Open UWP tool": "باز کردن ابزار UWP",
   "Open UWP tool": "باز کردن ابزار UWP",
   "Open UWP tool Info": "از ویندوز 8 به بعد، برنامه‌های UWP (مانند Microsoft Store) از دسترسی مستقیم به خدمات شبکه محلی محدود شده‌اند و این ابزار می‌تواند برای دور زدن این محدودیت استفاده شود",
   "Open UWP tool Info": "از ویندوز 8 به بعد، برنامه‌های UWP (مانند Microsoft Store) از دسترسی مستقیم به خدمات شبکه محلی محدود شده‌اند و این ابزار می‌تواند برای دور زدن این محدودیت استفاده شود",

+ 1 - 1
src/locales/ru.json

@@ -264,7 +264,7 @@
   "Restart": "Перезапуск",
   "Restart": "Перезапуск",
   "Release Version": "Официальная версия",
   "Release Version": "Официальная версия",
   "Alpha Version": "Альфа-версия",
   "Alpha Version": "Альфа-версия",
-  "Tun mode requires": "Требуется Режим туннеля",
+  "Please Enable Service Mode": "Пожалуйста, сначала установите и включите режим обслуживания",
   "Grant": "Предоставить",
   "Grant": "Предоставить",
   "Open UWP tool": "Открыть UWP инструмент",
   "Open UWP tool": "Открыть UWP инструмент",
   "Open UWP tool Info": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение",
   "Open UWP tool Info": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение",

+ 1 - 1
src/locales/zh.json

@@ -266,7 +266,7 @@
   "Restart": "重启内核",
   "Restart": "重启内核",
   "Release Version": "正式版",
   "Release Version": "正式版",
   "Alpha Version": "预览版",
   "Alpha Version": "预览版",
-  "Tun mode requires": "如需启用 Tun 模式需要授权",
+  "Please Enable Service Mode": "请先安装并启用服务模式",
   "Grant": "授权",
   "Grant": "授权",
   "Open UWP tool": "UWP 工具",
   "Open UWP tool": "UWP 工具",
   "Open UWP tool Info": "Windows 8开始限制 UWP 应用(如微软商店)直接访问本地主机的网络服务,使用此工具可绕过该限制",
   "Open UWP tool Info": "Windows 8开始限制 UWP 应用(如微软商店)直接访问本地主机的网络服务,使用此工具可绕过该限制",