Refactor components to remove forwardRef and simplify props handling

- Updated multiple components to remove the use of forwardRef, simplifying the props structure.
- Adjusted imports and component definitions accordingly.
- Ensured consistent handling of refs and props across various viewer components.
- Improved readability and maintainability of the codebase.
This commit is contained in:
Tunglies
2025-09-30 14:23:29 +08:00
parent 0c88568cd7
commit 1cd013fb94
25 changed files with 1380 additions and 1455 deletions

View File

@@ -1,16 +1,10 @@
import { Box, Paper, Divider } from "@mui/material";
import dayjs from "dayjs";
import customParseFormat from "dayjs/plugin/customParseFormat";
import {
forwardRef,
useImperativeHandle,
useState,
useCallback,
useMemo,
} from "react";
import { useImperativeHandle, useState, useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef } from "@/components/base";
import { BaseDialog } from "@/components/base";
import { BaseLoadingOverlay } from "@/components/base";
import { listWebDavBackup } from "@/services/cmds";
@@ -25,7 +19,7 @@ dayjs.extend(customParseFormat);
const DATE_FORMAT = "YYYY-MM-DD_HH-mm-ss";
const FILENAME_PATTERN = /\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}/;
export const BackupViewer = forwardRef<DialogRef>((props, ref) => {
export const BackupViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
@@ -131,4 +125,4 @@ export const BackupViewer = forwardRef<DialogRef>((props, ref) => {
</Box>
</BaseDialog>
);
});
};

View File

@@ -12,11 +12,11 @@ import {
ListItemText,
} from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { mutate } from "swr";
import { BaseDialog, DialogRef } from "@/components/base";
import { BaseDialog } from "@/components/base";
import { useVerge } from "@/hooks/use-verge";
import { changeClashCore, restartCore } from "@/services/cmds";
import {
@@ -31,7 +31,7 @@ const VALID_CORE = [
{ name: "Mihomo Alpha", core: "verge-mihomo-alpha", chip: "Alpha Version" },
];
export const ClashCoreViewer = forwardRef<DialogRef>((props, ref) => {
export const ClashCoreViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const { verge, mutateVerge } = useVerge();
@@ -169,4 +169,4 @@ export const ClashCoreViewer = forwardRef<DialogRef>((props, ref) => {
</List>
</BaseDialog>
);
});
};

View File

@@ -9,7 +9,7 @@ import {
TextField,
} from "@mui/material";
import { useLockFn, useRequest } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, Switch } from "@/components/base";
@@ -30,10 +30,12 @@ interface ClashPortViewerRef {
const generateRandomPort = () =>
Math.floor(Math.random() * (65535 - 1025 + 1)) + 1025;
export const ClashPortViewer = forwardRef<
ClashPortViewerRef,
ClashPortViewerProps
>((props, ref) => {
export const ClashPortViewer = ({
ref,
...props
}: ClashPortViewerProps & {
ref?: React.RefObject<ClashPortViewerRef | null>;
}) => {
const { t } = useTranslation();
const { clashInfo, patchInfo } = useClashInfo();
const { verge, patchVerge } = useVerge();
@@ -348,4 +350,4 @@ export const ClashPortViewer = forwardRef<
</List>
</BaseDialog>
);
});
};

View File

@@ -1,12 +1,11 @@
import { Box, Chip } from "@mui/material";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { DialogRef } from "@/components/base";
import { EditorViewer } from "@/components/profile/editor-viewer";
import { getRuntimeYaml } from "@/services/cmds";
export const ConfigViewer = forwardRef<DialogRef>((_, ref) => {
export const ConfigViewer = ({ ref, ..._ }) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const [runtimeConfig, setRuntimeConfig] = useState("");
@@ -38,4 +37,4 @@ export const ConfigViewer = forwardRef<DialogRef>((_, ref) => {
onClose={() => setOpen(false)}
/>
);
});
};

View File

