From ecc272aa20f4edb2f5521dc29ed39cc327b4c8a5 Mon Sep 17 00:00:00 2001 From: Tunglies Date: Tue, 25 Nov 2025 16:58:25 +0800 Subject: [PATCH] feat: integrate tauri-plugin-clipboard-manager and add system info commands (#5593) --- Cargo.lock | 1 + Cargo.toml | 1 + .../Cargo.toml | 1 + .../src/commands.rs | 39 ++++++++++++++ .../src/lib.rs | 19 ++++++- src-tauri/Cargo.toml | 2 +- src-tauri/src/cmd/system.rs | 52 +------------------ src-tauri/src/config/config.rs | 14 +++-- src-tauri/src/core/service.rs | 10 +--- src-tauri/src/core/tray/mod.rs | 5 +- src-tauri/src/lib.rs | 8 +-- src/services/cmds.ts | 2 +- 12 files changed, 82 insertions(+), 72 deletions(-) create mode 100644 crates/tauri-plugin-clash-verge-sysinfo/src/commands.rs diff --git a/Cargo.lock b/Cargo.lock index f21aa35bd..efc878f58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7578,6 +7578,7 @@ dependencies = [ "parking_lot", "sysinfo", "tauri", + "tauri-plugin-clipboard-manager", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b46aaa0da..092a35f23 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,7 @@ clash-verge-types = { path = "crates/clash-verge-types" } tauri-plugin-clash-verge-sysinfo = { path = "crates/tauri-plugin-clash-verge-sysinfo" } tauri = { version = "2.9.3" } +tauri-plugin-clipboard-manager = "2.3.2" parking_lot = { version = "0.12.5", features = ["hardware-lock-elision"] } anyhow = "1.0.100" criterion = { version = "0.7.0", features = ["async_tokio"] } diff --git a/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml b/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml index 282e90776..0ab3031ef 100644 --- a/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml +++ b/crates/tauri-plugin-clash-verge-sysinfo/Cargo.toml @@ -6,6 +6,7 @@ rust-version.workspace = true [dependencies] tauri = { workspace = true } +tauri-plugin-clipboard-manager = { workspace = true } parking_lot = { workspace = true } sysinfo = { version = "0.37.2", features = ["network", "system"] } diff --git a/crates/tauri-plugin-clash-verge-sysinfo/src/commands.rs b/crates/tauri-plugin-clash-verge-sysinfo/src/commands.rs new file mode 100644 index 000000000..47e24a30c --- /dev/null +++ b/crates/tauri-plugin-clash-verge-sysinfo/src/commands.rs @@ -0,0 +1,39 @@ +use parking_lot::RwLock; +use tauri::{AppHandle, Runtime, State, command}; +use tauri_plugin_clipboard_manager::{ClipboardExt as _, Error}; + +use crate::Platform; + +// TODO 迁移,让新的结构体允许通过 tauri command 正确使用 structure.field 方式获取信息 +#[command] +pub fn get_system_info(state: State<'_, RwLock>) -> Result { + Ok(state.inner().read().to_string()) +} + +/// 获取应用的运行时间(毫秒) +#[command] +pub fn get_app_uptime(state: State<'_, RwLock>) -> Result { + Ok(state + .inner() + .read() + .appinfo + .app_startup_time + .elapsed() + .as_millis()) +} + +/// 检查应用是否以管理员身份运行 +#[command] +pub fn app_is_admin(state: State<'_, RwLock>) -> Result { + Ok(state.inner().read().appinfo.app_is_admin) +} + +#[command] +pub fn export_diagnostic_info( + app_handle: AppHandle, + state: State<'_, RwLock>, +) -> Result<(), Error> { + let info = state.inner().read().to_string(); + let clipboard = app_handle.clipboard(); + clipboard.write_text(info) +} diff --git a/crates/tauri-plugin-clash-verge-sysinfo/src/lib.rs b/crates/tauri-plugin-clash-verge-sysinfo/src/lib.rs index 0364c87e7..fb1dd97a0 100644 --- a/crates/tauri-plugin-clash-verge-sysinfo/src/lib.rs +++ b/crates/tauri-plugin-clash-verge-sysinfo/src/lib.rs @@ -3,6 +3,8 @@ use std::{ time::Instant, }; +pub mod commands; + #[cfg(windows)] use deelevate::{PrivilegeLevel, Token}; use parking_lot::RwLock; @@ -130,11 +132,24 @@ pub fn set_app_core_mode(app: &tauri::AppHandle, mode: impl Into< spec.appinfo.app_core_mode = mode.into(); } +#[inline] +pub fn is_current_app_handle_admin(app: &tauri::AppHandle) -> bool { + let platform_spec = app.state::>(); + let spec = platform_spec.read(); + spec.appinfo.app_is_admin +} + #[inline] pub fn init() -> TauriPlugin { - Builder::new("clash_verge_sysinfo") + Builder::::new("clash_verge_sysinfo") + // TODO 现在 crate 还不是真正的 tauri 插件,必须由主 lib 自行注册 // TODO 从 clash-verge 中迁移获取系统信息的 commnand 并实现优雅 structure.field 访问 - // .invoke_handler(tauri::generate_handler![greet]) + // .invoke_handler(tauri::generate_handler![ + // commands::get_system_info, + // commands::get_app_uptime, + // commands::app_is_admin, + // commands::export_diagnostic_info, + // ]) .setup(move |app, _api| { let app_version = app.package_info().version.to_string(); let is_admin = is_binary_admin(); diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 84dfc513a..3e25a73b3 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -35,6 +35,7 @@ clash-verge-logging = { workspace = true } clash-verge-signal = { workspace = true } clash-verge-types = { workspace = true } tauri-plugin-clash-verge-sysinfo = { workspace = true } +tauri-plugin-clipboard-manager = { workspace = true } tauri = { workspace = true, features = [ "protocol-asset", "devtools", @@ -72,7 +73,6 @@ tauri-plugin-shell = "2.3.3" tauri-plugin-dialog = "2.4.2" tauri-plugin-fs = "2.4.4" tauri-plugin-process = "2.3.1" -tauri-plugin-clipboard-manager = "2.3.2" tauri-plugin-deep-link = "2.4.5" tauri-plugin-window-state = "2.4.1" zip = "6.0.0" diff --git a/src-tauri/src/cmd/system.rs b/src-tauri/src/cmd/system.rs index f38886d72..6eaeb3f15 100644 --- a/src-tauri/src/cmd/system.rs +++ b/src-tauri/src/cmd/system.rs @@ -1,59 +1,9 @@ use std::sync::Arc; -use super::CmdResult; -use crate::core::{CoreManager, handle, manager::RunningMode}; -use clash_verge_logging::{Type, logging}; -use parking_lot::RwLock; -use tauri::Manager as _; -use tauri_plugin_clash_verge_sysinfo::Platform; -use tauri_plugin_clipboard_manager::ClipboardExt as _; - -#[tauri::command] -pub async fn export_diagnostic_info() -> CmdResult<()> { - let app_handle = handle::Handle::app_handle(); - let info = app_handle.state::>().read().to_string(); - - let app_handle = handle::Handle::app_handle(); - let cliboard = app_handle.clipboard(); - if cliboard.write_text(info).is_err() { - logging!(error, Type::System, "Failed to write to clipboard"); - } - Ok(()) -} - -// TODO 迁移,让新的结构体允许通过 tauri command 正确使用 structure.field 方式获取信息 -#[tauri::command] -pub async fn get_system_info() -> CmdResult { - let app_handle = handle::Handle::app_handle(); - let info = app_handle.state::>().read().to_string(); - Ok(info) -} +use crate::core::{CoreManager, manager::RunningMode}; /// 获取当前内核运行模式 #[tauri::command] pub async fn get_running_mode() -> Result, String> { Ok(CoreManager::global().get_running_mode()) } - -/// 获取应用的运行时间(毫秒) -#[tauri::command] -pub fn get_app_uptime() -> u128 { - let app_handle = handle::Handle::app_handle(); - let startup_time = app_handle - .state::>() - .read() - .appinfo - .app_startup_time; - startup_time.elapsed().as_millis() -} - -/// 检查应用是否以管理员身份运行 -#[tauri::command] -pub fn is_admin() -> bool { - let app_handle = handle::Handle::app_handle(); - app_handle - .state::>() - .read() - .appinfo - .app_is_admin -} diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs index d3152616e..d3f01b6b0 100644 --- a/src-tauri/src/config/config.rs +++ b/src-tauri/src/config/config.rs @@ -1,9 +1,13 @@ use super::{IClashTemp, IProfiles, IVerge}; use crate::{ - cmd, config::{PrfItem, profiles_append_item_safe}, constants::{files, timing}, - core::{CoreManager, handle, service, tray, validate::CoreConfigValidator}, + core::{ + CoreManager, + handle::{self, Handle}, + service, tray, + validate::CoreConfigValidator, + }, enhance, utils::{dirs, help}, }; @@ -14,6 +18,7 @@ use clash_verge_logging::{Type, logging, logging_error}; use clash_verge_types::runtime::IRuntime; use smartstring::alias::String; use std::path::PathBuf; +use tauri_plugin_clash_verge_sysinfo::is_current_app_handle_admin; use tokio::sync::OnceCell; use tokio::time::sleep; @@ -60,7 +65,10 @@ impl Config { Self::ensure_default_profile_items().await?; // init Tun mode - if !cmd::system::is_admin() && service::is_service_available().await.is_err() { + let handle = Handle::app_handle(); + let is_admin = is_current_app_handle_admin(handle); + let is_service_available = service::is_service_available().await.is_ok(); + if !is_admin && !is_service_available { let verge = Self::verge().await; verge.edit_draft(|d| { d.enable_tun_mode = Some(false); diff --git a/src-tauri/src/core/service.rs b/src-tauri/src/core/service.rs index 353d72282..34c263326 100644 --- a/src-tauri/src/core/service.rs +++ b/src-tauri/src/core/service.rs @@ -255,15 +255,9 @@ async fn reinstall_service() -> Result<()> { #[cfg(target_os = "linux")] fn linux_running_as_root() -> bool { use crate::core::handle; - use parking_lot::RwLock; - use tauri::Manager as _; - use tauri_plugin_clash_verge_sysinfo::Platform; + use tauri_plugin_clash_verge_sysinfo::is_current_app_handle_admin; let app_handle = handle::Handle::app_handle(); - app_handle - .state::>() - .read() - .appinfo - .app_is_admin + is_current_app_handle_admin(app_handle) } #[cfg(target_os = "macos")] diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index 29a4837fd..832f10d2d 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -1,5 +1,6 @@ use once_cell::sync::OnceCell; use tauri::tray::TrayIconBuilder; +use tauri_plugin_clash_verge_sysinfo::is_current_app_handle_admin; use tauri_plugin_mihomo::models::Proxies; use tokio::fs; #[cfg(target_os = "macos")] @@ -303,8 +304,8 @@ impl Tray { let verge = Config::verge().await.latest_arc(); let system_proxy = verge.enable_system_proxy.as_ref().unwrap_or(&false); let tun_mode = verge.enable_tun_mode.as_ref().unwrap_or(&false); - let tun_mode_available = - cmd::system::is_admin() || service::is_service_available().await.is_ok(); + let tun_mode_available = is_current_app_handle_admin(app_handle) + || service::is_service_available().await.is_ok(); let mode = { Config::clash() .await diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 083eafe63..0e3e7c102 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -137,6 +137,10 @@ mod app_init { pub fn generate_handlers() -> impl Fn(tauri::ipc::Invoke) -> bool + Send + Sync + 'static { tauri::generate_handler![ + tauri_plugin_clash_verge_sysinfo::commands::get_system_info, + tauri_plugin_clash_verge_sysinfo::commands::get_app_uptime, + tauri_plugin_clash_verge_sysinfo::commands::app_is_admin, + tauri_plugin_clash_verge_sysinfo::commands::export_diagnostic_info, cmd::get_sys_proxy, cmd::get_auto_proxy, cmd::open_app_dir, @@ -155,9 +159,7 @@ mod app_init { cmd::notify_ui_ready, cmd::update_ui_stage, cmd::get_running_mode, - cmd::get_app_uptime, cmd::get_auto_launch_status, - cmd::is_admin, cmd::entry_lightweight_mode, cmd::exit_lightweight_mode, cmd::install_service, @@ -218,8 +220,6 @@ mod app_init { cmd::list_webdav_backup, cmd::delete_webdav_backup, cmd::restore_webdav_backup, - cmd::export_diagnostic_info, - cmd::get_system_info, cmd::get_unlock_items, cmd::check_media_unlock, ] diff --git a/src/services/cmds.ts b/src/services/cmds.ts index 860209f61..9991eaf17 100644 --- a/src/services/cmds.ts +++ b/src/services/cmds.ts @@ -540,7 +540,7 @@ export const exit_lightweight_mode = async () => { export const isAdmin = async () => { try { - return await invoke("is_admin"); + return await invoke("app_is_admin"); } catch (error) { console.error("检查管理员权限失败:", error); return false;