diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock
index 33d3ecc..bfcc5e9 100644
--- a/src-tauri/Cargo.lock
+++ b/src-tauri/Cargo.lock
@@ -933,6 +933,7 @@ dependencies = [
"tauri",
"tauri-build",
"tauri-plugin-clipboard-manager",
+ "tauri-plugin-deep-link",
"tauri-plugin-devtools",
"tauri-plugin-dialog",
"tauri-plugin-fs",
@@ -942,6 +943,7 @@ dependencies = [
"tauri-plugin-shell",
"tauri-plugin-updater",
"tokio",
+ "url",
"users",
"warp",
"window-shadows",
@@ -1062,6 +1064,26 @@ dependencies = [
"crossbeam-utils",
]
+[[package]]
+name = "const-random"
+version = "0.1.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
+dependencies = [
+ "const-random-macro",
+]
+
+[[package]]
+name = "const-random-macro"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
+dependencies = [
+ "getrandom 0.2.15",
+ "once_cell",
+ "tiny-keccak",
+]
+
[[package]]
name = "convert_case"
version = "0.4.0"
@@ -1565,6 +1587,15 @@ dependencies = [
"syn 2.0.77",
]
+[[package]]
+name = "dlv-list"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
+dependencies = [
+ "const-random",
+]
+
[[package]]
name = "dpi"
version = "0.1.1"
@@ -2627,7 +2658,7 @@ dependencies = [
"httpdate",
"itoa 1.0.11",
"pin-project-lite",
- "socket2 0.5.7",
+ "socket2 0.4.10",
"tokio",
"tower-service",
"tracing",
@@ -4018,6 +4049,16 @@ dependencies = [
"num-traits",
]
+[[package]]
+name = "ordered-multimap"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
+dependencies = [
+ "dlv-list",
+ "hashbrown 0.14.5",
+]
+
[[package]]
name = "ordered-stream"
version = "0.2.0"
@@ -4944,6 +4985,17 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "rust-ini"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f"
+dependencies = [
+ "cfg-if",
+ "ordered-multimap",
+ "trim-in-place",
+]
+
[[package]]
name = "rustc-demangle"
version = "0.1.24"
@@ -5984,7 +6036,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-clipboard-manager"
version = "2.0.0-rc.3"
-source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#9291e4d2caa31c883c71e55f2193bd8754d72f03"
+source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#984110a978774712bad4d746ed06134d54debcd0"
dependencies = [
"arboard",
"image 0.24.9",
@@ -5996,6 +6048,25 @@ dependencies = [
"thiserror",
]
+[[package]]
+name = "tauri-plugin-deep-link"
+version = "2.0.0-rc.4"
+source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#984110a978774712bad4d746ed06134d54debcd0"
+dependencies = [
+ "dunce",
+ "log",
+ "rust-ini",
+ "serde",
+ "serde_json",
+ "tauri",
+ "tauri-plugin",
+ "tauri-utils",
+ "thiserror",
+ "url",
+ "windows-registry",
+ "windows-result 0.2.0",
+]
+
[[package]]
name = "tauri-plugin-devtools"
version = "2.0.0-rc.1"
@@ -6026,7 +6097,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-dialog"
version = "2.0.0-rc.5"
-source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#9291e4d2caa31c883c71e55f2193bd8754d72f03"
+source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#984110a978774712bad4d746ed06134d54debcd0"
dependencies = [
"log",
"raw-window-handle 0.6.2",
@@ -6043,7 +6114,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-fs"
version = "2.0.0-rc.3"
-source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#9291e4d2caa31c883c71e55f2193bd8754d72f03"
+source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#984110a978774712bad4d746ed06134d54debcd0"
dependencies = [
"anyhow",
"dunce",
@@ -6078,7 +6149,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-notification"
version = "2.0.0-rc.4"
-source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#9291e4d2caa31c883c71e55f2193bd8754d72f03"
+source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#984110a978774712bad4d746ed06134d54debcd0"
dependencies = [
"log",
"notify-rust",
@@ -6096,7 +6167,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-process"
version = "2.0.0-rc.1"
-source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#9291e4d2caa31c883c71e55f2193bd8754d72f03"
+source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#984110a978774712bad4d746ed06134d54debcd0"
dependencies = [
"tauri",
"tauri-plugin",
@@ -6105,7 +6176,7 @@ dependencies = [
[[package]]
name = "tauri-plugin-shell"
version = "2.0.0-rc.3"
-source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#9291e4d2caa31c883c71e55f2193bd8754d72f03"
+source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v2#984110a978774712bad4d746ed06134d54debcd0"
dependencies = [
"encoding_rs",
"log",
@@ -6426,6 +6497,15 @@ dependencies = [
"time-core",
]
+[[package]]
+name = "tiny-keccak"
+version = "2.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
+dependencies = [
+ "crunchy",
+]
+
[[package]]
name = "tinystr"
version = "0.7.6"
@@ -6800,6 +6880,12 @@ dependencies = [
"windows-sys 0.59.0",
]
+[[package]]
+name = "trim-in-place"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc"
+
[[package]]
name = "try-lock"
version = "0.2.5"
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
old mode 100644
new mode 100755
index 73193ba..02d544d
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -51,12 +51,15 @@ tauri-plugin-fs = { git = "https://github.com/tauri-apps/plugins-workspace", bra
tauri-plugin-notification = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-process = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-clipboard-manager = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
+tauri-plugin-deep-link = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
tauri-plugin-devtools = "2.0.0-rc"
-
+url = "2.5.2"
[target.'cfg(windows)'.dependencies]
runas = "=1.2.0"
deelevate = "0.2.0"
winreg = "0.52.0"
+url = "2.5.2"
+
[target.'cfg(target_os = "linux")'.dependencies]
users = "0.11.0"
diff --git a/src-tauri/Info.plist b/src-tauri/Info.plist
deleted file mode 100644
index 954d43a..0000000
--- a/src-tauri/Info.plist
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-CFBundleURLTypes
-
-
- CFBundleURLName
- Clash Verge
- CFBundleURLSchemes
-
- clash
-
-
-
-
-
\ No newline at end of file
diff --git a/src-tauri/capabilities/desktop.json b/src-tauri/capabilities/desktop.json
old mode 100644
new mode 100755
index c4936c0..fbb332b
--- a/src-tauri/capabilities/desktop.json
+++ b/src-tauri/capabilities/desktop.json
@@ -3,5 +3,9 @@
"platforms": ["macOS", "windows", "linux"],
"webviews": ["main"],
"windows": ["main"],
- "permissions": ["global-shortcut:default", "updater:default"]
+ "permissions": [
+ "global-shortcut:default",
+ "updater:default",
+ "deep-link:default"
+ ]
}
diff --git a/src-tauri/src/cmds.rs b/src-tauri/src/cmds.rs
index a560fd8..69711c9 100644
--- a/src-tauri/src/cmds.rs
+++ b/src-tauri/src/cmds.rs
@@ -32,8 +32,12 @@ pub async fn enhance_profiles() -> CmdResult {
}
#[tauri::command]
-pub async fn import_profile(url: String, option: Option) -> CmdResult {
- let item = wrap_err!(PrfItem::from_url(&url, None, None, option).await)?;
+pub async fn import_profile(
+ url: String,
+ name: Option,
+ option: Option,
+) -> CmdResult {
+ let item = wrap_err!(PrfItem::from_url(&url, name, None, option).await)?;
wrap_err!(Config::profiles().data().append_item(item))
}
diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs
old mode 100644
new mode 100755
index fe0fb9c..ca5cb10
--- a/src-tauri/src/main.rs
+++ b/src-tauri/src/main.rs
@@ -10,7 +10,8 @@ mod enhance;
mod feat;
mod utils;
-use crate::utils::{resolve, server};
+use crate::utils::{resolve, resolve::resolve_scheme, server};
+use tauri::Listener;
fn main() -> std::io::Result<()> {
// 单例检测
@@ -42,10 +43,25 @@ fn main() -> std::io::Result<()> {
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_shell::init())
+ .plugin(tauri_plugin_deep_link::init())
.setup(|app| {
+ #[cfg(target_os = "linux")]
+ {
+ use tauri_plugin_deep_link::DeepLinkExt;
+ app.deep_link().register_all()?;
+ }
+
+ app.listen("deep-link://new-url", |event| {
+ tauri::async_runtime::spawn(async move {
+ let payload = event.payload();
+ log_err!(resolve_scheme(payload.to_string()).await);
+ });
+ });
+
tauri::async_runtime::block_on(async move {
resolve::resolve_setup(app).await;
});
+
Ok(())
})
.invoke_handler(tauri::generate_handler![
diff --git a/src-tauri/src/utils/resolve.rs b/src-tauri/src/utils/resolve.rs
index 5408144..a20379c 100644
--- a/src-tauri/src/utils/resolve.rs
+++ b/src-tauri/src/utils/resolve.rs
@@ -2,12 +2,15 @@ use crate::cmds::import_profile;
use crate::config::IVerge;
use crate::utils::error;
use crate::{config::Config, core::*, utils::init, utils::server};
-use crate::{log_err, trace_err};
-use anyhow::Result;
+use crate::{error as er, log_err, trace_err};
+use anyhow::{bail, Result};
use once_cell::sync::OnceCell;
+use percent_encoding::percent_decode_str;
use serde_yaml::Mapping;
use std::net::TcpListener;
use tauri::{App, AppHandle, Manager};
+
+use url::Url;
//#[cfg(not(target_os = "linux"))]
// use window_shadows::set_shadow;
use tauri_plugin_notification::NotificationExt;
@@ -96,14 +99,6 @@ pub async fn resolve_setup(app: &mut App) {
log_err!(handle::Handle::update_systray_part());
log_err!(hotkey::Hotkey::global().init(app.app_handle()));
log_err!(timer::Timer::global().init());
-
- let argvs: Vec = std::env::args().collect();
- if argvs.len() > 1 {
- let param = argvs[1].as_str();
- if param.starts_with("clash:") {
- log_err!(resolve_scheme(argvs[1].to_owned()).await);
- }
- }
}
/// reset system proxy
@@ -240,34 +235,67 @@ pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) ->
}
pub async fn resolve_scheme(param: String) -> Result<()> {
- let url = param
- .trim_start_matches("clash://install-config/?url=")
- .trim_start_matches("clash://install-config?url=");
+ log::info!("received deep link: {}", param);
+ let param_str = if param.starts_with("[") && param.len() > 4 {
+ param
+ .get(2..param.len() - 2)
+ .ok_or_else(|| anyhow::anyhow!("Invalid string slice boundaries"))?
+ } else {
+ bail!("invalid deep link param: {:?}", param)
+ };
- let handle = handle::Handle::global();
- let app_handle = handle.app_handle.lock().clone();
- if let Some(app_handle) = app_handle.as_ref() {
- match import_profile(url.to_string(), None).await {
- Ok(_) => {
- app_handle
- .notification()
- .builder()
- .title("Clash Verge")
- .body("Import profile success")
- .show()
- .unwrap();
- }
- Err(e) => {
- app_handle
- .notification()
- .builder()
- .title("Clash Verge")
- .body(format!("Import profile failed: {e}"))
- .show()
- .unwrap();
- log::error!("Import profile failed: {e}");
+ // 解析 URL
+ let link_parsed = match Url::parse(param_str) {
+ Ok(url) => url,
+ Err(e) => {
+ bail!("failed to parse deep link: {:?}, param: {:?}", e, param);
+ }
+ };
+
+ if link_parsed.scheme() == "clash" || link_parsed.scheme() == "clash-verge" {
+ let name = link_parsed
+ .query_pairs()
+ .find(|(key, _)| key == "name")
+ .map(|(_, value)| value.into_owned());
+
+ let encode_url = link_parsed
+ .query_pairs()
+ .find(|(key, _)| key == "url")
+ .map(|(_, value)| value.into_owned());
+
+ match encode_url {
+ Some(url) => {
+ let decoded_url = percent_decode_str(url.as_ref()).decode_utf8_lossy();
+ let handle = handle::Handle::global();
+ let app_handle = handle.app_handle.lock().clone();
+ if let Some(app_handle) = app_handle.as_ref() {
+ er!(format!("decode_url: {}", decoded_url));
+ match import_profile(decoded_url.to_string(), name.clone(), None).await {
+ Ok(_) => {
+ app_handle
+ .notification()
+ .builder()
+ .title("Clash Verge")
+ .body("Import profile success")
+ .show()
+ .unwrap();
+ }
+ Err(e) => {
+ app_handle
+ .notification()
+ .builder()
+ .title("Clash Verge")
+ .body(format!("Import profile failed: {e}"))
+ .show()
+ .unwrap();
+ bail!("Import profile failed: {e}");
+ }
+ }
+ }
}
+ None => bail!("failed to get profile url"),
}
}
+
Ok(())
}
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
old mode 100644
new mode 100755
index 0876ef1..7d1cc0e
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -34,6 +34,11 @@
"https://download.clashverge.dev/https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-proxy.json",
"https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update.json"
]
+ },
+ "deep-link": {
+ "desktop": {
+ "schemes": ["clash", "clash-verge"]
+ }
}
},
"app": {
diff --git a/src/services/cmds.ts b/src/services/cmds.ts
index 552da39..d757d60 100644
--- a/src/services/cmds.ts
+++ b/src/services/cmds.ts
@@ -63,6 +63,7 @@ export async function saveProfileFile(index: string, fileData: string) {
export async function importProfile(url: string) {
return invoke("import_profile", {
url,
+ name: null,
option: { with_proxy: true },
});
}