feat: support clash meta memory usage display
This commit is contained in:
parent
6f5acee1c3
commit
96ffbe2f84
@ -26,6 +26,9 @@ pub struct IVerge {
|
|||||||
/// enable traffic graph default is true
|
/// enable traffic graph default is true
|
||||||
pub traffic_graph: Option<bool>,
|
pub traffic_graph: Option<bool>,
|
||||||
|
|
||||||
|
/// show memory info (only for Clash Meta)
|
||||||
|
pub enable_memory_usage: Option<bool>,
|
||||||
|
|
||||||
/// clash tun mode
|
/// clash tun mode
|
||||||
pub enable_tun_mode: Option<bool>,
|
pub enable_tun_mode: Option<bool>,
|
||||||
|
|
||||||
@ -125,6 +128,7 @@ impl IVerge {
|
|||||||
theme_mode: Some("system".into()),
|
theme_mode: Some("system".into()),
|
||||||
theme_blur: Some(false),
|
theme_blur: Some(false),
|
||||||
traffic_graph: Some(true),
|
traffic_graph: Some(true),
|
||||||
|
enable_memory_usage: Some(true),
|
||||||
enable_auto_launch: Some(false),
|
enable_auto_launch: Some(false),
|
||||||
enable_silent_start: Some(false),
|
enable_silent_start: Some(false),
|
||||||
enable_system_proxy: Some(false),
|
enable_system_proxy: Some(false),
|
||||||
@ -158,6 +162,7 @@ impl IVerge {
|
|||||||
patch!(theme_mode);
|
patch!(theme_mode);
|
||||||
patch!(theme_blur);
|
patch!(theme_blur);
|
||||||
patch!(traffic_graph);
|
patch!(traffic_graph);
|
||||||
|
patch!(enable_memory_usage);
|
||||||
|
|
||||||
patch!(enable_tun_mode);
|
patch!(enable_tun_mode);
|
||||||
patch!(enable_service_mode);
|
patch!(enable_service_mode);
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { Box, Typography } from "@mui/material";
|
import { Box, Typography } from "@mui/material";
|
||||||
import { ArrowDownward, ArrowUpward } from "@mui/icons-material";
|
import {
|
||||||
|
ArrowDownward,
|
||||||
|
ArrowUpward,
|
||||||
|
MemoryOutlined,
|
||||||
|
} from "@mui/icons-material";
|
||||||
import { useClashInfo } from "@/hooks/use-clash";
|
import { useClashInfo } from "@/hooks/use-clash";
|
||||||
import { useVerge } from "@/hooks/use-verge";
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
import { TrafficGraph, type TrafficRef } from "./traffic-graph";
|
import { TrafficGraph, type TrafficRef } from "./traffic-graph";
|
||||||
@ -12,13 +16,15 @@ import parseTraffic from "@/utils/parse-traffic";
|
|||||||
// setup the traffic
|
// setup the traffic
|
||||||
const LayoutTraffic = () => {
|
const LayoutTraffic = () => {
|
||||||
const { clashInfo } = useClashInfo();
|
const { clashInfo } = useClashInfo();
|
||||||
|
const { verge } = useVerge();
|
||||||
|
|
||||||
// whether hide traffic graph
|
// whether hide traffic graph
|
||||||
const { verge } = useVerge();
|
|
||||||
const trafficGraph = verge?.traffic_graph ?? true;
|
const trafficGraph = verge?.traffic_graph ?? true;
|
||||||
|
|
||||||
const trafficRef = useRef<TrafficRef>(null);
|
const trafficRef = useRef<TrafficRef>(null);
|
||||||
const [traffic, setTraffic] = useState({ up: 0, down: 0 });
|
const [traffic, setTraffic] = useState({ up: 0, down: 0 });
|
||||||
|
const [memory, setMemory] = useState({ inuse: 0 });
|
||||||
|
const pageVisible = useVisibility();
|
||||||
|
|
||||||
// setup log ws during layout
|
// setup log ws during layout
|
||||||
useLogSetup();
|
useLogSetup();
|
||||||
@ -29,8 +35,6 @@ const LayoutTraffic = () => {
|
|||||||
setTraffic(data);
|
setTraffic(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
const pageVisible = useVisibility();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!clashInfo || !pageVisible) return;
|
if (!clashInfo || !pageVisible) return;
|
||||||
|
|
||||||
@ -42,14 +46,38 @@ const LayoutTraffic = () => {
|
|||||||
};
|
};
|
||||||
}, [clashInfo, pageVisible]);
|
}, [clashInfo, pageVisible]);
|
||||||
|
|
||||||
|
/* --------- meta memory information --------- */
|
||||||
|
const isMetaCore = verge?.clash_core === "clash-meta";
|
||||||
|
const displayMemory = isMetaCore && (verge?.enable_memory_usage ?? true);
|
||||||
|
|
||||||
|
const memoryWs = useWebsocket(
|
||||||
|
(event) => {
|
||||||
|
setMemory(JSON.parse(event.data));
|
||||||
|
},
|
||||||
|
{ onError: () => setMemory({ inuse: 0 }) }
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!clashInfo || !pageVisible || !displayMemory) return;
|
||||||
|
const { server = "", secret = "" } = clashInfo;
|
||||||
|
memoryWs.connect(
|
||||||
|
`ws://${server}/memory?token=${encodeURIComponent(secret)}`
|
||||||
|
);
|
||||||
|
return () => memoryWs.disconnect();
|
||||||
|
}, [clashInfo, pageVisible, displayMemory]);
|
||||||
|
|
||||||
const [up, upUnit] = parseTraffic(traffic.up);
|
const [up, upUnit] = parseTraffic(traffic.up);
|
||||||
const [down, downUnit] = parseTraffic(traffic.down);
|
const [down, downUnit] = parseTraffic(traffic.down);
|
||||||
|
const [inuse, inuseUnit] = parseTraffic(memory.inuse);
|
||||||
|
|
||||||
|
const iconStyle: any = {
|
||||||
|
sx: { mr: "8px", fontSize: 16 },
|
||||||
|
};
|
||||||
const valStyle: any = {
|
const valStyle: any = {
|
||||||
component: "span",
|
component: "span",
|
||||||
color: "primary",
|
color: "primary",
|
||||||
textAlign: "center",
|
textAlign: "center",
|
||||||
sx: { flex: "1 1 54px", userSelect: "none" },
|
sx: { flex: "1 1 56px", userSelect: "none" },
|
||||||
};
|
};
|
||||||
const unitStyle: any = {
|
const unitStyle: any = {
|
||||||
component: "span",
|
component: "span",
|
||||||
@ -71,22 +99,37 @@ const LayoutTraffic = () => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<Box mb={1.5} display="flex" alignItems="center" whiteSpace="nowrap">
|
<Box display="flex" flexDirection="column" gap={0.75}>
|
||||||
<ArrowUpward
|
<Box display="flex" alignItems="center" whiteSpace="nowrap">
|
||||||
sx={{ mr: 0.75, fontSize: 18 }}
|
<ArrowUpward
|
||||||
color={+up > 0 ? "primary" : "disabled"}
|
{...iconStyle}
|
||||||
/>
|
color={+up > 0 ? "primary" : "disabled"}
|
||||||
<Typography {...valStyle}>{up}</Typography>
|
/>
|
||||||
<Typography {...unitStyle}>{upUnit}/s</Typography>
|
<Typography {...valStyle}>{up}</Typography>
|
||||||
</Box>
|
<Typography {...unitStyle}>{upUnit}/s</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box display="flex" alignItems="center" whiteSpace="nowrap">
|
<Box display="flex" alignItems="center" whiteSpace="nowrap">
|
||||||
<ArrowDownward
|
<ArrowDownward
|
||||||
sx={{ mr: 0.75, fontSize: 18 }}
|
{...iconStyle}
|
||||||
color={+down > 0 ? "primary" : "disabled"}
|
color={+down > 0 ? "primary" : "disabled"}
|
||||||
/>
|
/>
|
||||||
<Typography {...valStyle}>{down}</Typography>
|
<Typography {...valStyle}>{down}</Typography>
|
||||||
<Typography {...unitStyle}>{downUnit}/s</Typography>
|
<Typography {...unitStyle}>{downUnit}/s</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{displayMemory && (
|
||||||
|
<Box
|
||||||
|
display="flex"
|
||||||
|
alignItems="center"
|
||||||
|
whiteSpace="nowrap"
|
||||||
|
title="Memory Usage"
|
||||||
|
>
|
||||||
|
<MemoryOutlined {...iconStyle} color="disabled" />
|
||||||
|
<Typography {...valStyle}>{inuse}</Typography>
|
||||||
|
<Typography {...unitStyle}>{inuseUnit}</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
80
src/components/setting/mods/layout-viewer.tsx
Normal file
80
src/components/setting/mods/layout-viewer.tsx
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
import { forwardRef, useImperativeHandle, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { List, Switch } from "@mui/material";
|
||||||
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
|
import { BaseDialog, DialogRef, Notice } from "@/components/base";
|
||||||
|
import { SettingItem } from "./setting-comp";
|
||||||
|
import { GuardState } from "./guard-state";
|
||||||
|
|
||||||
|
export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { verge, patchVerge, mutateVerge } = useVerge();
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
open: () => setOpen(true),
|
||||||
|
close: () => setOpen(false),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const onSwitchFormat = (_e: any, value: boolean) => value;
|
||||||
|
const onError = (err: any) => {
|
||||||
|
Notice.error(err.message || err.toString());
|
||||||
|
};
|
||||||
|
const onChangeData = (patch: Partial<IVergeConfig>) => {
|
||||||
|
mutateVerge({ ...verge, ...patch }, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseDialog
|
||||||
|
open={open}
|
||||||
|
title={t("Layout Setting")}
|
||||||
|
contentSx={{ width: 450 }}
|
||||||
|
disableOk
|
||||||
|
cancelBtn={t("Cancel")}
|
||||||
|
onClose={() => setOpen(false)}
|
||||||
|
onCancel={() => setOpen(false)}
|
||||||
|
>
|
||||||
|
<List>
|
||||||
|
<SettingItem label={t("Theme Blur")}>
|
||||||
|
<GuardState
|
||||||
|
value={verge?.theme_blur ?? false}
|
||||||
|
valueProps="checked"
|
||||||
|
onCatch={onError}
|
||||||
|
onFormat={onSwitchFormat}
|
||||||
|
onChange={(e) => onChangeData({ theme_blur: e })}
|
||||||
|
onGuard={(e) => patchVerge({ theme_blur: e })}
|
||||||
|
>
|
||||||
|
<Switch edge="end" />
|
||||||
|
</GuardState>
|
||||||
|
</SettingItem>
|
||||||
|
|
||||||
|
<SettingItem label={t("Traffic Graph")}>
|
||||||
|
<GuardState
|
||||||
|
value={verge?.traffic_graph ?? true}
|
||||||
|
valueProps="checked"
|
||||||
|
onCatch={onError}
|
||||||
|
onFormat={onSwitchFormat}
|
||||||
|
onChange={(e) => onChangeData({ traffic_graph: e })}
|
||||||
|
onGuard={(e) => patchVerge({ traffic_graph: e })}
|
||||||
|
>
|
||||||
|
<Switch edge="end" />
|
||||||
|
</GuardState>
|
||||||
|
</SettingItem>
|
||||||
|
|
||||||
|
<SettingItem label={t("Memory Usage")}>
|
||||||
|
<GuardState
|
||||||
|
value={verge?.enable_memory_usage ?? true}
|
||||||
|
valueProps="checked"
|
||||||
|
onCatch={onError}
|
||||||
|
onFormat={onSwitchFormat}
|
||||||
|
onChange={(e) => onChangeData({ enable_memory_usage: e })}
|
||||||
|
onGuard={(e) => patchVerge({ enable_memory_usage: e })}
|
||||||
|
>
|
||||||
|
<Switch edge="end" />
|
||||||
|
</GuardState>
|
||||||
|
</SettingItem>
|
||||||
|
</List>
|
||||||
|
</BaseDialog>
|
||||||
|
);
|
||||||
|
});
|
@ -11,10 +11,11 @@ interface ItemProps {
|
|||||||
label: ReactNode;
|
label: ReactNode;
|
||||||
extra?: ReactNode;
|
extra?: ReactNode;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
|
secondary?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SettingItem: React.FC<ItemProps> = (props) => {
|
export const SettingItem: React.FC<ItemProps> = (props) => {
|
||||||
const { label, extra, children } = props;
|
const { label, extra, children, secondary } = props;
|
||||||
|
|
||||||
const primary = !extra ? (
|
const primary = !extra ? (
|
||||||
label
|
label
|
||||||
@ -27,7 +28,7 @@ export const SettingItem: React.FC<ItemProps> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItem sx={{ pt: "5px", pb: "5px" }}>
|
<ListItem sx={{ pt: "5px", pb: "5px" }}>
|
||||||
<ListItemText primary={primary} />
|
<ListItemText primary={primary} secondary={secondary} />
|
||||||
{children}
|
{children}
|
||||||
</ListItem>
|
</ListItem>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import { IconButton, MenuItem, Select, Typography } from "@mui/material";
|
||||||
IconButton,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
Switch,
|
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { openAppDir, openCoreDir, openLogsDir } from "@/services/cmds";
|
import { openAppDir, openCoreDir, openLogsDir } from "@/services/cmds";
|
||||||
import { ArrowForward } from "@mui/icons-material";
|
import { ArrowForward } from "@mui/icons-material";
|
||||||
import { useVerge } from "@/hooks/use-verge";
|
import { useVerge } from "@/hooks/use-verge";
|
||||||
@ -19,6 +13,7 @@ import { HotkeyViewer } from "./mods/hotkey-viewer";
|
|||||||
import { MiscViewer } from "./mods/misc-viewer";
|
import { MiscViewer } from "./mods/misc-viewer";
|
||||||
import { ThemeViewer } from "./mods/theme-viewer";
|
import { ThemeViewer } from "./mods/theme-viewer";
|
||||||
import { GuardState } from "./mods/guard-state";
|
import { GuardState } from "./mods/guard-state";
|
||||||
|
import { LayoutViewer } from "./mods/layout-viewer";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onError?: (err: Error) => void;
|
onError?: (err: Error) => void;
|
||||||
@ -35,6 +30,7 @@ const SettingVerge = ({ onError }: Props) => {
|
|||||||
const hotkeyRef = useRef<DialogRef>(null);
|
const hotkeyRef = useRef<DialogRef>(null);
|
||||||
const miscRef = useRef<DialogRef>(null);
|
const miscRef = useRef<DialogRef>(null);
|
||||||
const themeRef = useRef<DialogRef>(null);
|
const themeRef = useRef<DialogRef>(null);
|
||||||
|
const layoutRef = useRef<DialogRef>(null);
|
||||||
|
|
||||||
const onSwitchFormat = (_e: any, value: boolean) => value;
|
const onSwitchFormat = (_e: any, value: boolean) => value;
|
||||||
const onChangeData = (patch: Partial<IVergeConfig>) => {
|
const onChangeData = (patch: Partial<IVergeConfig>) => {
|
||||||
@ -47,6 +43,7 @@ const SettingVerge = ({ onError }: Props) => {
|
|||||||
<ConfigViewer ref={configRef} />
|
<ConfigViewer ref={configRef} />
|
||||||
<HotkeyViewer ref={hotkeyRef} />
|
<HotkeyViewer ref={hotkeyRef} />
|
||||||
<MiscViewer ref={miscRef} />
|
<MiscViewer ref={miscRef} />
|
||||||
|
<LayoutViewer ref={layoutRef} />
|
||||||
|
|
||||||
<SettingItem label={t("Language")}>
|
<SettingItem label={t("Language")}>
|
||||||
<GuardState
|
<GuardState
|
||||||
@ -75,30 +72,26 @@ const SettingVerge = ({ onError }: Props) => {
|
|||||||
</GuardState>
|
</GuardState>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
<SettingItem label={t("Theme Blur")}>
|
<SettingItem label={t("Theme Setting")}>
|
||||||
<GuardState
|
<IconButton
|
||||||
value={theme_blur ?? false}
|
color="inherit"
|
||||||
valueProps="checked"
|
size="small"
|
||||||
onCatch={onError}
|
sx={{ my: "2px" }}
|
||||||
onFormat={onSwitchFormat}
|
onClick={() => themeRef.current?.open()}
|
||||||
onChange={(e) => onChangeData({ theme_blur: e })}
|
|
||||||
onGuard={(e) => patchVerge({ theme_blur: e })}
|
|
||||||
>
|
>
|
||||||
<Switch edge="end" />
|
<ArrowForward />
|
||||||
</GuardState>
|
</IconButton>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
<SettingItem label={t("Traffic Graph")}>
|
<SettingItem label={t("Layout Setting")}>
|
||||||
<GuardState
|
<IconButton
|
||||||
value={traffic_graph ?? true}
|
color="inherit"
|
||||||
valueProps="checked"
|
size="small"
|
||||||
onCatch={onError}
|
sx={{ my: "2px" }}
|
||||||
onFormat={onSwitchFormat}
|
onClick={() => layoutRef.current?.open()}
|
||||||
onChange={(e) => onChangeData({ traffic_graph: e })}
|
|
||||||
onGuard={(e) => patchVerge({ traffic_graph: e })}
|
|
||||||
>
|
>
|
||||||
<Switch edge="end" />
|
<ArrowForward />
|
||||||
</GuardState>
|
</IconButton>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
<SettingItem label={t("Miscellaneous")}>
|
<SettingItem label={t("Miscellaneous")}>
|
||||||
@ -112,17 +105,6 @@ const SettingVerge = ({ onError }: Props) => {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</SettingItem>
|
</SettingItem>
|
||||||
|
|
||||||
<SettingItem label={t("Theme Setting")}>
|
|
||||||
<IconButton
|
|
||||||
color="inherit"
|
|
||||||
size="small"
|
|
||||||
sx={{ my: "2px" }}
|
|
||||||
onClick={() => themeRef.current?.open()}
|
|
||||||
>
|
|
||||||
<ArrowForward />
|
|
||||||
</IconButton>
|
|
||||||
</SettingItem>
|
|
||||||
|
|
||||||
<SettingItem label={t("Hotkey Setting")}>
|
<SettingItem label={t("Hotkey Setting")}>
|
||||||
<IconButton
|
<IconButton
|
||||||
color="inherit"
|
color="inherit"
|
||||||
|
@ -5,6 +5,7 @@ export type WsMsgFn = (event: MessageEvent<any>) => void;
|
|||||||
export interface WsOptions {
|
export interface WsOptions {
|
||||||
errorCount?: number; // default is 5
|
errorCount?: number; // default is 5
|
||||||
retryInterval?: number; // default is 2500
|
retryInterval?: number; // default is 2500
|
||||||
|
onError?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWebsocket = (onMessage: WsMsgFn, options?: WsOptions) => {
|
export const useWebsocket = (onMessage: WsMsgFn, options?: WsOptions) => {
|
||||||
@ -38,6 +39,9 @@ export const useWebsocket = (onMessage: WsMsgFn, options?: WsOptions) => {
|
|||||||
|
|
||||||
if (errorCount >= 0) {
|
if (errorCount >= 0) {
|
||||||
timerRef.current = setTimeout(connectHelper, 2500);
|
timerRef.current = setTimeout(connectHelper, 2500);
|
||||||
|
} else {
|
||||||
|
disconnect();
|
||||||
|
options?.onError?.();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -55,6 +55,8 @@
|
|||||||
"Descriptions": "Descriptions",
|
"Descriptions": "Descriptions",
|
||||||
"Subscription URL": "Subscription URL",
|
"Subscription URL": "Subscription URL",
|
||||||
"Update Interval": "Update Interval",
|
"Update Interval": "Update Interval",
|
||||||
|
"Use System Proxy": "Use System Proxy",
|
||||||
|
"Use Clash Proxy": "Use Clash Proxy",
|
||||||
|
|
||||||
"Settings": "Settings",
|
"Settings": "Settings",
|
||||||
"Clash Setting": "Clash Setting",
|
"Clash Setting": "Clash Setting",
|
||||||
@ -64,6 +66,7 @@
|
|||||||
"IPv6": "IPv6",
|
"IPv6": "IPv6",
|
||||||
"Log Level": "Log Level",
|
"Log Level": "Log Level",
|
||||||
"Mixed Port": "Mixed Port",
|
"Mixed Port": "Mixed Port",
|
||||||
|
"External": "External",
|
||||||
"Clash Core": "Clash Core",
|
"Clash Core": "Clash Core",
|
||||||
"Tun Mode": "Tun Mode",
|
"Tun Mode": "Tun Mode",
|
||||||
"Service Mode": "Service Mode",
|
"Service Mode": "Service Mode",
|
||||||
@ -78,8 +81,11 @@
|
|||||||
"Theme Mode": "Theme Mode",
|
"Theme Mode": "Theme Mode",
|
||||||
"Theme Blur": "Theme Blur",
|
"Theme Blur": "Theme Blur",
|
||||||
"Theme Setting": "Theme Setting",
|
"Theme Setting": "Theme Setting",
|
||||||
|
"Layout Setting": "Layout Setting",
|
||||||
|
"Miscellaneous": "Miscellaneous",
|
||||||
"Hotkey Setting": "Hotkey Setting",
|
"Hotkey Setting": "Hotkey Setting",
|
||||||
"Traffic Graph": "Traffic Graph",
|
"Traffic Graph": "Traffic Graph",
|
||||||
|
"Memory Usage": "Memory Usage",
|
||||||
"Language": "Language",
|
"Language": "Language",
|
||||||
"Open App Dir": "Open App Dir",
|
"Open App Dir": "Open App Dir",
|
||||||
"Open Core Dir": "Open Core Dir",
|
"Open Core Dir": "Open Core Dir",
|
||||||
@ -97,6 +103,10 @@
|
|||||||
"Save": "Save",
|
"Save": "Save",
|
||||||
"Cancel": "Cancel",
|
"Cancel": "Cancel",
|
||||||
|
|
||||||
|
"Default": "Default",
|
||||||
|
"Download Speed": "Download Speed",
|
||||||
|
"Upload Speed": "Upload Speed",
|
||||||
|
|
||||||
"clash_mode_rule": "Rule Mode",
|
"clash_mode_rule": "Rule Mode",
|
||||||
"clash_mode_global": "Global Mode",
|
"clash_mode_global": "Global Mode",
|
||||||
"clash_mode_direct": "Direct Mode",
|
"clash_mode_direct": "Direct Mode",
|
||||||
|
@ -80,10 +80,12 @@
|
|||||||
"Current System Proxy": "当前系统代理",
|
"Current System Proxy": "当前系统代理",
|
||||||
"Theme Mode": "主题模式",
|
"Theme Mode": "主题模式",
|
||||||
"Theme Blur": "背景模糊",
|
"Theme Blur": "背景模糊",
|
||||||
"Miscellaneous": "杂项设置",
|
|
||||||
"Theme Setting": "主题设置",
|
"Theme Setting": "主题设置",
|
||||||
|
"Layout Setting": "界面设置",
|
||||||
|
"Miscellaneous": "杂项设置",
|
||||||
"Hotkey Setting": "热键设置",
|
"Hotkey Setting": "热键设置",
|
||||||
"Traffic Graph": "流量图显",
|
"Traffic Graph": "流量图显",
|
||||||
|
"Memory Usage": "内存使用",
|
||||||
"Language": "语言设置",
|
"Language": "语言设置",
|
||||||
"Open App Dir": "应用目录",
|
"Open App Dir": "应用目录",
|
||||||
"Open Core Dir": "内核目录",
|
"Open Core Dir": "内核目录",
|
||||||
|
1
src/services/types.d.ts
vendored
1
src/services/types.d.ts
vendored
@ -159,6 +159,7 @@ interface IVergeConfig {
|
|||||||
theme_mode?: "light" | "dark" | "system";
|
theme_mode?: "light" | "dark" | "system";
|
||||||
theme_blur?: boolean;
|
theme_blur?: boolean;
|
||||||
traffic_graph?: boolean;
|
traffic_graph?: boolean;
|
||||||
|
enable_memory_usage?: boolean;
|
||||||
enable_tun_mode?: boolean;
|
enable_tun_mode?: boolean;
|
||||||
enable_auto_launch?: boolean;
|
enable_auto_launch?: boolean;
|
||||||
enable_service_mode?: boolean;
|
enable_service_mode?: boolean;
|
||||||
|
Loading…
Reference in New Issue
Block a user