mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
@@ -8,9 +8,9 @@ use tauri::{
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "verge-dev"))]
|
||||
static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev";
|
||||
pub static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev";
|
||||
#[cfg(feature = "verge-dev")]
|
||||
static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev.dev";
|
||||
pub static APP_ID: &str = "io.github.clash-verge-rev.clash-verge-rev.dev";
|
||||
|
||||
pub static PORTABLE_FLAG: OnceCell<bool> = OnceCell::new();
|
||||
|
||||
|
||||
@@ -300,3 +300,34 @@ pub fn init_service() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// initialize url scheme
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn init_scheme() -> Result<()> {
|
||||
use tauri::utils::platform::current_exe;
|
||||
use winreg::enums::*;
|
||||
use winreg::RegKey;
|
||||
|
||||
let app_exe = current_exe()?;
|
||||
let app_exe = dunce::canonicalize(app_exe)?;
|
||||
let app_exe = app_exe.to_string_lossy().to_owned();
|
||||
|
||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||
let (clash, _) = hkcu.create_subkey("Software\\Classes\\Clash")?;
|
||||
clash.set_value("", &"Clash Verge")?;
|
||||
clash.set_value("URL Protocol", &"Clash Verge URL Scheme Protocol")?;
|
||||
let (default_icon, _) = hkcu.create_subkey("Software\\Classes\\Clash\\DefaultIcon")?;
|
||||
default_icon.set_value("", &format!("{app_exe}"))?;
|
||||
let (command, _) = hkcu.create_subkey("Software\\Classes\\Clash\\Shell\\Open\\Command")?;
|
||||
command.set_value("", &format!("{app_exe} \"%1\""))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn init_scheme() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn init_scheme() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
use crate::config::IVerge;
|
||||
use crate::{config::Config, core::*, utils::init, utils::server};
|
||||
use crate::config::{IVerge, PrfOption};
|
||||
use crate::{
|
||||
config::{Config, PrfItem},
|
||||
core::*,
|
||||
utils::init,
|
||||
utils::server,
|
||||
};
|
||||
use crate::{log_err, trace_err};
|
||||
use anyhow::Result;
|
||||
use once_cell::sync::OnceCell;
|
||||
use serde_yaml::Mapping;
|
||||
use std::net::TcpListener;
|
||||
use tauri::api::notification;
|
||||
use tauri::{App, AppHandle, Manager};
|
||||
|
||||
pub static VERSION: OnceCell<String> = OnceCell::new();
|
||||
@@ -37,6 +43,8 @@ pub fn resolve_setup(app: &mut App) {
|
||||
log_err!(init::init_resources());
|
||||
#[cfg(target_os = "windows")]
|
||||
log_err!(init::init_service());
|
||||
log_err!(init::init_scheme());
|
||||
|
||||
// 处理随机端口
|
||||
let enable_random_port = Config::verge().latest().enable_random_port.unwrap_or(false);
|
||||
|
||||
@@ -89,6 +97,13 @@ pub 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<String> = std::env::args().collect();
|
||||
if argvs.len() > 1 {
|
||||
tauri::async_runtime::block_on(async {
|
||||
resolve_scheme(argvs[1].to_owned()).await;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// reset system proxy
|
||||
@@ -223,3 +238,29 @@ pub fn save_window_size_position(app_handle: &AppHandle, save_to_file: bool) ->
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn resolve_scheme(param: String) {
|
||||
let url = param.trim_start_matches("clash://install-config/?url=");
|
||||
let option = PrfOption {
|
||||
user_agent: None,
|
||||
with_proxy: Some(true),
|
||||
self_proxy: None,
|
||||
update_interval: None,
|
||||
};
|
||||
if let Ok(item) = PrfItem::from_url(&url, None, None, Some(option)).await {
|
||||
if let Ok(_) = Config::profiles().data().append_item(item) {
|
||||
notification::Notification::new(crate::utils::dirs::APP_ID)
|
||||
.title("Clash Verge")
|
||||
.body("Import profile success")
|
||||
.show()
|
||||
.unwrap();
|
||||
};
|
||||
} else {
|
||||
notification::Notification::new(crate::utils::dirs::APP_ID)
|
||||
.title("Clash Verge")
|
||||
.body("Import profile failed")
|
||||
.show()
|
||||
.unwrap();
|
||||
log::error!("failed to parse url: {}", url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,19 +4,42 @@ use super::resolve;
|
||||
use crate::config::IVerge;
|
||||
use anyhow::{bail, Result};
|
||||
use port_scanner::local_port_available;
|
||||
use std::convert::Infallible;
|
||||
use tauri::AppHandle;
|
||||
use warp::Filter;
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
struct QueryParam {
|
||||
param: String,
|
||||
}
|
||||
|
||||
/// check whether there is already exists
|
||||
pub fn check_singleton() -> Result<()> {
|
||||
let port = IVerge::get_singleton_port();
|
||||
|
||||
if !local_port_available(port) {
|
||||
tauri::async_runtime::block_on(async {
|
||||
let url = format!("http://127.0.0.1:{port}/commands/visible");
|
||||
let resp = reqwest::get(url).await?.text().await?;
|
||||
let resp = reqwest::get(format!("http://127.0.0.1:{port}/commands/ping"))
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
|
||||
if &resp == "ok" {
|
||||
let argvs: Vec<String> = std::env::args().collect();
|
||||
if argvs.len() > 1 {
|
||||
let param = argvs[1].as_str();
|
||||
reqwest::get(format!(
|
||||
"http://127.0.0.1:{port}/commands/scheme?param={param}"
|
||||
))
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
} else {
|
||||
reqwest::get(format!("http://127.0.0.1:{port}/commands/visible"))
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
}
|
||||
bail!("app exists");
|
||||
}
|
||||
|
||||
@@ -34,11 +57,22 @@ pub fn embed_server(app_handle: AppHandle) {
|
||||
let port = IVerge::get_singleton_port();
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let commands = warp::path!("commands" / "visible").map(move || {
|
||||
let ping = warp::path!("commands" / "ping").map(move || "ok");
|
||||
|
||||
let visible = warp::path!("commands" / "visible").map(move || {
|
||||
resolve::create_window(&app_handle);
|
||||
format!("ok")
|
||||
"ok"
|
||||
});
|
||||
|
||||
warp::serve(commands).bind(([127, 0, 0, 1], port)).await;
|
||||
let scheme = warp::path!("commands" / "scheme")
|
||||
.and(warp::query::<QueryParam>())
|
||||
.and_then(scheme_handler);
|
||||
|
||||
async fn scheme_handler(query: QueryParam) -> Result<impl warp::Reply, Infallible> {
|
||||
resolve::resolve_scheme(query.param).await;
|
||||
Ok("ok")
|
||||
}
|
||||
let commands = ping.or(visible).or(scheme);
|
||||
warp::serve(commands).run(([127, 0, 0, 1], port)).await;
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user