Bladeren bron

feat: get network interface

MystiPanda 11 maanden geleden
bovenliggende
commit
1bd51be99c

+ 11 - 0
src-tauri/src/cmds.rs

@@ -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") {

+ 1 - 0
src-tauri/src/main.rs

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

+ 17 - 6
src/components/profile/groups-editor-viewer.tsx

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

+ 71 - 57
src/components/profile/profile-item.tsx

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

+ 21 - 19
src/components/profile/profile-more.tsx

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

+ 2 - 1
src/components/setting/mods/config-viewer.tsx

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

+ 16 - 14
src/components/setting/mods/sysproxy-viewer.tsx

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

+ 15 - 13
src/components/setting/mods/theme-viewer.tsx

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

+ 4 - 0
src/services/cmds.ts

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