fix: unified switch style

This commit is contained in:
MystiPanda 2024-07-15 20:29:56 +08:00
parent ef337ffb69
commit 4cd7ccda57
No known key found for this signature in database
8 changed files with 112 additions and 220 deletions

View File

@ -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,

View File

@ -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>
)}
</>
);
};

View File

@ -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>
);
});

View File

@ -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 { import { checkService } from "@/services/cmds";
checkService,
installService,
uninstallService,
} 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 <ServiceSwitcher
size="small" status={serviceStatus ?? "unknown"}
variant="contained" mutate={mutateServiceStatus}
sx={{ mr: serviceStatus !== "installed" ? -1 : 0 }} patchVerge={patchVerge}
onClick={onInstallOrEnableService} onChangeData={onChangeData}
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>
)}
</SettingItem> </SettingItem>
<SettingItem <SettingItem

View File

@ -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",

View File

@ -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) از دسترسی مستقیم به خدمات شبکه محلی محدود شده‌اند و این ابزار می‌تواند برای دور زدن این محدودیت استفاده شود",

View File

@ -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) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение",

View File

@ -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 应用(如微软商店)直接访问本地主机的网络服务,使用此工具可绕过该限制",