mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-15 22:40:42 +08:00
* perf: utilize smartstring for string handling - Updated various modules to replace standard String with smartstring::alias::String for improved performance and memory efficiency. - Adjusted string manipulations and conversions throughout the codebase to ensure compatibility with the new smartstring type. - Enhanced readability and maintainability by using `.into()` for conversions where applicable. - Ensured that all instances of string handling in configuration, logging, and network management leverage the benefits of smartstring. * fix: replace wrap_err with stringify_err for better error handling in UWP tool invocation * refactor: update import path for StringifyErr and adjust string handling in sysopt * fix: correct import path for CmdResult in UWP module * fix: update argument type for execute_sysproxy_command to use std::string::String * fix: add missing CmdResult import in UWP platform module * fix: improve string handling and error messaging across multiple files * style: format code for improved readability and consistency across multiple files * fix: remove unused file
139 lines
4.3 KiB
Rust
139 lines
4.3 KiB
Rust
use crate::{
|
||
config::Config,
|
||
core::{CoreManager, handle, tray},
|
||
logging_error,
|
||
process::AsyncHandler,
|
||
utils::{self, logging::Type, resolve},
|
||
};
|
||
use serde_yaml_ng::{Mapping, Value};
|
||
use smartstring::alias::String;
|
||
|
||
/// Restart the Clash core
|
||
pub async fn restart_clash_core() {
|
||
match CoreManager::global().restart_core().await {
|
||
Ok(_) => {
|
||
handle::Handle::refresh_clash();
|
||
handle::Handle::notice_message("set_config::ok", "ok");
|
||
}
|
||
Err(err) => {
|
||
handle::Handle::notice_message("set_config::error", format!("{err}"));
|
||
log::error!(target:"app", "{err}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// Restart the application
|
||
pub async fn restart_app() {
|
||
utils::server::shutdown_embedded_server();
|
||
if let Err(err) = resolve::resolve_reset_async().await {
|
||
handle::Handle::notice_message(
|
||
"restart_app::error",
|
||
format!("Failed to cleanup resources: {err}"),
|
||
);
|
||
log::error!(target:"app", "Restart failed during cleanup: {err}");
|
||
return;
|
||
}
|
||
|
||
let app_handle = handle::Handle::app_handle();
|
||
app_handle.restart();
|
||
}
|
||
|
||
fn after_change_clash_mode() {
|
||
AsyncHandler::spawn(move || async {
|
||
let mihomo = handle::Handle::mihomo().await;
|
||
match mihomo.get_connections().await {
|
||
Ok(connections) => {
|
||
if let Some(connections_array) = connections.connections {
|
||
for connection in connections_array {
|
||
let _ = mihomo.close_connection(&connection.id).await;
|
||
}
|
||
}
|
||
}
|
||
Err(err) => {
|
||
log::error!(target: "app", "Failed to get connections: {err}");
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
/// Change Clash mode (rule/global/direct/script)
|
||
pub async fn change_clash_mode(mode: String) {
|
||
let mut mapping = Mapping::new();
|
||
mapping.insert(Value::from("mode"), Value::from(mode.as_str()));
|
||
// Convert YAML mapping to JSON Value
|
||
let json_value = serde_json::json!({
|
||
"mode": mode
|
||
});
|
||
log::debug!(target: "app", "change clash mode to {mode}");
|
||
match handle::Handle::mihomo()
|
||
.await
|
||
.patch_base_config(&json_value)
|
||
.await
|
||
{
|
||
Ok(_) => {
|
||
// 更新订阅
|
||
Config::clash().await.data_mut().patch_config(mapping);
|
||
|
||
// 分离数据获取和异步调用
|
||
let clash_data = Config::clash().await.data_mut().clone();
|
||
if clash_data.save_config().await.is_ok() {
|
||
handle::Handle::refresh_clash();
|
||
logging_error!(Type::Tray, tray::Tray::global().update_menu().await);
|
||
logging_error!(Type::Tray, tray::Tray::global().update_icon().await);
|
||
}
|
||
|
||
let is_auto_close_connection = Config::verge()
|
||
.await
|
||
.data_mut()
|
||
.auto_close_connection
|
||
.unwrap_or(false);
|
||
if is_auto_close_connection {
|
||
after_change_clash_mode();
|
||
}
|
||
}
|
||
Err(err) => log::error!(target: "app", "{err}"),
|
||
}
|
||
}
|
||
|
||
/// Test connection delay to a URL
|
||
pub async fn test_delay(url: String) -> anyhow::Result<u32> {
|
||
use crate::utils::network::{NetworkManager, ProxyType};
|
||
use tokio::time::Instant;
|
||
|
||
let tun_mode = Config::verge()
|
||
.await
|
||
.latest_ref()
|
||
.enable_tun_mode
|
||
.unwrap_or(false);
|
||
|
||
// 如果是TUN模式,不使用代理,否则使用自身代理
|
||
let proxy_type = if !tun_mode {
|
||
ProxyType::Localhost
|
||
} else {
|
||
ProxyType::None
|
||
};
|
||
|
||
let user_agent = Some("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0".into());
|
||
|
||
let start = Instant::now();
|
||
|
||
let response = NetworkManager::new()
|
||
.get_with_interrupt(&url, proxy_type, Some(10), user_agent, false)
|
||
.await;
|
||
|
||
match response {
|
||
Ok(response) => {
|
||
log::trace!(target: "app", "test_delay response: {response:#?}");
|
||
if response.status().is_success() {
|
||
Ok(start.elapsed().as_millis() as u32)
|
||
} else {
|
||
Ok(10000u32)
|
||
}
|
||
}
|
||
Err(err) => {
|
||
log::trace!(target: "app", "test_delay error: {err:#?}");
|
||
Err(err)
|
||
}
|
||
}
|
||
}
|