mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2024-11-16 03:32:36 +08:00
feat: get network interface
This commit is contained in:
parent
ee56080af0
commit
1bd51be99c
|
@ -322,6 +322,17 @@ pub fn copy_icon_file(path: String, name: String) -> CmdResult<String> {
|
|||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_network_interfaces() -> Vec<String> {
|
||||
use sysinfo::Networks;
|
||||
let mut result = Vec::new();
|
||||
let networks = Networks::new_with_refreshed_list();
|
||||
for (interface_name, _) in &networks {
|
||||
result.push(interface_name.clone());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn open_devtools(app_handle: tauri::AppHandle) {
|
||||
if let Some(window) = app_handle.get_window("main") {
|
||||
|
|
|
@ -51,6 +51,7 @@ fn main() -> std::io::Result<()> {
|
|||
cmds::open_web_url,
|
||||
cmds::open_core_dir,
|
||||
cmds::get_portable_flag,
|
||||
cmds::get_network_interfaces,
|
||||
// cmds::kill_sidecar,
|
||||
cmds::restart_sidecar,
|
||||
// clash
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { ReactNode, useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useLockFn } from "ahooks";
|
||||
import yaml from "js-yaml";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
@ -30,7 +30,11 @@ import {
|
|||
styled,
|
||||
} from "@mui/material";
|
||||
import { GroupItem } from "@/components/profile/group-item";
|
||||
import { readProfileFile, saveProfileFile } from "@/services/cmds";
|
||||
import {
|
||||
getNetworkInterfaces,
|
||||
readProfileFile,
|
||||
saveProfileFile,
|
||||
} from "@/services/cmds";
|
||||
import { Notice, Switch } from "@/components/base";
|
||||
import getSystem from "@/utils/get-system";
|
||||
import { BaseSearchBox } from "../base/base-search-box";
|
||||
|
@ -60,7 +64,7 @@ export const GroupsEditorViewer = (props: Props) => {
|
|||
const [currData, setCurrData] = useState("");
|
||||
const [visualization, setVisualization] = useState(true);
|
||||
const [match, setMatch] = useState(() => (_: string) => true);
|
||||
|
||||
const [interfaceNameList, setInterfaceNameList] = useState<string[]>([]);
|
||||
const { control, watch, register, ...formIns } = useForm<IProxyGroupConfig>({
|
||||
defaultValues: {
|
||||
type: "select",
|
||||
|
@ -251,6 +255,10 @@ export const GroupsEditorViewer = (props: Props) => {
|
|||
setProxyProviderList(Object.keys(provider));
|
||||
setGroupList(originGroupsObj?.["proxy-groups"] || []);
|
||||
};
|
||||
const getInterfaceNameList = async () => {
|
||||
let list = await getNetworkInterfaces();
|
||||
setInterfaceNameList(list);
|
||||
};
|
||||
useEffect(() => {
|
||||
fetchProxyPolicy();
|
||||
}, [prependSeq, appendSeq, deleteSeq]);
|
||||
|
@ -259,6 +267,7 @@ export const GroupsEditorViewer = (props: Props) => {
|
|||
fetchContent();
|
||||
fetchProxyPolicy();
|
||||
fetchProfile();
|
||||
getInterfaceNameList();
|
||||
}, [open]);
|
||||
|
||||
const validateGroup = () => {
|
||||
|
@ -485,11 +494,13 @@ export const GroupsEditorViewer = (props: Props) => {
|
|||
render={({ field }) => (
|
||||
<Item>
|
||||
<ListItemText primary={t("Interface Name")} />
|
||||
<TextField
|
||||
autoComplete="new-password"
|
||||
<Autocomplete
|
||||
size="small"
|
||||
sx={{ width: "calc(100% - 150px)" }}
|
||||
{...field}
|
||||
options={interfaceNameList}
|
||||
value={field.value}
|
||||
onChange={(_, value) => value && field.onChange(value)}
|
||||
renderInput={(params) => <TextField {...params} />}
|
||||
/>
|
||||
</Item>
|
||||
)}
|
||||
|
|
|
@ -475,64 +475,78 @@ export const ProfileItem = (props: Props) => {
|
|||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
{fileOpen && (
|
||||
<EditorViewer
|
||||
open={true}
|
||||
initialData={readProfileFile(uid)}
|
||||
language="yaml"
|
||||
schema="clash"
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(uid, curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setFileOpen(false)}
|
||||
/>
|
||||
)}
|
||||
{rulesOpen && (
|
||||
<RulesEditorViewer
|
||||
groupsUid={option?.groups ?? ""}
|
||||
mergeUid={option?.merge ?? ""}
|
||||
profileUid={uid}
|
||||
property={option?.rules ?? ""}
|
||||
open={true}
|
||||
onSave={onSave}
|
||||
onClose={() => setRulesOpen(false)}
|
||||
/>
|
||||
)}
|
||||
{proxiesOpen && (
|
||||
<ProxiesEditorViewer
|
||||
profileUid={uid}
|
||||
property={option?.proxies ?? ""}
|
||||
open={true}
|
||||
onSave={onSave}
|
||||
onClose={() => setProxiesOpen(false)}
|
||||
/>
|
||||
)}
|
||||
{groupsOpen && (
|
||||
<GroupsEditorViewer
|
||||
mergeUid={option?.merge ?? ""}
|
||||
proxiesUid={option?.proxies ?? ""}
|
||||
profileUid={uid}
|
||||
property={option?.groups ?? ""}
|
||||
open={true}
|
||||
onSave={onSave}
|
||||
onClose={() => {
|
||||
setGroupsOpen(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{mergeOpen && (
|
||||
<EditorViewer
|
||||
open={true}
|
||||
initialData={readProfileFile(option?.merge ?? "")}
|
||||
language="yaml"
|
||||
schema="clash"
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(option?.merge ?? "", curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setMergeOpen(false)}
|
||||
/>
|
||||
)}
|
||||
{scriptOpen && (
|
||||
<EditorViewer
|
||||
open={true}
|
||||
initialData={readProfileFile(option?.script ?? "")}
|
||||
language="javascript"
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(option?.script ?? "", curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setScriptOpen(false)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<EditorViewer
|
||||
open={fileOpen}
|
||||
initialData={readProfileFile(uid)}
|
||||
language="yaml"
|
||||
schema="clash"
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(uid, curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setFileOpen(false)}
|
||||
/>
|
||||
<RulesEditorViewer
|
||||
groupsUid={option?.groups ?? ""}
|
||||
mergeUid={option?.merge ?? ""}
|
||||
profileUid={uid}
|
||||
property={option?.rules ?? ""}
|
||||
open={rulesOpen}
|
||||
onSave={onSave}
|
||||
onClose={() => setRulesOpen(false)}
|
||||
/>
|
||||
<ProxiesEditorViewer
|
||||
profileUid={uid}
|
||||
property={option?.proxies ?? ""}
|
||||
open={proxiesOpen}
|
||||
onSave={onSave}
|
||||
onClose={() => setProxiesOpen(false)}
|
||||
/>
|
||||
<GroupsEditorViewer
|
||||
mergeUid={option?.merge ?? ""}
|
||||
proxiesUid={option?.proxies ?? ""}
|
||||
profileUid={uid}
|
||||
property={option?.groups ?? ""}
|
||||
open={groupsOpen}
|
||||
onSave={onSave}
|
||||
onClose={() => setGroupsOpen(false)}
|
||||
/>
|
||||
<EditorViewer
|
||||
open={mergeOpen}
|
||||
initialData={readProfileFile(option?.merge ?? "")}
|
||||
language="yaml"
|
||||
schema="clash"
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(option?.merge ?? "", curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setMergeOpen(false)}
|
||||
/>
|
||||
<EditorViewer
|
||||
open={scriptOpen}
|
||||
initialData={readProfileFile(option?.script ?? "")}
|
||||
language="javascript"
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(option?.script ?? "", curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setScriptOpen(false)}
|
||||
/>
|
||||
<ConfirmViewer
|
||||
title={t("Confirm deletion")}
|
||||
message={t("This operation is not reversible")}
|
||||
|
|
|
@ -167,25 +167,27 @@ export const ProfileMore = (props: Props) => {
|
|||
</MenuItem>
|
||||
))}
|
||||
</Menu>
|
||||
|
||||
<EditorViewer
|
||||
open={fileOpen}
|
||||
title={`${t("Global " + id)}`}
|
||||
initialData={readProfileFile(id)}
|
||||
language={id === "Merge" ? "yaml" : "javascript"}
|
||||
schema={id === "Merge" ? "clash" : undefined}
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(id, curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setFileOpen(false)}
|
||||
/>
|
||||
|
||||
<LogViewer
|
||||
open={logOpen}
|
||||
logInfo={logInfo}
|
||||
onClose={() => setLogOpen(false)}
|
||||
/>
|
||||
{fileOpen && (
|
||||
<EditorViewer
|
||||
open={true}
|
||||
title={`${t("Global " + id)}`}
|
||||
initialData={readProfileFile(id)}
|
||||
language={id === "Merge" ? "yaml" : "javascript"}
|
||||
schema={id === "Merge" ? "clash" : undefined}
|
||||
onSave={async (prev, curr) => {
|
||||
await saveProfileFile(id, curr ?? "");
|
||||
onSave && onSave(prev, curr);
|
||||
}}
|
||||
onClose={() => setFileOpen(false)}
|
||||
/>
|
||||
)}
|
||||
{logOpen && (
|
||||
<LogViewer
|
||||
open={logOpen}
|
||||
logInfo={logInfo}
|
||||
onClose={() => setLogOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -20,9 +20,10 @@ export const ConfigViewer = forwardRef<DialogRef>((_, ref) => {
|
|||
close: () => setOpen(false),
|
||||
}));
|
||||
|
||||
if (!open) return null;
|
||||
return (
|
||||
<EditorViewer
|
||||
open={open}
|
||||
open={true}
|
||||
title={
|
||||
<Box>
|
||||
{t("Runtime Config")}
|
||||
|
|
|
@ -261,20 +261,22 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
>
|
||||
{t("Edit")} PAC
|
||||
</Button>
|
||||
<EditorViewer
|
||||
open={editorOpen}
|
||||
title={`${t("Edit")} PAC`}
|
||||
initialData={Promise.resolve(value.pac_content ?? "")}
|
||||
language="javascript"
|
||||
onSave={(_prev, curr) => {
|
||||
let pac = DEFAULT_PAC;
|
||||
if (curr && curr.trim().length > 0) {
|
||||
pac = curr;
|
||||
}
|
||||
setValue((v) => ({ ...v, pac_content: pac }));
|
||||
}}
|
||||
onClose={() => setEditorOpen(false)}
|
||||
/>
|
||||
{editorOpen && (
|
||||
<EditorViewer
|
||||
open={true}
|
||||
title={`${t("Edit")} PAC`}
|
||||
initialData={Promise.resolve(value.pac_content ?? "")}
|
||||
language="javascript"
|
||||
onSave={(_prev, curr) => {
|
||||
let pac = DEFAULT_PAC;
|
||||
if (curr && curr.trim().length > 0) {
|
||||
pac = curr;
|
||||
}
|
||||
setValue((v) => ({ ...v, pac_content: pac }));
|
||||
}}
|
||||
onClose={() => setEditorOpen(false)}
|
||||
/>
|
||||
)}
|
||||
</ListItem>
|
||||
</>
|
||||
)}
|
||||
|
|
|
@ -123,19 +123,21 @@ export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
>
|
||||
{t("Edit")} CSS
|
||||
</Button>
|
||||
<EditorViewer
|
||||
open={editorOpen}
|
||||
title={`${t("Edit")} CSS`}
|
||||
initialData={Promise.resolve(theme.css_injection ?? "")}
|
||||
language="css"
|
||||
onSave={(_prev, curr) => {
|
||||
theme.css_injection = curr;
|
||||
handleChange("css_injection");
|
||||
}}
|
||||
onClose={() => {
|
||||
setEditorOpen(false);
|
||||
}}
|
||||
/>
|
||||
{editorOpen && (
|
||||
<EditorViewer
|
||||
open={true}
|
||||
title={`${t("Edit")} CSS`}
|
||||
initialData={Promise.resolve(theme.css_injection ?? "")}
|
||||
language="css"
|
||||
onSave={(_prev, curr) => {
|
||||
theme.css_injection = curr;
|
||||
handleChange("css_injection");
|
||||
}}
|
||||
onClose={() => {
|
||||
setEditorOpen(false);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Item>
|
||||
</List>
|
||||
</BaseDialog>
|
||||
|
|
|
@ -233,3 +233,7 @@ export async function copyIconFile(
|
|||
export async function downloadIconCache(url: string, name: string) {
|
||||
return invoke<string>("download_icon_cache", { url, name });
|
||||
}
|
||||
|
||||
export async function getNetworkInterfaces() {
|
||||
return invoke<string[]>("get_network_interfaces");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user