Parcourir la source

feat: Support Startup Script

MystiPanda il y a 1 an
Parent
commit
a8b11abec8

+ 1 - 1
src-tauri/Cargo.toml

@@ -39,7 +39,7 @@ tokio = { version = "1", features = ["full"] }
 serde = { version = "1.0", features = ["derive"] }
 reqwest = { version = "0.11", features = ["json", "rustls-tls"] }
 sysproxy = { git="https://github.com/clash-verge-rev/sysproxy-rs", branch = "main" }
-tauri = { version = "1.5", features = [ "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] }
+tauri = { version = "1.5", features = [ "dialog-open", "notification-all", "icon-png", "clipboard-all", "global-shortcut-all", "process-all", "shell-all", "system-tray", "updater", "window-all"] }
 
 [target.'cfg(windows)'.dependencies]
 runas = "=1.0.0" # 高版本会返回错误 Status

+ 4 - 0
src-tauri/src/config/verge.rs

@@ -25,6 +25,9 @@ pub struct IVerge {
     /// copy env type
     pub env_type: Option<String>,
 
+    /// startup script path
+    pub startup_script: Option<String>,
+
     /// enable traffic graph default is true
     pub traffic_graph: Option<bool>,
 
@@ -189,6 +192,7 @@ impl IVerge {
         patch!(theme_mode);
         patch!(tray_event);
         patch!(env_type);
+        patch!(startup_script);
         patch!(traffic_graph);
         patch!(enable_memory_usage);
 

+ 43 - 0
src-tauri/src/utils/init.rs

@@ -8,7 +8,9 @@ use log4rs::append::file::FileAppender;
 use log4rs::config::{Appender, Logger, Root};
 use log4rs::encode::pattern::PatternEncoder;
 use std::fs::{self, DirEntry};
+use std::path::PathBuf;
 use std::str::FromStr;
+use tauri::api::process::Command;
 
 /// initialize this instance's log file
 fn init_log() -> Result<()> {
@@ -340,3 +342,44 @@ pub fn init_scheme() -> Result<()> {
 pub fn init_scheme() -> Result<()> {
     Ok(())
 }
+
+pub fn startup_script() -> Result<()> {
+    let path = {
+        let verge = Config::verge();
+        let verge = verge.latest();
+        verge.startup_script.clone().unwrap_or("".to_string())
+    };
+
+    if !path.is_empty() {
+        let mut shell = "";
+        if path.ends_with(".sh") {
+            shell = "bash";
+        }
+        if path.ends_with(".ps1") {
+            shell = "powershell";
+        }
+        if path.ends_with(".bat") {
+            shell = "cmd";
+        }
+        if shell.is_empty() {
+            return Err(anyhow::anyhow!("unsupported script: {path}"));
+        }
+        let current_dir = PathBuf::from(path.clone());
+        if !current_dir.exists() {
+            return Err(anyhow::anyhow!("script not found: {path}"));
+        }
+        let current_dir = current_dir.parent();
+        match current_dir {
+            Some(dir) => {
+                let _ = Command::new(shell)
+                    .current_dir(dir.to_path_buf())
+                    .args(&[path])
+                    .output()?;
+            }
+            None => {
+                let _ = Command::new(shell).args(&[path]).output()?;
+            }
+        }
+    }
+    Ok(())
+}

+ 1 - 1
src-tauri/src/utils/resolve.rs

@@ -44,7 +44,7 @@ pub fn resolve_setup(app: &mut App) {
     #[cfg(target_os = "windows")]
     log_err!(init::init_service());
     log_err!(init::init_scheme());
-
+    log_err!(init::startup_script());
     // 处理随机端口
     let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false);
 

+ 4 - 0
src-tauri/tauri.conf.json

@@ -54,6 +54,10 @@
       },
       "notification": {
         "all": true
+      },
+      "dialog": {
+        "all": false,
+        "open": true
       }
     },
     "windows": [],

+ 59 - 3
src/components/setting/setting-verge.tsx

@@ -1,7 +1,15 @@
 import { useRef } from "react";
 import { useLockFn } from "ahooks";
 import { useTranslation } from "react-i18next";
-import { IconButton, MenuItem, Select, Typography } from "@mui/material";
+import { open } from "@tauri-apps/api/dialog";
+import {
+  Button,
+  IconButton,
+  MenuItem,
+  Select,
+  Input,
+  Typography,
+} from "@mui/material";
 import { openAppDir, openCoreDir, openLogsDir } from "@/services/cmds";
 import { ArrowForward } from "@mui/icons-material";
 import { checkUpdate } from "@tauri-apps/api/updater";
@@ -30,7 +38,8 @@ const SettingVerge = ({ onError }: Props) => {
   const { t } = useTranslation();
 
   const { verge, patchVerge, mutateVerge } = useVerge();
-  const { theme_mode, language, tray_event, env_type } = verge ?? {};
+  const { theme_mode, language, tray_event, env_type, startup_script } =
+    verge ?? {};
   const configRef = useRef<DialogRef>(null);
   const hotkeyRef = useRef<DialogRef>(null);
   const miscRef = useRef<DialogRef>(null);
@@ -125,7 +134,54 @@ const SettingVerge = ({ onError }: Props) => {
           </Select>
         </GuardState>
       </SettingItem>
-
+      <SettingItem label={t("Startup Script")}>
+        <GuardState
+          value={startup_script ?? ""}
+          onCatch={onError}
+          onFormat={(e: any) => e.target.value}
+          onChange={(e) => onChangeData({ startup_script: e })}
+          onGuard={(e) => patchVerge({ startup_script: e })}
+        >
+          <Input
+            value={startup_script}
+            disabled
+            endAdornment={
+              <>
+                <Button
+                  onClick={async () => {
+                    const path = await open({
+                      directory: false,
+                      multiple: false,
+                      filters: [
+                        {
+                          name: "Shell Script",
+                          extensions: ["sh", "bat", "ps1"],
+                        },
+                      ],
+                    });
+                    if (path?.length) {
+                      onChangeData({ startup_script: `${path}` });
+                      patchVerge({ startup_script: `${path}` });
+                    }
+                  }}
+                >
+                  {t("Browse")}
+                </Button>
+                {startup_script && (
+                  <Button
+                    onClick={async () => {
+                      onChangeData({ startup_script: "" });
+                      patchVerge({ startup_script: "" });
+                    }}
+                  >
+                    {t("Clear")}
+                  </Button>
+                )}
+              </>
+            }
+          ></Input>
+        </GuardState>
+      </SettingItem>
       <SettingItem label={t("Theme Setting")}>
         <IconButton
           color="inherit"

+ 2 - 0
src/locales/en.json

@@ -99,6 +99,8 @@
   "Theme Mode": "Theme Mode",
   "Tray Click Event": "Tray Click Event",
   "Copy Env Type": "Copy Env Type",
+  "Startup Script": "Startup Script",
+  "Browse": "Browse",
   "Show Main Window": "Show Main Window",
   "Theme Setting": "Theme Setting",
   "Layout Setting": "Layout Setting",

+ 2 - 0
src/locales/ru.json

@@ -90,6 +90,8 @@
   "Theme Mode": "Режим темы",
   "Tray Click Event": "Событие щелчка в лотке",
   "Copy Env Type": "Скопировать тип Env",
+  "Startup Script": "Скрипт запуска",
+  "Browse": "Просмотреть",
   "Show Main Window": "Показать главное окно",
   "Theme Setting": "Настройка темы",
   "Hotkey Setting": "Настройка клавиатурных сокращений",

+ 2 - 0
src/locales/zh.json

@@ -99,6 +99,8 @@
   "Theme Mode": "主题模式",
   "Tray Click Event": "托盘点击事件",
   "Copy Env Type": "复制环境变量类型",
+  "Startup Script": "启动脚本",
+  "Browse": "浏览",
   "Show Main Window": "显示主窗口",
   "Theme Setting": "主题设置",
   "Layout Setting": "界面设置",

+ 1 - 0
src/services/types.d.ts

@@ -167,6 +167,7 @@ interface IVergeConfig {
   language?: string;
   tray_event?: "main_window" | "system_proxy" | "tun_mode" | string;
   env_type?: "bash" | "cmd" | "powershell" | string;
+  startup_script?: string;
   clash_core?: string;
   theme_mode?: "light" | "dark" | "system";
   traffic_graph?: boolean;