refactor: invock mihomo api by use tauri-plugin-mihomo (#4926)

* feat: add tauri-plugin-mihomo

* refactor: invock mihomo api by use tauri-plugin-mihomo

* chore: todo

* chore: update

* chore: update

* chore: update

* chore: update

* fix: incorrect delay status and update pretty config

* chore: update

* chore: remove cache

* chore: update

* chore: update

* fix: app freezed when change group proxy

* chore: update

* chore: update

* chore: add rustfmt.toml to tauri-plugin-mihomo

* chore: happy clippy

* refactor: connect mihomo websocket

* chore: update

* chore: update

* fix: parse bigint to number

* chore: update

* Revert "fix: parse bigint to number"

This reverts commit 74c006522e23aa52cf8979a8fb47d2b1ae0bb043.

* chore: use number instead of bigint

* chore: cleanup

* fix: rule data not refresh when switch profile

* chore: update

* chore: cleanup

* chore: update

* fix: traffic graph data display

* feat: add ipc connection pool

* chore: update

* chore: clippy

* fix: incorrect delay status

* fix: typo

* fix: empty proxies tray menu

* chore: clippy

* chore: import tauri-plugin-mihomo by using git repo

* chore: cleanup

* fix: mihomo api

* fix: incorrect delay status

* chore: update tauri-plugin-mihomo dep

chore: update
This commit is contained in:
oomeow
2025-10-08 12:32:40 +08:00
committed by GitHub
parent 72aa56007c
commit 7fc238c27b
85 changed files with 1780 additions and 3344 deletions

View File

@@ -51,53 +51,7 @@ pub fn app_home_dir() -> Result<PathBuf> {
}
// 避免在Handle未初始化时崩溃
let app_handle = match handle::Handle::global().app_handle() {
Some(handle) => handle,
None => {
log::warn!(target: "app", "app_handle not initialized, using default path");
// 使用可执行文件目录作为备用
let exe_path = tauri::utils::platform::current_exe()?;
let exe_dir = exe_path
.parent()
.ok_or(anyhow::anyhow!("failed to get executable directory"))?;
// 使用系统临时目录 + 应用ID
#[cfg(target_os = "windows")]
{
if let Some(local_app_data) = std::env::var_os("LOCALAPPDATA") {
let path = PathBuf::from(local_app_data).join(APP_ID);
return Ok(path);
}
}
#[cfg(target_os = "macos")]
{
if let Some(home) = std::env::var_os("HOME") {
let path = PathBuf::from(home)
.join("Library")
.join("Application Support")
.join(APP_ID);
return Ok(path);
}
}
#[cfg(target_os = "linux")]
{
if let Some(home) = std::env::var_os("HOME") {
let path = PathBuf::from(home)
.join(".local")
.join("share")
.join(APP_ID);
return Ok(path);
}
}
// 如果无法获取系统目录,则回退到可执行文件目录
let fallback_dir = PathBuf::from(exe_dir).join(".config").join(APP_ID);
log::warn!(target: "app", "Using fallback data directory: {fallback_dir:?}");
return Ok(fallback_dir);
}
};
let app_handle = handle::Handle::app_handle();
match app_handle.path().data_dir() {
Ok(dir) => Ok(dir.join(APP_ID)),
@@ -111,18 +65,7 @@ pub fn app_home_dir() -> Result<PathBuf> {
/// get the resources dir
pub fn app_resources_dir() -> Result<PathBuf> {
// 避免在Handle未初始化时崩溃
let app_handle = match handle::Handle::global().app_handle() {
Some(handle) => handle,
None => {
log::warn!(target: "app", "app_handle not initialized in app_resources_dir, using fallback");
// 使用可执行文件目录作为备用
let exe_dir = tauri::utils::platform::current_exe()?
.parent()
.ok_or(anyhow::anyhow!("failed to get executable directory"))?
.to_path_buf();
return Ok(exe_dir.join("resources"));
}
};
let app_handle = handle::Handle::app_handle();
match app_handle.path().resource_dir() {
Ok(dir) => Ok(dir.join("resources")),

View File

@@ -1,4 +1,5 @@
/// Format bytes into human readable string (B, KB, MB, GB)
#[allow(unused)]
pub fn fmt_bytes(bytes: u64) -> String {
const UNITS: &[&str] = &["B", "KB", "MB", "GB"];
let (mut val, mut unit) = (bytes as f64, 0);

View File

@@ -494,15 +494,7 @@ pub fn init_scheme() -> Result<()> {
}
pub async fn startup_script() -> Result<()> {
let app_handle = match handle::Handle::global().app_handle() {
Some(handle) => handle,
None => {
return Err(anyhow::anyhow!(
"app_handle not available for startup script execution"
));
}
};
let app_handle = handle::Handle::app_handle();
let script_path = {
let verge = Config::verge().await;
let verge = verge.latest_ref();

View File

@@ -28,7 +28,7 @@ pub enum Type {
Lightweight,
Network,
ProxyMode,
Ipc,
// Ipc,
// Cache,
ClashVergeRev,
}
@@ -51,7 +51,7 @@ impl fmt::Display for Type {
Type::Lightweight => write!(f, "[Lightweight]"),
Type::Network => write!(f, "[Network]"),
Type::ProxyMode => write!(f, "[ProxMode]"),
Type::Ipc => write!(f, "[IPC]"),
// Type::Ipc => write!(f, "[IPC]"),
// Type::Cache => write!(f, "[Cache]"),
Type::ClashVergeRev => write!(f, "[ClashVergeRev]"),
}

View File

@@ -2,13 +2,7 @@
pub async fn set_public_dns(dns_server: String) {
use crate::{core::handle, utils::dirs};
use tauri_plugin_shell::ShellExt;
let app_handle = match handle::Handle::global().app_handle() {
Some(handle) => handle,
None => {
log::error!(target: "app", "app_handle not available for DNS configuration");
return;
}
};
let app_handle = handle::Handle::app_handle();
log::info!(target: "app", "try to set system dns");
let resource_dir = match dirs::app_resources_dir() {
@@ -50,13 +44,7 @@ pub async fn set_public_dns(dns_server: String) {
pub async fn restore_public_dns() {
use crate::{core::handle, utils::dirs};
use tauri_plugin_shell::ShellExt;
let app_handle = match handle::Handle::global().app_handle() {
Some(handle) => handle,
None => {
log::error!(target: "app", "app_handle not available for DNS restoration");
return;
}
};
let app_handle = handle::Handle::app_handle();
log::info!(target: "app", "try to unset system dns");
let resource_dir = match dirs::app_resources_dir() {
Ok(dir) => dir,

View File

@@ -1,5 +1,4 @@
use anyhow::Result;
use tauri::AppHandle;
use crate::{
config::Config,
@@ -18,8 +17,8 @@ pub mod ui;
pub mod window;
pub mod window_script;
pub fn resolve_setup_handle(app_handle: AppHandle) {
init_handle(app_handle);
pub fn resolve_setup_handle() {
init_handle();
}
pub fn resolve_setup_sync() {
@@ -121,9 +120,9 @@ pub async fn resolve_reset_async() -> Result<(), anyhow::Error> {
Ok(())
}
pub fn init_handle(app_handle: AppHandle) {
pub fn init_handle() {
logging!(info, Type::Setup, true, "Initializing app handle...");
handle::Handle::global().init(app_handle);
handle::Handle::global().init();
}
pub(super) fn init_scheme() {

View File

@@ -2,7 +2,7 @@ use tauri::WebviewWindow;
use crate::{
core::handle,
logging, logging_error,
logging_error,
utils::{
logging::Type,
resolve::window_script::{INITIAL_LOADING_OVERLAY, WINDOW_INITIAL_SCRIPT},
@@ -18,18 +18,10 @@ const MINIMAL_HEIGHT: f64 = 520.0;
/// 构建新的 WebView 窗口
pub fn build_new_window() -> Result<WebviewWindow, String> {
let app_handle = handle::Handle::global().app_handle().ok_or_else(|| {
logging!(
error,
Type::Window,
true,
"无法获取app_handle窗口创建失败"
);
"无法获取app_handle".to_string()
})?;
let app_handle = handle::Handle::app_handle();
match tauri::WebviewWindowBuilder::new(
&app_handle,
app_handle,
"main", /* the unique window label */
tauri::WebviewUrl::App("index.html".into()),
)

View File

@@ -67,7 +67,7 @@ fn should_handle_window_operation() -> bool {
let now = Instant::now();
let elapsed = now.duration_since(*last_operation);
log::debug!(target: "app", "[防抖] 检查窗口操作间隔: {}ms (需要>={}ms)",
log::debug!(target: "app", "[防抖] 检查窗口操作间隔: {}ms (需要>={}ms)",
elapsed.as_millis(), WINDOW_OPERATION_DEBOUNCE_MS);
if elapsed >= Duration::from_millis(WINDOW_OPERATION_DEBOUNCE_MS) {
@@ -76,7 +76,7 @@ fn should_handle_window_operation() -> bool {
log::info!(target: "app", "[防抖] 窗口操作被允许执行");
true
} else {
log::warn!(target: "app", "[防抖] 窗口操作被防抖机制忽略,距离上次操作 {}ms < {}ms",
log::warn!(target: "app", "[防抖] 窗口操作被防抖机制忽略,距离上次操作 {}ms < {}ms",
elapsed.as_millis(), WINDOW_OPERATION_DEBOUNCE_MS);
false
}
@@ -117,9 +117,8 @@ impl WindowManager {
/// 获取主窗口实例
pub fn get_main_window() -> Option<WebviewWindow<Wry>> {
handle::Handle::global()
.app_handle()
.and_then(|app| app.get_webview_window("main"))
let app_handle = handle::Handle::app_handle();
app_handle.get_webview_window("main")
}
/// 智能显示主窗口