@@ -12,15 +12,15 @@ import {
Tooltip,
} from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { useClashInfo } from "@/hooks/use-clash";
import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService";
export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
export const ControllerViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const [copySuccess, setCopySuccess] = useState<null | string>(null);
@@ -217,4 +217,4 @@ export const ControllerViewer = forwardRef<DialogRef>((props, ref) => {
</Snackbar>
</BaseDialog>
);
});
};

View File

@@ -15,11 +15,11 @@ import {
import { invoke } from "@tauri-apps/api/core";
import { useLockFn } from "ahooks";
import yaml from "js-yaml";
import { forwardRef, useImperativeHandle, useState, useEffect } from "react";
import { useImperativeHandle, useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import MonacoEditor from "react-monaco-editor";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { useClash } from "@/hooks/use-clash";
import { showNotice } from "@/services/noticeService";
import { useThemeMode } from "@/services/states";
@@ -87,7 +87,7 @@ const DEFAULT_DNS_CONFIG = {
},
};
export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
export const DnsViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const { clash, mutateClash } = useClash();
const themeMode = useThemeMode();
@@ -1034,4 +1034,4 @@ export const DnsViewer = forwardRef<DialogRef>((props, ref) => {
)}
</BaseDialog>
);
});
};

View File

@@ -1,7 +1,7 @@
import { Delete as DeleteIcon } from "@mui/icons-material";
import { Box, Button, Divider, List, ListItem, TextField } from "@mui/material";
import { useLockFn, useRequest } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, Switch } from "@/components/base";
@@ -71,201 +71,194 @@ interface ClashHeaderConfigingRef {
close: () => void;
}
export const HeaderConfiguration = forwardRef<ClashHeaderConfigingRef>(
(props, ref) => {
const { t } = useTranslation();
const { clash, mutateClash, patchClash } = useClash();
const [open, setOpen] = useState(false);
export const HeaderConfiguration = ({ ref, ...props }) => {
const { t } = useTranslation();
const { clash, mutateClash, patchClash } = useClash();
const [open, setOpen] = useState(false);
// CORS配置状态管理
const [corsConfig, setCorsConfig] = useState<{
allowPrivateNetwork: boolean;
allowOrigins: string[];
}>(() => {
// CORS配置状态管理
const [corsConfig, setCorsConfig] = useState<{
allowPrivateNetwork: boolean;
allowOrigins: string[];
}>(() => {
const cors = clash?.["external-controller-cors"];
const origins = cors?.["allow-origins"] ?? [];
return {
allowPrivateNetwork: cors?.["allow-private-network"] ?? true,
allowOrigins: filterBaseOriginsForUI(origins),
};
});
// 处理CORS配置变更
const handleCorsConfigChange = (
key: "allowPrivateNetwork" | "allowOrigins",
value: boolean | string[],
) => {
setCorsConfig((prev) => ({
...prev,
[key]: value,
}));
};
// 添加新的允许来源
const handleAddOrigin = () => {
handleCorsConfigChange("allowOrigins", [...corsConfig.allowOrigins, ""]);
};
// 更新允许来源列表中的某一项
const handleUpdateOrigin = (index: number, value: string) => {
const newOrigins = [...corsConfig.allowOrigins];
newOrigins[index] = value;
handleCorsConfigChange("allowOrigins", newOrigins);
};
// 删除允许来源列表中的某一项
const handleDeleteOrigin = (index: number) => {
const newOrigins = [...corsConfig.allowOrigins];
newOrigins.splice(index, 1);
handleCorsConfigChange("allowOrigins", newOrigins);
};
// 保存配置请求
const { loading, run: saveConfig } = useRequest(
async () => {
// 保存时使用完整的源列表包括开发URL
const fullOrigins = getFullOrigins(corsConfig.allowOrigins);
await patchClash({
"external-controller-cors": {
"allow-private-network": corsConfig.allowPrivateNetwork,
"allow-origins": fullOrigins.filter(
(origin: string) => origin.trim() !== "",
),
},
});
await mutateClash();
},
{
manual: true,
onSuccess: () => {
setOpen(false);
showNotice("success", t("Configuration saved successfully"));
},
onError: () => {
showNotice("error", t("Failed to save configuration"));
},
},
);
useImperativeHandle(ref, () => ({
open: () => {
const cors = clash?.["external-controller-cors"];
const origins = cors?.["allow-origins"] ?? [];
return {
setCorsConfig({
allowPrivateNetwork: cors?.["allow-private-network"] ?? true,
allowOrigins: filterBaseOriginsForUI(origins),
};
});
});
setOpen(true);
},
close: () => setOpen(false),
}));
// 处理CORS配置变更
const handleCorsConfigChange = (
key: "allowPrivateNetwork" | "allowOrigins",
value: boolean | string[],
) => {
setCorsConfig((prev) => ({
...prev,
[key]: value,
}));
};
const handleSave = useLockFn(async () => {
await saveConfig();
});
// 添加新的允许来源
const handleAddOrigin = () => {
handleCorsConfigChange("allowOrigins", [...corsConfig.allowOrigins, ""]);
};
return (
<BaseDialog
open={open}
title={t("External Cors Configuration")}
contentSx={{ width: 500 }}
okBtn={loading ? t("Saving...") : t("Save")}
cancelBtn={t("Cancel")}
onClose={() => setOpen(false)}
onCancel={() => setOpen(false)}
onOk={handleSave}
>
<List sx={{ width: "90%", padding: 2 }}>
<ListItem sx={{ padding: "8px 0" }}>
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
width="100%"
>
<span style={{ fontWeight: "normal" }}>
{t("Allow private network access")}
</span>
<Switch
edge="end"
checked={corsConfig.allowPrivateNetwork}
onChange={(e) =>
handleCorsConfigChange("allowPrivateNetwork", e.target.checked)
}
/>
</Box>
</ListItem>
// 更新允许来源列表中的某一项
const handleUpdateOrigin = (index: number, value: string) => {
const newOrigins = [...corsConfig.allowOrigins];
newOrigins[index] = value;
handleCorsConfigChange("allowOrigins", newOrigins);
};
// 删除允许来源列表中的某一项
const handleDeleteOrigin = (index: number) => {
const newOrigins = [...corsConfig.allowOrigins];
newOrigins.splice(index, 1);
handleCorsConfigChange("allowOrigins", newOrigins);
};
// 保存配置请求
const { loading, run: saveConfig } = useRequest(
async () => {
// 保存时使用完整的源列表包括开发URL
const fullOrigins = getFullOrigins(corsConfig.allowOrigins);
await patchClash({
"external-controller-cors": {
"allow-private-network": corsConfig.allowPrivateNetwork,
"allow-origins": fullOrigins.filter(
(origin: string) => origin.trim() !== "",
),
},
});
await mutateClash();
},
{
manual: true,
onSuccess: () => {
setOpen(false);
showNotice("success", t("Configuration saved successfully"));
},
onError: () => {
showNotice("error", t("Failed to save configuration"));
},
},
);
useImperativeHandle(ref, () => ({
open: () => {
const cors = clash?.["external-controller-cors"];
const origins = cors?.["allow-origins"] ?? [];
setCorsConfig({
allowPrivateNetwork: cors?.["allow-private-network"] ?? true,
allowOrigins: filterBaseOriginsForUI(origins),
});
setOpen(true);
},
close: () => setOpen(false),
}));
const handleSave = useLockFn(async () => {
await saveConfig();
});
return (
<BaseDialog
open={open}
title={t("External Cors Configuration")}
contentSx={{ width: 500 }}
okBtn={loading ? t("Saving...") : t("Save")}
cancelBtn={t("Cancel")}
onClose={() => setOpen(false)}
onCancel={() => setOpen(false)}
onOk={handleSave}
>
<List sx={{ width: "90%", padding: 2 }}>
<ListItem sx={{ padding: "8px 0" }}>
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
width="100%"
>
<span style={{ fontWeight: "normal" }}>
{t("Allow private network access")}
</span>
<Switch
edge="end"
checked={corsConfig.allowPrivateNetwork}
onChange={(e) =>
handleCorsConfigChange(
"allowPrivateNetwork",
e.target.checked,
)
}
/>
</Box>
</ListItem>
<Divider sx={{ my: 2 }} />
<ListItem sx={{ padding: "8px 0" }}>
<div style={{ width: "100%" }}>
<div style={{ marginBottom: 8, fontWeight: "bold" }}>
{t("Allowed Origins")}
</div>
{corsConfig.allowOrigins.map((origin, index) => (
<div
key={index}
style={{
display: "flex",
alignItems: "center",
marginBottom: 8,
}}
>
<TextField
fullWidth
size="small"
sx={{ fontSize: 14, marginRight: 2 }}
value={origin}
onChange={(e) => handleUpdateOrigin(index, e.target.value)}
placeholder={t("Please enter a valid url")}
inputProps={{ style: { fontSize: 14 } }}
/>
<Button
variant="contained"
color="error"
size="small"
onClick={() => handleDeleteOrigin(index)}
disabled={corsConfig.allowOrigins.length <= 0}
sx={deleteButtonStyle}
>
<DeleteIcon fontSize="small" />
</Button>
</div>
))}
<Button
variant="contained"
size="small"
onClick={handleAddOrigin}
sx={addButtonStyle}
>
{t("Add")}
</Button>
<Divider sx={{ my: 2 }} />
<ListItem sx={{ padding: "8px 0" }}>
<div style={{ width: "100%" }}>
<div style={{ marginBottom: 8, fontWeight: "bold" }}>
{t("Allowed Origins")}
</div>
{corsConfig.allowOrigins.map((origin, index) => (
<div
key={index}
style={{
marginTop: 12,
padding: 8,
backgroundColor: "#f5f5f5",
borderRadius: 4,
display: "flex",
alignItems: "center",
marginBottom: 8,
}}
>
<div
style={{ color: "#666", fontSize: 12, fontStyle: "italic" }}
<TextField
fullWidth
size="small"
sx={{ fontSize: 14, marginRight: 2 }}
value={origin}
onChange={(e) => handleUpdateOrigin(index, e.target.value)}
placeholder={t("Please enter a valid url")}
inputProps={{ style: { fontSize: 14 } }}
/>
<Button
variant="contained"
color="error"
size="small"
onClick={() => handleDeleteOrigin(index)}
disabled={corsConfig.allowOrigins.length <= 0}
sx={deleteButtonStyle}
>
{t("Always included origins: {{urls}}", {
urls: DEV_URLS.join(", "),
})}
</div>
<DeleteIcon fontSize="small" />
</Button>
</div>
))}
<Button
variant="contained"
size="small"
onClick={handleAddOrigin}
sx={addButtonStyle}
>
{t("Add")}
</Button>
<div
style={{
marginTop: 12,
padding: 8,
backgroundColor: "#f5f5f5",
borderRadius: 4,
}}
>
<div style={{ color: "#666", fontSize: 12, fontStyle: "italic" }}>
{t("Always included origins: {{urls}}", {
urls: DEV_URLS.join(", "),
})}
</div>
</div>
</ListItem>
</List>
</BaseDialog>
);
},
);
</div>
</ListItem>
</List>
</BaseDialog>
);
};

View File

@@ -1,9 +1,9 @@
import { styled, Typography } from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService";
@@ -26,7 +26,7 @@ const HOTKEY_FUNC = [
"entry_lightweight_mode",
];
export const HotkeyViewer = forwardRef<DialogRef>((props, ref) => {
export const HotkeyViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
@@ -117,4 +117,4 @@ export const HotkeyViewer = forwardRef<DialogRef>((props, ref) => {
))}
</BaseDialog>
);
});
};

View File

@@ -12,10 +12,10 @@ import { convertFileSrc } from "@tauri-apps/api/core";
import { join } from "@tauri-apps/api/path";
import { open as openDialog } from "@tauri-apps/plugin-dialog";
import { exists } from "@tauri-apps/plugin-fs";
import { forwardRef, useEffect, useImperativeHandle, useState } from "react";
import { useEffect, useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { useVerge } from "@/hooks/use-verge";
import { copyIconFile, getAppDir } from "@/services/cmds";
@@ -38,7 +38,7 @@ const getIcons = async (icon_dir: string, name: string) => {
};
};
export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
export const LayoutViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const { verge, patchVerge, mutateVerge } = useVerge();
@@ -387,7 +387,7 @@ export const LayoutViewer = forwardRef<DialogRef>((props, ref) => {
</List>
</BaseDialog>
);
});
};
const Item = styled(ListItem)(() => ({
padding: "5px 2px",

View File

@@ -7,16 +7,16 @@ import {
InputAdornment,
} from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { useVerge } from "@/hooks/use-verge";
import { entry_lightweight_mode } from "@/services/cmds";
import { showNotice } from "@/services/noticeService";
export const LiteModeViewer = forwardRef<DialogRef>((props, ref) => {
export const LiteModeViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const { verge, patchVerge } = useVerge();
@@ -143,4 +143,4 @@ export const LiteModeViewer = forwardRef<DialogRef>((props, ref) => {
</List>
</BaseDialog>
);
});
};

View File

@@ -8,15 +8,15 @@ import {
TextField,
} from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { useVerge } from "@/hooks/use-verge";
import { showNotice } from "@/services/noticeService";
export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
export const MiscViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const { verge, patchVerge } = useVerge();
@@ -319,4 +319,4 @@ export const MiscViewer = forwardRef<DialogRef>((props, ref) => {
</List>
</BaseDialog>
);
});
};

View File

@@ -1,15 +1,15 @@
import { ContentCopyRounded } from "@mui/icons-material";
import { alpha, Box, Button, IconButton } from "@mui/material";
import { writeText } from "@tauri-apps/plugin-clipboard-manager";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import useSWR from "swr";
import { BaseDialog, DialogRef } from "@/components/base";
import { BaseDialog } from "@/components/base";
import { getNetworkInterfacesInfo } from "@/services/cmds";
import { showNotice } from "@/services/noticeService";
export const NetworkInterfaceViewer = forwardRef<DialogRef>((props, ref) => {
export const NetworkInterfaceViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const [isV4, setIsV4] = useState(true);
@@ -99,7 +99,7 @@ export const NetworkInterfaceViewer = forwardRef<DialogRef>((props, ref) => {
))}
</BaseDialog>
);
});
};
const AddressDisplay = (props: { label: string; content: string }) => {
const { t } = useTranslation();

View File

@@ -11,25 +11,19 @@ import {
Typography,
} from "@mui/material";
import { useLockFn } from "ahooks";
import {
forwardRef,
useEffect,
useImperativeHandle,
useMemo,
useState,
} from "react";
import { useEffect, useImperativeHandle, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import useSWR, { mutate } from "swr";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { BaseFieldset } from "@/components/base/base-fieldset";
import { TooltipIcon } from "@/components/base/base-tooltip-icon";
import { EditorViewer } from "@/components/profile/editor-viewer";
import { useVerge } from "@/hooks/use-verge";
import { useAppData } from "@/providers/app-data-provider";
import { getClashConfig } from "@/services/cmds";
import {
getAutotemProxy,
getClashConfig,
getNetworkInterfacesInfo,
getSystemHostname,
getSystemProxy,
@@ -75,7 +69,7 @@ const getValidReg = (isWindows: boolean) => {
return new RegExp(rValid);
};
export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
export const SysproxyViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const isWindows = getSystem() === "windows";
const validReg = useMemo(() => getValidReg(isWindows), [isWindows]);
@@ -619,7 +613,7 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
</List>
</BaseDialog>
);
});
};
const FlexBox = styled("div")`
display: flex;

View File

@@ -9,16 +9,16 @@ import {
useTheme,
} from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef } from "@/components/base";
import { BaseDialog } from "@/components/base";
import { EditorViewer } from "@/components/profile/editor-viewer";
import { useVerge } from "@/hooks/use-verge";
import { defaultTheme, defaultDarkTheme } from "@/pages/_theme";
import { showNotice } from "@/services/noticeService";
export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
export const ThemeViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
@@ -144,7 +144,7 @@ export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
</List>
</BaseDialog>
);
});
};
const Item = styled(ListItem)(() => ({
padding: "5px 2px",

View File

@@ -8,10 +8,10 @@ import {
TextField,
} from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, DialogRef, Switch } from "@/components/base";
import { BaseDialog, Switch } from "@/components/base";
import { useClash } from "@/hooks/use-clash";
import { enhanceProfiles } from "@/services/cmds";
import { showNotice } from "@/services/noticeService";
@@ -21,7 +21,7 @@ import { StackModeSwitch } from "./stack-mode-switch";
const OS = getSystem();
export const TunViewer = forwardRef<DialogRef>((props, ref) => {
export const TunViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const { clash, mutateClash, patchClash } = useClash();
@@ -238,4 +238,4 @@ export const TunViewer = forwardRef<DialogRef>((props, ref) => {
</List>
</BaseDialog>
);
});
};

View File

@@ -4,24 +4,18 @@ import { relaunch } from "@tauri-apps/plugin-process";
import { open as openUrl } from "@tauri-apps/plugin-shell";
import { check as checkUpdate } from "@tauri-apps/plugin-updater";
import { useLockFn } from "ahooks";
import {
forwardRef,
useImperativeHandle,
useState,
useMemo,
useEffect,
} from "react";
import { useImperativeHandle, useState, useMemo, useEffect } from "react";
import { useTranslation } from "react-i18next";
import ReactMarkdown from "react-markdown";
import useSWR from "swr";
import { BaseDialog, DialogRef } from "@/components/base";
import { BaseDialog } from "@/components/base";
import { useListen } from "@/hooks/use-listen";
import { portableFlag } from "@/pages/_layout";
import { showNotice } from "@/services/noticeService";
import { useUpdateState, useSetUpdateState } from "@/services/states";
export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
export const UpdateViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
@@ -167,4 +161,4 @@ export const UpdateViewer = forwardRef<DialogRef>((props, ref) => {
)}
</BaseDialog>
);
});
};

View File

@@ -1,9 +1,9 @@
import { Button, Box, Typography } from "@mui/material";
import { useLockFn } from "ahooks";
import { forwardRef, useImperativeHandle, useState } from "react";
import { useImperativeHandle, useState } from "react";
import { useTranslation } from "react-i18next";
import { BaseDialog, BaseEmpty, DialogRef } from "@/components/base";
import { BaseDialog, BaseEmpty } from "@/components/base";
import { useClashInfo } from "@/hooks/use-clash";
import { useVerge } from "@/hooks/use-verge";
import { openWebUrl } from "@/services/cmds";
@@ -11,7 +11,7 @@ import { showNotice } from "@/services/noticeService";
import { WebUIItem } from "./web-ui-item";
export const WebUIViewer = forwardRef<DialogRef>((props, ref) => {
export const WebUIViewer = ({ ref, ...props }) => {
const { t } = useTranslation();
const { clashInfo } = useClashInfo();
@@ -139,4 +139,4 @@ export const WebUIViewer = forwardRef<DialogRef>((props, ref) => {
)}
</BaseDialog>
);
});
};