mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-11-08 11:02:08 +08:00
style: adjust rustfmt max_width to 120
This commit is contained in:
@@ -84,10 +84,7 @@ impl WebDavClient {
|
||||
} else {
|
||||
// 释放锁后获取异步配置
|
||||
let verge = Config::verge().await.data_arc();
|
||||
if verge.webdav_url.is_none()
|
||||
|| verge.webdav_username.is_none()
|
||||
|| verge.webdav_password.is_none()
|
||||
{
|
||||
if verge.webdav_url.is_none() || verge.webdav_username.is_none() || verge.webdav_password.is_none() {
|
||||
let msg: String =
|
||||
"Unable to create web dav client, please make sure the webdav config is correct".into();
|
||||
return Err(anyhow::Error::msg(msg));
|
||||
@@ -129,10 +126,7 @@ impl WebDavClient {
|
||||
.build()?,
|
||||
)
|
||||
.set_host(config.url.into())
|
||||
.set_auth(reqwest_dav::Auth::Basic(
|
||||
config.username.into(),
|
||||
config.password.into(),
|
||||
))
|
||||
.set_auth(reqwest_dav::Auth::Basic(config.username.into(), config.password.into()))
|
||||
.build()?;
|
||||
|
||||
// 尝试检查目录是否存在,如果不存在尝试创建
|
||||
@@ -144,18 +138,10 @@ impl WebDavClient {
|
||||
match client.mkcol(dirs::BACKUP_DIR).await {
|
||||
Ok(_) => logging!(info, Type::Backup, "Successfully created backup directory"),
|
||||
Err(e) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Backup,
|
||||
"Warning: Failed to create backup directory: {}",
|
||||
e
|
||||
);
|
||||
logging!(warn, Type::Backup, "Warning: Failed to create backup directory: {}", e);
|
||||
// 清除缓存,强制下次重新尝试
|
||||
self.reset();
|
||||
return Err(anyhow::Error::msg(format!(
|
||||
"Failed to create backup directory: {}",
|
||||
e
|
||||
)));
|
||||
return Err(anyhow::Error::msg(format!("Failed to create backup directory: {}", e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -191,11 +177,7 @@ impl WebDavClient {
|
||||
|
||||
match upload_result {
|
||||
Err(_) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Backup,
|
||||
"Warning: Upload timed out, retrying once"
|
||||
);
|
||||
logging!(warn, Type::Backup, "Warning: Upload timed out, retrying once");
|
||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||
timeout(
|
||||
Duration::from_secs(TIMEOUT_UPLOAD),
|
||||
@@ -206,11 +188,7 @@ impl WebDavClient {
|
||||
}
|
||||
|
||||
Ok(Err(e)) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Backup,
|
||||
"Warning: Upload failed, retrying once: {e}"
|
||||
);
|
||||
logging!(warn, Type::Backup, "Warning: Upload failed, retrying once: {e}");
|
||||
tokio::time::sleep(Duration::from_millis(500)).await;
|
||||
timeout(
|
||||
Duration::from_secs(TIMEOUT_UPLOAD),
|
||||
@@ -243,9 +221,7 @@ impl WebDavClient {
|
||||
let path = format!("{}/", dirs::BACKUP_DIR);
|
||||
|
||||
let fut = async {
|
||||
let files = client
|
||||
.list(path.as_str(), reqwest_dav::Depth::Number(1))
|
||||
.await?;
|
||||
let files = client.list(path.as_str(), reqwest_dav::Depth::Number(1)).await?;
|
||||
let mut final_files = Vec::new();
|
||||
for file in files {
|
||||
if let ListEntity::File(file) = file {
|
||||
|
||||
@@ -177,10 +177,7 @@ impl Hotkey {
|
||||
"Failed to reactivate subscriptions via hotkey: {}",
|
||||
err
|
||||
);
|
||||
handle::Handle::notice_message(
|
||||
"reactivate_profiles::error",
|
||||
err.to_string(),
|
||||
);
|
||||
handle::Handle::notice_message("reactivate_profiles::error", err.to_string());
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -205,8 +202,7 @@ impl Hotkey {
|
||||
pub async fn register_system_hotkey(&self, hotkey: SystemHotkey) -> Result<()> {
|
||||
let hotkey_str = hotkey.to_string();
|
||||
let function = hotkey.function();
|
||||
self.register_hotkey_with_function(&hotkey_str, function)
|
||||
.await
|
||||
self.register_hotkey_with_function(&hotkey_str, function).await
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
@@ -218,11 +214,7 @@ impl Hotkey {
|
||||
|
||||
/// Register a hotkey with function enum
|
||||
#[allow(clippy::unused_async)]
|
||||
pub async fn register_hotkey_with_function(
|
||||
&self,
|
||||
hotkey: &str,
|
||||
function: HotkeyFunction,
|
||||
) -> Result<()> {
|
||||
pub async fn register_hotkey_with_function(&self, hotkey: &str, function: HotkeyFunction) -> Result<()> {
|
||||
let app_handle = handle::Handle::app_handle();
|
||||
let manager = app_handle.global_shortcut();
|
||||
|
||||
@@ -261,11 +253,8 @@ impl Hotkey {
|
||||
AsyncHandler::spawn(move || async move {
|
||||
logging!(debug, Type::Hotkey, "Executing function directly");
|
||||
|
||||
let is_enable_global_hotkey = Config::verge()
|
||||
.await
|
||||
.data_arc()
|
||||
.enable_global_hotkey
|
||||
.unwrap_or(true);
|
||||
let is_enable_global_hotkey =
|
||||
Config::verge().await.data_arc().enable_global_hotkey.unwrap_or(true);
|
||||
|
||||
if is_enable_global_hotkey {
|
||||
Self::execute_function(function);
|
||||
@@ -312,12 +301,7 @@ impl Hotkey {
|
||||
let hotkeys = verge.data_arc().hotkeys.clone();
|
||||
|
||||
if let Some(hotkeys) = hotkeys {
|
||||
logging!(
|
||||
debug,
|
||||
Type::Hotkey,
|
||||
"Has {} hotkeys need to register",
|
||||
hotkeys.len()
|
||||
);
|
||||
logging!(debug, Type::Hotkey, "Has {} hotkeys need to register", hotkeys.len());
|
||||
|
||||
for hotkey in hotkeys.iter() {
|
||||
let mut iter = hotkey.split(',');
|
||||
@@ -326,13 +310,7 @@ impl Hotkey {
|
||||
|
||||
match (key, func) {
|
||||
(Some(key), Some(func)) => {
|
||||
logging!(
|
||||
debug,
|
||||
Type::Hotkey,
|
||||
"Registering hotkey: {} -> {}",
|
||||
key,
|
||||
func
|
||||
);
|
||||
logging!(debug, Type::Hotkey, "Registering hotkey: {} -> {}", key, func);
|
||||
if let Err(e) = self.register(key, func).await {
|
||||
logging!(
|
||||
error,
|
||||
@@ -465,12 +443,7 @@ impl Drop for Hotkey {
|
||||
fn drop(&mut self) {
|
||||
let app_handle = handle::Handle::app_handle();
|
||||
if let Err(e) = app_handle.global_shortcut().unregister_all() {
|
||||
logging!(
|
||||
error,
|
||||
Type::Hotkey,
|
||||
"Error unregistering all hotkeys: {:?}",
|
||||
e
|
||||
);
|
||||
logging!(error, Type::Hotkey, "Error unregistering all hotkeys: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,9 +94,6 @@ impl CoreManager {
|
||||
}
|
||||
|
||||
async fn reload_config(&self, path: &str) -> Result<(), MihomoError> {
|
||||
handle::Handle::mihomo()
|
||||
.await
|
||||
.reload_config(true, path)
|
||||
.await
|
||||
handle::Handle::mihomo().await.reload_config(true, path).await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,10 +78,7 @@ impl CoreManager {
|
||||
|
||||
fn after_core_process(&self) {
|
||||
let app_handle = Handle::app_handle();
|
||||
tauri_plugin_clash_verge_sysinfo::set_app_core_mode(
|
||||
app_handle,
|
||||
self.get_running_mode().to_string(),
|
||||
);
|
||||
tauri_plugin_clash_verge_sysinfo::set_app_core_mode(app_handle, self.get_running_mode().to_string());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
@@ -89,11 +86,7 @@ impl CoreManager {
|
||||
use crate::{config::Config, constants::timing};
|
||||
use backoff::{Error as BackoffError, ExponentialBackoff};
|
||||
|
||||
let needs_service = Config::verge()
|
||||
.await
|
||||
.latest_arc()
|
||||
.enable_tun_mode
|
||||
.unwrap_or(false);
|
||||
let needs_service = Config::verge().await.latest_arc().enable_tun_mode.unwrap_or(false);
|
||||
|
||||
if !needs_service {
|
||||
return;
|
||||
@@ -121,9 +114,7 @@ impl CoreManager {
|
||||
if matches!(manager.current(), ServiceStatus::Ready) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(BackoffError::transient(anyhow::anyhow!(
|
||||
"Service not ready"
|
||||
)))
|
||||
Err(BackoffError::transient(anyhow::anyhow!("Service not ready")))
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -54,8 +54,7 @@ impl CoreManager {
|
||||
self.set_running_child_sidecar(child);
|
||||
self.set_running_mode(RunningMode::Sidecar);
|
||||
|
||||
let shared_writer: SharedWriter =
|
||||
std::sync::Arc::new(tokio::sync::Mutex::new(sidecar_writer().await?));
|
||||
let shared_writer: SharedWriter = std::sync::Arc::new(tokio::sync::Mutex::new(sidecar_writer().await?));
|
||||
|
||||
AsyncHandler::spawn(|| async move {
|
||||
while let Some(event) = rx.recv().await {
|
||||
@@ -64,12 +63,7 @@ impl CoreManager {
|
||||
| tauri_plugin_shell::process::CommandEvent::Stderr(line) => {
|
||||
let mut now = DeferredNow::default();
|
||||
let message = CompactString::from(String::from_utf8_lossy(&line).as_ref());
|
||||
write_sidecar_log(
|
||||
shared_writer.lock().await,
|
||||
&mut now,
|
||||
Level::Error,
|
||||
&message,
|
||||
);
|
||||
write_sidecar_log(shared_writer.lock().await, &mut now, Level::Error, &message);
|
||||
CLASH_LOGGER.append_log(message).await;
|
||||
}
|
||||
tauri_plugin_shell::process::CommandEvent::Terminated(term) => {
|
||||
@@ -81,12 +75,7 @@ impl CoreManager {
|
||||
} else {
|
||||
CompactString::from("Process terminated")
|
||||
};
|
||||
write_sidecar_log(
|
||||
shared_writer.lock().await,
|
||||
&mut now,
|
||||
Level::Info,
|
||||
&message,
|
||||
);
|
||||
write_sidecar_log(shared_writer.lock().await, &mut now, Level::Info, &message);
|
||||
CLASH_LOGGER.clear_logs().await;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -80,12 +80,7 @@ impl NotificationSystem {
|
||||
|
||||
match result {
|
||||
Ok(handle) => self.worker_handle = Some(handle),
|
||||
Err(e) => logging!(
|
||||
error,
|
||||
Type::System,
|
||||
"Failed to start notification worker: {}",
|
||||
e
|
||||
),
|
||||
Err(e) => logging!(error, Type::System, "Failed to start notification worker: {}", e),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,31 +143,19 @@ impl NotificationSystem {
|
||||
}
|
||||
}
|
||||
|
||||
fn serialize_event(
|
||||
&self,
|
||||
event: FrontendEvent,
|
||||
) -> (&'static str, Result<serde_json::Value, serde_json::Error>) {
|
||||
fn serialize_event(&self, event: FrontendEvent) -> (&'static str, Result<serde_json::Value, serde_json::Error>) {
|
||||
use serde_json::json;
|
||||
|
||||
match event {
|
||||
FrontendEvent::RefreshClash => ("verge://refresh-clash-config", Ok(json!("yes"))),
|
||||
FrontendEvent::RefreshVerge => ("verge://refresh-verge-config", Ok(json!("yes"))),
|
||||
FrontendEvent::NoticeMessage { status, message } => (
|
||||
"verge://notice-message",
|
||||
serde_json::to_value((status, message)),
|
||||
),
|
||||
FrontendEvent::ProfileChanged { current_profile_id } => {
|
||||
("profile-changed", Ok(json!(current_profile_id)))
|
||||
}
|
||||
FrontendEvent::TimerUpdated { profile_index } => {
|
||||
("verge://timer-updated", Ok(json!(profile_index)))
|
||||
}
|
||||
FrontendEvent::ProfileUpdateStarted { uid } => {
|
||||
("profile-update-started", Ok(json!({ "uid": uid })))
|
||||
}
|
||||
FrontendEvent::ProfileUpdateCompleted { uid } => {
|
||||
("profile-update-completed", Ok(json!({ "uid": uid })))
|
||||
FrontendEvent::NoticeMessage { status, message } => {
|
||||
("verge://notice-message", serde_json::to_value((status, message)))
|
||||
}
|
||||
FrontendEvent::ProfileChanged { current_profile_id } => ("profile-changed", Ok(json!(current_profile_id))),
|
||||
FrontendEvent::TimerUpdated { profile_index } => ("verge://timer-updated", Ok(json!(profile_index))),
|
||||
FrontendEvent::ProfileUpdateStarted { uid } => ("profile-update-started", Ok(json!({ "uid": uid }))),
|
||||
FrontendEvent::ProfileUpdateCompleted { uid } => ("profile-update-completed", Ok(json!({ "uid": uid }))),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,12 +165,7 @@ impl NotificationSystem {
|
||||
|
||||
let errors = self.stats.total_errors.load(Ordering::Relaxed);
|
||||
if errors > retry::EVENT_EMIT_THRESHOLD && !self.emergency_mode.load(Ordering::Acquire) {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Frontend,
|
||||
"Entering emergency mode after {} errors",
|
||||
errors
|
||||
);
|
||||
logging!(warn, Type::Frontend, "Entering emergency mode after {} errors", errors);
|
||||
self.emergency_mode.store(true, Ordering::Release);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,7 @@ async fn uninstall_service() -> Result<()> {
|
||||
let level = token.privilege_level()?;
|
||||
let status = match level {
|
||||
PrivilegeLevel::NotPrivileged => RunasCommand::new(uninstall_path).show(false).status()?,
|
||||
_ => StdCommand::new(uninstall_path)
|
||||
.creation_flags(0x08000000)
|
||||
.status()?,
|
||||
_ => StdCommand::new(uninstall_path).creation_flags(0x08000000).status()?,
|
||||
};
|
||||
|
||||
if !status.success() {
|
||||
@@ -85,16 +83,11 @@ async fn install_service() -> Result<()> {
|
||||
let level = token.privilege_level()?;
|
||||
let status = match level {
|
||||
PrivilegeLevel::NotPrivileged => RunasCommand::new(install_path).show(false).status()?,
|
||||
_ => StdCommand::new(install_path)
|
||||
.creation_flags(0x08000000)
|
||||
.status()?,
|
||||
_ => StdCommand::new(install_path).creation_flags(0x08000000).status()?,
|
||||
};
|
||||
|
||||
if !status.success() {
|
||||
bail!(
|
||||
"failed to install service with status {}",
|
||||
status.code().unwrap_or(-1)
|
||||
);
|
||||
bail!("failed to install service with status {}", status.code().unwrap_or(-1));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -123,8 +116,7 @@ async fn reinstall_service() -> Result<()> {
|
||||
async fn uninstall_service() -> Result<()> {
|
||||
logging!(info, Type::Service, "uninstall service");
|
||||
|
||||
let uninstall_path =
|
||||
tauri::utils::platform::current_exe()?.with_file_name("clash-verge-service-uninstall");
|
||||
let uninstall_path = tauri::utils::platform::current_exe()?.with_file_name("clash-verge-service-uninstall");
|
||||
|
||||
if !uninstall_path.exists() {
|
||||
bail!(format!("uninstaller not found: {uninstall_path:?}"));
|
||||
@@ -181,8 +173,7 @@ async fn uninstall_service() -> Result<()> {
|
||||
async fn install_service() -> Result<()> {
|
||||
logging!(info, Type::Service, "install service");
|
||||
|
||||
let install_path =
|
||||
tauri::utils::platform::current_exe()?.with_file_name("clash-verge-service-install");
|
||||
let install_path = tauri::utils::platform::current_exe()?.with_file_name("clash-verge-service-install");
|
||||
|
||||
if !install_path.exists() {
|
||||
bail!(format!("installer not found: {install_path:?}"));
|
||||
@@ -225,10 +216,7 @@ async fn install_service() -> Result<()> {
|
||||
);
|
||||
|
||||
if !status.success() {
|
||||
bail!(
|
||||
"failed to install service with status {}",
|
||||
status.code().unwrap_or(-1)
|
||||
);
|
||||
bail!("failed to install service with status {}", status.code().unwrap_or(-1));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -276,15 +264,12 @@ async fn uninstall_service() -> Result<()> {
|
||||
crate::utils::i18n::sync_locale().await;
|
||||
|
||||
let prompt = rust_i18n::t!("service.adminUninstallPrompt").to_string();
|
||||
let command = format!(
|
||||
r#"do shell script "sudo '{uninstall_shell}'" with administrator privileges with prompt "{prompt}""#
|
||||
);
|
||||
let command =
|
||||
format!(r#"do shell script "sudo '{uninstall_shell}'" with administrator privileges with prompt "{prompt}""#);
|
||||
|
||||
// logging!(debug, Type::Service, "uninstall command: {}", command);
|
||||
|
||||
let status = StdCommand::new("osascript")
|
||||
.args(vec!["-e", &command])
|
||||
.status()?;
|
||||
let status = StdCommand::new("osascript").args(vec!["-e", &command]).status()?;
|
||||
|
||||
if !status.success() {
|
||||
bail!(
|
||||
@@ -312,19 +297,13 @@ async fn install_service() -> Result<()> {
|
||||
crate::utils::i18n::sync_locale().await;
|
||||
|
||||
let prompt = rust_i18n::t!("service.adminInstallPrompt").to_string();
|
||||
let command = format!(
|
||||
r#"do shell script "sudo '{install_shell}'" with administrator privileges with prompt "{prompt}""#
|
||||
);
|
||||
let command =
|
||||
format!(r#"do shell script "sudo '{install_shell}'" with administrator privileges with prompt "{prompt}""#);
|
||||
|
||||
let status = StdCommand::new("osascript")
|
||||
.args(vec!["-e", &command])
|
||||
.status()?;
|
||||
let status = StdCommand::new("osascript").args(vec!["-e", &command]).status()?;
|
||||
|
||||
if !status.success() {
|
||||
bail!(
|
||||
"failed to install service with status {}",
|
||||
status.code().unwrap_or(-1)
|
||||
);
|
||||
bail!("failed to install service with status {}", status.code().unwrap_or(-1));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -362,19 +341,13 @@ async fn check_service_version() -> Result<String> {
|
||||
let version_arc: Result<String> = {
|
||||
logging!(info, Type::Service, "开始检查服务版本 (IPC)");
|
||||
let result = clash_verge_service_ipc::get_version().await;
|
||||
logging!(
|
||||
debug,
|
||||
Type::Service,
|
||||
"检查服务版本 (IPC) 结果: {:?}",
|
||||
result
|
||||
);
|
||||
logging!(debug, Type::Service, "检查服务版本 (IPC) 结果: {:?}", result);
|
||||
|
||||
// 检查错误信息是否是JSON序列化错误或预期值错误,以适配老版本服务
|
||||
// 这可能是因为老版本服务的API不兼容,导致无法正确解析响应
|
||||
// 如果是这种情况,直接返回空字符串,表示无法获取版本
|
||||
if let Err(e) = result.as_ref()
|
||||
&& (e.to_string().contains("JSON serialization error")
|
||||
|| e.to_string().contains("expected value"))
|
||||
&& (e.to_string().contains("JSON serialization error") || e.to_string().contains("expected value"))
|
||||
{
|
||||
logging!(
|
||||
warn,
|
||||
@@ -468,12 +441,7 @@ pub(super) async fn get_clash_logs_by_service() -> Result<Vec<CompactString>> {
|
||||
|
||||
if response.code > 0 {
|
||||
let err_msg = response.message;
|
||||
logging!(
|
||||
error,
|
||||
Type::Service,
|
||||
"获取服务模式下的 Clash 日志失败: {}",
|
||||
err_msg
|
||||
);
|
||||
logging!(error, Type::Service, "获取服务模式下的 Clash 日志失败: {}", err_msg);
|
||||
bail!(err_msg);
|
||||
}
|
||||
|
||||
@@ -594,12 +562,7 @@ impl ServiceManager {
|
||||
self.0 = ServiceStatus::Unavailable("Service Uninstalled".into());
|
||||
}
|
||||
ServiceStatus::Unavailable(reason) => {
|
||||
logging!(
|
||||
info,
|
||||
Type::Service,
|
||||
"服务不可用: {},将使用Sidecar模式",
|
||||
reason
|
||||
);
|
||||
logging!(info, Type::Service, "服务不可用: {},将使用Sidecar模式", reason);
|
||||
self.0 = ServiceStatus::Unavailable(reason.clone());
|
||||
return Err(anyhow::anyhow!("服务不可用: {}", reason));
|
||||
}
|
||||
@@ -609,5 +572,4 @@ impl ServiceManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub static SERVICE_MANAGER: Lazy<Mutex<ServiceManager>> =
|
||||
Lazy::new(|| Mutex::new(ServiceManager::default()));
|
||||
pub static SERVICE_MANAGER: Lazy<Mutex<ServiceManager>> = Lazy::new(|| Mutex::new(ServiceManager::default()));
|
||||
|
||||
@@ -35,10 +35,7 @@ impl Default for Sysopt {
|
||||
reset_sysproxy: AtomicBool::new(false),
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
inner_proxy: Arc::new(RwLock::new((Sysproxy::default(), Autoproxy::default()))),
|
||||
guard: Arc::new(RwLock::new(GuardMonitor::new(
|
||||
GuardType::None,
|
||||
Duration::from_secs(30),
|
||||
))),
|
||||
guard: Arc::new(RwLock::new(GuardMonitor::new(GuardType::None, Duration::from_secs(30)))),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,11 +49,7 @@ static DEFAULT_BYPASS: &str =
|
||||
"127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,localhost,*.local,*.crashlytics.com,<local>";
|
||||
|
||||
async fn get_bypass() -> String {
|
||||
let use_default = Config::verge()
|
||||
.await
|
||||
.latest_arc()
|
||||
.use_default_bypass
|
||||
.unwrap_or(true);
|
||||
let use_default = Config::verge().await.latest_arc().use_default_bypass.unwrap_or(true);
|
||||
let res = {
|
||||
let verge = Config::verge().await;
|
||||
let verge = verge.latest_arc();
|
||||
@@ -136,9 +129,9 @@ impl Sysopt {
|
||||
);
|
||||
{
|
||||
let guard = self.access_guard();
|
||||
guard.write().set_interval(Duration::from_secs(
|
||||
verge.proxy_guard_duration.unwrap_or(30),
|
||||
));
|
||||
guard
|
||||
.write()
|
||||
.set_interval(Duration::from_secs(verge.proxy_guard_duration.unwrap_or(30)));
|
||||
}
|
||||
logging!(info, Type::Core, "Starting system proxy guard...");
|
||||
{
|
||||
@@ -180,10 +173,7 @@ impl Sysopt {
|
||||
(
|
||||
verge.enable_system_proxy.unwrap_or(false),
|
||||
verge.proxy_auto_config.unwrap_or(false),
|
||||
verge
|
||||
.proxy_host
|
||||
.clone()
|
||||
.unwrap_or_else(|| String::from("127.0.0.1")),
|
||||
verge.proxy_host.clone().unwrap_or_else(|| String::from("127.0.0.1")),
|
||||
)
|
||||
};
|
||||
|
||||
@@ -306,12 +296,7 @@ impl Sysopt {
|
||||
pub async fn update_launch(&self) -> Result<()> {
|
||||
let enable_auto_launch = { Config::verge().await.latest_arc().enable_auto_launch };
|
||||
let is_enable = enable_auto_launch.unwrap_or(false);
|
||||
logging!(
|
||||
info,
|
||||
Type::System,
|
||||
"Setting auto-launch state to: {:?}",
|
||||
is_enable
|
||||
);
|
||||
logging!(info, Type::System, "Setting auto-launch state to: {:?}", is_enable);
|
||||
|
||||
// 首先尝试使用快捷方式方法
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
+30
-72
@@ -75,12 +75,7 @@ impl Timer {
|
||||
// Log timer info first
|
||||
{
|
||||
let timer_map = self.timer_map.read();
|
||||
logging!(
|
||||
info,
|
||||
Type::Timer,
|
||||
"已注册的定时任务数量: {}",
|
||||
timer_map.len()
|
||||
);
|
||||
logging!(info, Type::Timer, "已注册的定时任务数量: {}", timer_map.len());
|
||||
|
||||
for (uid, task) in timer_map.iter() {
|
||||
logging!(
|
||||
@@ -97,32 +92,30 @@ impl Timer {
|
||||
let cur_timestamp = chrono::Local::now().timestamp();
|
||||
|
||||
// Collect profiles that need immediate update
|
||||
let profiles_to_update =
|
||||
if let Some(items) = Config::profiles().await.latest_arc().get_items() {
|
||||
items
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
let allow_auto_update =
|
||||
item.option.as_ref()?.allow_auto_update.unwrap_or_default();
|
||||
if !allow_auto_update {
|
||||
return None;
|
||||
}
|
||||
let profiles_to_update = if let Some(items) = Config::profiles().await.latest_arc().get_items() {
|
||||
items
|
||||
.iter()
|
||||
.filter_map(|item| {
|
||||
let allow_auto_update = item.option.as_ref()?.allow_auto_update.unwrap_or_default();
|
||||
if !allow_auto_update {
|
||||
return None;
|
||||
}
|
||||
|
||||
let interval = item.option.as_ref()?.update_interval? as i64;
|
||||
let updated = item.updated? as i64;
|
||||
let uid = item.uid.as_ref()?;
|
||||
let interval = item.option.as_ref()?.update_interval? as i64;
|
||||
let updated = item.updated? as i64;
|
||||
let uid = item.uid.as_ref()?;
|
||||
|
||||
if interval > 0 && cur_timestamp - updated >= interval * 60 {
|
||||
logging!(info, Type::Timer, "需要立即更新的配置: uid={}", uid);
|
||||
Some(uid.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
if interval > 0 && cur_timestamp - updated >= interval * 60 {
|
||||
logging!(info, Type::Timer, "需要立即更新的配置: uid={}", uid);
|
||||
Some(uid.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
// Advance tasks outside of locks to minimize lock contention
|
||||
if !profiles_to_update.is_empty() {
|
||||
@@ -178,12 +171,7 @@ impl Timer {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
logging!(
|
||||
info,
|
||||
Type::Timer,
|
||||
"Refreshing {} timer tasks",
|
||||
diff_map.len()
|
||||
);
|
||||
logging!(info, Type::Timer, "Refreshing {} timer tasks", diff_map.len());
|
||||
|
||||
// Apply changes - first collect operations to perform without holding locks
|
||||
let mut operations_to_add: Vec<(String, TaskID, u64)> = Vec::new();
|
||||
@@ -286,12 +274,7 @@ impl Timer {
|
||||
}
|
||||
}
|
||||
|
||||
logging!(
|
||||
debug,
|
||||
Type::Timer,
|
||||
"生成的定时更新配置数量: {}",
|
||||
new_map.len()
|
||||
);
|
||||
logging!(debug, Type::Timer, "生成的定时更新配置数量: {}", new_map.len());
|
||||
new_map
|
||||
}
|
||||
|
||||
@@ -302,12 +285,7 @@ impl Timer {
|
||||
|
||||
// Read lock for comparing current state
|
||||
let timer_map = self.timer_map.read();
|
||||
logging!(
|
||||
debug,
|
||||
Type::Timer,
|
||||
"当前 timer_map 大小: {}",
|
||||
timer_map.len()
|
||||
);
|
||||
logging!(debug, Type::Timer, "当前 timer_map 大小: {}", timer_map.len());
|
||||
|
||||
// Find tasks to modify or delete
|
||||
for (uid, task) in timer_map.iter() {
|
||||
@@ -364,13 +342,7 @@ impl Timer {
|
||||
}
|
||||
|
||||
/// Add a timer task with better error handling
|
||||
fn add_task(
|
||||
&self,
|
||||
delay_timer: &DelayTimer,
|
||||
uid: String,
|
||||
tid: TaskID,
|
||||
minutes: u64,
|
||||
) -> Result<()> {
|
||||
fn add_task(&self, delay_timer: &DelayTimer, uid: String, tid: TaskID, minutes: u64) -> Result<()> {
|
||||
logging!(
|
||||
info,
|
||||
Type::Timer,
|
||||
@@ -394,9 +366,7 @@ impl Timer {
|
||||
})
|
||||
.context("failed to create timer task")?;
|
||||
|
||||
delay_timer
|
||||
.add_task(task)
|
||||
.context("failed to add timer task")?;
|
||||
delay_timer.add_task(task).context("failed to add timer task")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -443,13 +413,7 @@ impl Timer {
|
||||
// Calculate next update time
|
||||
if updated > 0 && task_interval > 0 {
|
||||
let next_time = updated + (task_interval as i64 * 60);
|
||||
logging!(
|
||||
info,
|
||||
Type::Timer,
|
||||
"计算得到下次更新时间: {}, uid={}",
|
||||
next_time,
|
||||
uid
|
||||
);
|
||||
logging!(info, Type::Timer, "计算得到下次更新时间: {}, uid={}", next_time, uid);
|
||||
Some(next_time)
|
||||
} else {
|
||||
logging!(
|
||||
@@ -483,13 +447,7 @@ impl Timer {
|
||||
Self::emit_update_event(uid, true);
|
||||
|
||||
let is_current = Config::profiles().await.latest_arc().current.as_ref() == Some(uid);
|
||||
logging!(
|
||||
info,
|
||||
Type::Timer,
|
||||
"配置 {} 是否为当前激活配置: {}",
|
||||
uid,
|
||||
is_current
|
||||
);
|
||||
logging!(info, Type::Timer, "配置 {} 是否为当前激活配置: {}", uid, is_current);
|
||||
|
||||
feat::update_profile(uid, None, is_current, false).await
|
||||
})
|
||||
|
||||
+56
-207
@@ -93,29 +93,17 @@ impl TrayState {
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let tray_icon_colorful = verge
|
||||
.tray_icon
|
||||
.clone()
|
||||
.unwrap_or_else(|| "monochrome".into());
|
||||
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
if tray_icon_colorful == "monochrome" {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-mono.ico").to_vec(),
|
||||
)
|
||||
(false, include_bytes!("../../../icons/tray-icon-mono.ico").to_vec())
|
||||
} else {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon.ico").to_vec(),
|
||||
)
|
||||
(false, include_bytes!("../../../icons/tray-icon.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon.ico").to_vec(),
|
||||
)
|
||||
(false, include_bytes!("../../../icons/tray-icon.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,29 +117,20 @@ impl TrayState {
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let tray_icon_colorful = verge
|
||||
.tray_icon
|
||||
.clone()
|
||||
.unwrap_or_else(|| "monochrome".into());
|
||||
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
if tray_icon_colorful == "monochrome" {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-sys-mono-new.ico").to_vec(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-sys.ico").to_vec(),
|
||||
)
|
||||
(false, include_bytes!("../../../icons/tray-icon-sys.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-sys.ico").to_vec(),
|
||||
)
|
||||
(false, include_bytes!("../../../icons/tray-icon-sys.ico").to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,28 +144,19 @@ impl TrayState {
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let tray_icon_colorful = verge
|
||||
.tray_icon
|
||||
.clone()
|
||||
.unwrap_or_else(|| "monochrome".into());
|
||||
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
if tray_icon_colorful == "monochrome" {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-tun-mono-new.ico").to_vec(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-tun.ico").to_vec(),
|
||||
)
|
||||
(false, include_bytes!("../../../icons/tray-icon-tun.ico").to_vec())
|
||||
}
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
(
|
||||
false,
|
||||
include_bytes!("../../../icons/tray-icon-tun.ico").to_vec(),
|
||||
)
|
||||
(false, include_bytes!("../../../icons/tray-icon-tun.ico").to_vec())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,8 +274,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 = is_current_app_handle_admin(app_handle)
|
||||
|| 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
|
||||
@@ -339,11 +309,7 @@ impl Tray {
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Tray,
|
||||
"Failed to update tray menu: tray not found"
|
||||
);
|
||||
logging!(warn, Type::Tray, "Failed to update tray menu: tray not found");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -362,11 +328,7 @@ impl Tray {
|
||||
let tray = match app_handle.tray_by_id("main") {
|
||||
Some(tray) => tray,
|
||||
None => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Tray,
|
||||
"Failed to update tray icon: tray not found"
|
||||
);
|
||||
logging!(warn, Type::Tray, "Failed to update tray icon: tray not found");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
@@ -381,10 +343,7 @@ impl Tray {
|
||||
(false, false) => TrayState::get_common_tray_icon(verge).await,
|
||||
};
|
||||
|
||||
let colorful = verge
|
||||
.tray_icon
|
||||
.clone()
|
||||
.unwrap_or_else(|| "monochrome".into());
|
||||
let colorful = verge.tray_icon.clone().unwrap_or_else(|| "monochrome".into());
|
||||
let is_colorful = colorful == "colorful";
|
||||
|
||||
let _ = tray.set_icon(Some(tauri::image::Image::from_bytes(&icon_bytes)?));
|
||||
@@ -404,11 +363,7 @@ impl Tray {
|
||||
let tray = match app_handle.tray_by_id("main") {
|
||||
Some(tray) => tray,
|
||||
None => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Tray,
|
||||
"Failed to update tray icon: tray not found"
|
||||
);
|
||||
logging!(warn, Type::Tray, "Failed to update tray icon: tray not found");
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
@@ -488,11 +443,7 @@ impl Tray {
|
||||
if let Some(tray) = app_handle.tray_by_id("main") {
|
||||
let _ = tray.set_tooltip(Some(&tooltip));
|
||||
} else {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Tray,
|
||||
"Failed to update tray tooltip: tray not found"
|
||||
);
|
||||
logging!(warn, Type::Tray, "Failed to update tray tooltip: tray not found");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -525,9 +476,7 @@ impl Tray {
|
||||
let icon = tauri::image::Image::from_bytes(&icon_bytes)?;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
let builder = TrayIconBuilder::with_id("main")
|
||||
.icon(icon)
|
||||
.icon_as_template(false);
|
||||
let builder = TrayIconBuilder::with_id("main").icon(icon).icon_as_template(false);
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||
let show_menu_on_left_click = {
|
||||
@@ -538,9 +487,7 @@ impl Tray {
|
||||
};
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let mut builder = TrayIconBuilder::with_id("main")
|
||||
.icon(icon)
|
||||
.icon_as_template(false);
|
||||
let mut builder = TrayIconBuilder::with_id("main").icon(icon).icon_as_template(false);
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||
{
|
||||
@@ -679,18 +626,9 @@ fn create_subcreate_proxy_menu_item(
|
||||
|
||||
let display_text = format!("{} | {}", proxy_str, delay_text);
|
||||
|
||||
CheckMenuItem::with_id(
|
||||
app_handle,
|
||||
item_id,
|
||||
display_text,
|
||||
true,
|
||||
is_selected,
|
||||
None::<&str>,
|
||||
)
|
||||
.map_err(|e| {
|
||||
logging!(warn, Type::Tray, "Failed to create proxy menu item: {}", e)
|
||||
})
|
||||
.ok()
|
||||
CheckMenuItem::with_id(app_handle, item_id, display_text, true, is_selected, None::<&str>)
|
||||
.map_err(|e| logging!(warn, Type::Tray, "Failed to create proxy menu item: {}", e))
|
||||
.ok()
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -700,10 +638,8 @@ fn create_subcreate_proxy_menu_item(
|
||||
|
||||
let group_display_name = group_name.to_string();
|
||||
|
||||
let group_items_refs: Vec<&dyn IsMenuItem<Wry>> = group_items
|
||||
.iter()
|
||||
.map(|item| item as &dyn IsMenuItem<Wry>)
|
||||
.collect();
|
||||
let group_items_refs: Vec<&dyn IsMenuItem<Wry>> =
|
||||
group_items.iter().map(|item| item as &dyn IsMenuItem<Wry>).collect();
|
||||
|
||||
if let Ok(submenu) = Submenu::with_id_and_items(
|
||||
app_handle,
|
||||
@@ -715,34 +651,23 @@ fn create_subcreate_proxy_menu_item(
|
||||
let insertion_index = submenus.len();
|
||||
submenus.push((group_name.into(), insertion_index, submenu));
|
||||
} else {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Tray,
|
||||
"Failed to create proxy group submenu: {}",
|
||||
group_name
|
||||
);
|
||||
logging!(warn, Type::Tray, "Failed to create proxy group submenu: {}", group_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(order_map) = proxy_group_order_map.as_ref() {
|
||||
submenus.sort_by(
|
||||
|(name_a, original_index_a, _), (name_b, original_index_b, _)| match (
|
||||
order_map.get(name_a),
|
||||
order_map.get(name_b),
|
||||
) {
|
||||
submenus.sort_by(|(name_a, original_index_a, _), (name_b, original_index_b, _)| {
|
||||
match (order_map.get(name_a), order_map.get(name_b)) {
|
||||
(Some(index_a), Some(index_b)) => index_a.cmp(index_b),
|
||||
(Some(_), None) => std::cmp::Ordering::Less,
|
||||
(None, Some(_)) => std::cmp::Ordering::Greater,
|
||||
(None, None) => original_index_a.cmp(original_index_b),
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
submenus
|
||||
.into_iter()
|
||||
.map(|(_, _, submenu)| submenu)
|
||||
.collect()
|
||||
submenus.into_iter().map(|(_, _, submenu)| submenu).collect()
|
||||
};
|
||||
proxy_submenus
|
||||
}
|
||||
@@ -825,15 +750,14 @@ async fn create_tray_menu(
|
||||
.unwrap_or_default()
|
||||
});
|
||||
|
||||
let proxy_group_order_map: Option<
|
||||
HashMap<smartstring::SmartString<smartstring::LazyCompact>, usize>,
|
||||
> = runtime_proxy_groups_order.as_ref().map(|group_names| {
|
||||
group_names
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, name)| (name.clone(), index))
|
||||
.collect::<HashMap<String, usize>>()
|
||||
});
|
||||
let proxy_group_order_map: Option<HashMap<smartstring::SmartString<smartstring::LazyCompact>, usize>> =
|
||||
runtime_proxy_groups_order.as_ref().map(|group_names| {
|
||||
group_names
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, name)| (name.clone(), index))
|
||||
.collect::<HashMap<String, usize>>()
|
||||
});
|
||||
|
||||
let verge_settings = Config::verge().await.latest_arc();
|
||||
let show_proxy_groups_inline = verge_settings.tray_inline_proxy_groups.unwrap_or(true);
|
||||
@@ -842,8 +766,7 @@ async fn create_tray_menu(
|
||||
|
||||
let hotkeys = create_hotkeys(&verge_settings.hotkeys);
|
||||
|
||||
let profile_menu_items: Vec<CheckMenuItem<Wry>> =
|
||||
create_profile_menu_item(app_handle, profiles_preview)?;
|
||||
let profile_menu_items: Vec<CheckMenuItem<Wry>> = create_profile_menu_item(app_handle, profiles_preview)?;
|
||||
|
||||
// Pre-fetch all localized strings
|
||||
let texts = MenuTexts::new();
|
||||
@@ -915,19 +838,11 @@ async fn create_tray_menu(
|
||||
&profile_menu_items_refs,
|
||||
)?;
|
||||
|
||||
let proxy_sub_menus = create_subcreate_proxy_menu_item(
|
||||
app_handle,
|
||||
current_proxy_mode,
|
||||
proxy_group_order_map,
|
||||
proxy_nodes_data,
|
||||
);
|
||||
let proxy_sub_menus =
|
||||
create_subcreate_proxy_menu_item(app_handle, current_proxy_mode, proxy_group_order_map, proxy_nodes_data);
|
||||
|
||||
let (proxies_menu, inline_proxy_items) = create_proxy_menu_item(
|
||||
app_handle,
|
||||
show_proxy_groups_inline,
|
||||
proxy_sub_menus,
|
||||
&texts.proxies,
|
||||
)?;
|
||||
let (proxies_menu, inline_proxy_items) =
|
||||
create_proxy_menu_item(app_handle, show_proxy_groups_inline, proxy_sub_menus, &texts.proxies)?;
|
||||
|
||||
let system_proxy = &CheckMenuItem::with_id(
|
||||
app_handle,
|
||||
@@ -964,66 +879,24 @@ async fn create_tray_menu(
|
||||
hotkeys.get("entry_lightweight_mode").map(|s| s.as_str()),
|
||||
)?;
|
||||
|
||||
let copy_env = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::COPY_ENV,
|
||||
&texts.copy_env,
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let copy_env = &MenuItem::with_id(app_handle, MenuIds::COPY_ENV, &texts.copy_env, true, None::<&str>)?;
|
||||
|
||||
let open_app_dir = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::CONF_DIR,
|
||||
&texts.conf_dir,
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let open_app_dir = &MenuItem::with_id(app_handle, MenuIds::CONF_DIR, &texts.conf_dir, true, None::<&str>)?;
|
||||
|
||||
let open_core_dir = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::CORE_DIR,
|
||||
&texts.core_dir,
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let open_core_dir = &MenuItem::with_id(app_handle, MenuIds::CORE_DIR, &texts.core_dir, true, None::<&str>)?;
|
||||
|
||||
let open_logs_dir = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::LOGS_DIR,
|
||||
&texts.logs_dir,
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let open_logs_dir = &MenuItem::with_id(app_handle, MenuIds::LOGS_DIR, &texts.logs_dir, true, None::<&str>)?;
|
||||
|
||||
let open_app_log = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::APP_LOG,
|
||||
&texts.app_log,
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let open_app_log = &MenuItem::with_id(app_handle, MenuIds::APP_LOG, &texts.app_log, true, None::<&str>)?;
|
||||
|
||||
let open_core_log = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::CORE_LOG,
|
||||
&texts.core_log,
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let open_core_log = &MenuItem::with_id(app_handle, MenuIds::CORE_LOG, &texts.core_log, true, None::<&str>)?;
|
||||
|
||||
let open_dir = &Submenu::with_id_and_items(
|
||||
app_handle,
|
||||
MenuIds::OPEN_DIR,
|
||||
&texts.open_dir,
|
||||
true,
|
||||
&[
|
||||
open_app_dir,
|
||||
open_core_dir,
|
||||
open_logs_dir,
|
||||
open_app_log,
|
||||
open_core_log,
|
||||
],
|
||||
&[open_app_dir, open_core_dir, open_logs_dir, open_app_log, open_core_log],
|
||||
)?;
|
||||
|
||||
let restart_clash = &MenuItem::with_id(
|
||||
@@ -1034,13 +907,7 @@ async fn create_tray_menu(
|
||||
None::<&str>,
|
||||
)?;
|
||||
|
||||
let restart_app = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::RESTART_APP,
|
||||
&texts.restart_app,
|
||||
true,
|
||||
None::<&str>,
|
||||
)?;
|
||||
let restart_app = &MenuItem::with_id(app_handle, MenuIds::RESTART_APP, &texts.restart_app, true, None::<&str>)?;
|
||||
|
||||
let app_version = &MenuItem::with_id(
|
||||
app_handle,
|
||||
@@ -1064,19 +931,12 @@ async fn create_tray_menu(
|
||||
],
|
||||
)?;
|
||||
|
||||
let quit = &MenuItem::with_id(
|
||||
app_handle,
|
||||
MenuIds::EXIT,
|
||||
&texts.exit,
|
||||
true,
|
||||
Some("CmdOrControl+Q"),
|
||||
)?;
|
||||
let quit = &MenuItem::with_id(app_handle, MenuIds::EXIT, &texts.exit, true, Some("CmdOrControl+Q"))?;
|
||||
|
||||
let separator = &PredefinedMenuItem::separator(app_handle)?;
|
||||
|
||||
// 动态构建菜单项
|
||||
let mut menu_items: Vec<&dyn IsMenuItem<Wry>> =
|
||||
vec![open_window, outbound_modes, separator, profiles];
|
||||
let mut menu_items: Vec<&dyn IsMenuItem<Wry>> = vec![open_window, outbound_modes, separator, profiles];
|
||||
|
||||
// 如果有代理节点,添加代理节点菜单
|
||||
if show_proxy_groups_inline {
|
||||
@@ -1099,9 +959,7 @@ async fn create_tray_menu(
|
||||
quit as &dyn IsMenuItem<Wry>,
|
||||
]);
|
||||
|
||||
let menu = tauri::menu::MenuBuilder::new(app_handle)
|
||||
.items(&menu_items)
|
||||
.build()?;
|
||||
let menu = tauri::menu::MenuBuilder::new(app_handle).items(&menu_items).build()?;
|
||||
Ok(menu)
|
||||
}
|
||||
|
||||
@@ -1132,11 +990,7 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) {
|
||||
}
|
||||
MenuIds::CLOSE_ALL_CONNECTIONS => {
|
||||
if let Err(err) = handle::Handle::mihomo().await.close_all_connections().await {
|
||||
logging!(
|
||||
error,
|
||||
Type::Tray,
|
||||
"Failed to close all connections from tray: {err}"
|
||||
);
|
||||
logging!(error, Type::Tray, "Failed to close all connections from tray: {err}");
|
||||
}
|
||||
}
|
||||
MenuIds::COPY_ENV => feat::copy_clash_env().await,
|
||||
@@ -1188,12 +1042,7 @@ fn on_menu_event(_: &AppHandle, event: MenuEvent) {
|
||||
feat::switch_proxy_node(group_name, proxy_name).await;
|
||||
}
|
||||
_ => {
|
||||
logging!(
|
||||
debug,
|
||||
Type::Tray,
|
||||
"Unhandled tray menu event: {:?}",
|
||||
event.id
|
||||
);
|
||||
logging!(debug, Type::Tray, "Unhandled tray menu event: {:?}", event.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,17 +45,8 @@ impl CoreConfigValidator {
|
||||
let content = match fs::read_to_string(path).await {
|
||||
Ok(content) => content,
|
||||
Err(err) => {
|
||||
logging!(
|
||||
warn,
|
||||
Type::Validate,
|
||||
"无法读取文件以检测类型: {}, 错误: {}",
|
||||
path,
|
||||
err
|
||||
);
|
||||
return Err(anyhow::anyhow!(
|
||||
"Failed to read file to detect type: {}",
|
||||
err
|
||||
));
|
||||
logging!(warn, Type::Validate, "无法读取文件以检测类型: {}, 错误: {}", path, err);
|
||||
return Err(anyhow::anyhow!("Failed to read file to detect type: {}", err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -102,12 +93,7 @@ impl CoreConfigValidator {
|
||||
}
|
||||
|
||||
// 默认情况:无法确定时,假设为非脚本文件(更安全)
|
||||
logging!(
|
||||
debug,
|
||||
Type::Validate,
|
||||
"无法确定文件类型,默认当作YAML处理: {}",
|
||||
path
|
||||
);
|
||||
logging!(debug, Type::Validate, "无法确定文件类型,默认当作YAML处理: {}", path);
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
@@ -188,10 +174,7 @@ impl CoreConfigValidator {
|
||||
}
|
||||
|
||||
/// 验证指定的配置文件
|
||||
pub async fn validate_config_file(
|
||||
config_path: &str,
|
||||
is_merge_file: Option<bool>,
|
||||
) -> Result<(bool, String)> {
|
||||
pub async fn validate_config_file(config_path: &str, is_merge_file: Option<bool>) -> Result<(bool, String)> {
|
||||
// 检查程序是否正在退出,如果是则跳过验证
|
||||
if handle::Handle::global().is_exiting() {
|
||||
logging!(info, Type::Core, "应用正在退出,跳过验证");
|
||||
@@ -207,12 +190,7 @@ impl CoreConfigValidator {
|
||||
|
||||
// 如果是合并文件且不是强制验证,执行语法检查但不进行完整验证
|
||||
if is_merge_file.unwrap_or(false) {
|
||||
logging!(
|
||||
info,
|
||||
Type::Validate,
|
||||
"检测到Merge文件,仅进行语法检查: {}",
|
||||
config_path
|
||||
);
|
||||
logging!(info, Type::Validate, "检测到Merge文件,仅进行语法检查: {}", config_path);
|
||||
return Self::validate_file_syntax(config_path).await;
|
||||
}
|
||||
|
||||
@@ -224,13 +202,7 @@ impl CoreConfigValidator {
|
||||
Ok(result) => result,
|
||||
Err(err) => {
|
||||
// 如果无法确定文件类型,尝试使用Clash内核验证
|
||||
logging!(
|
||||
warn,
|
||||
Type::Validate,
|
||||
"无法确定文件类型: {}, 错误: {}",
|
||||
config_path,
|
||||
err
|
||||
);
|
||||
logging!(warn, Type::Validate, "无法确定文件类型: {}, 错误: {}", config_path, err);
|
||||
return Self::validate_config_internal(config_path).await;
|
||||
}
|
||||
}
|
||||
@@ -247,12 +219,7 @@ impl CoreConfigValidator {
|
||||
}
|
||||
|
||||
// 对YAML配置文件使用Clash内核验证
|
||||
logging!(
|
||||
info,
|
||||
Type::Validate,
|
||||
"使用Clash内核验证配置文件: {}",
|
||||
config_path
|
||||
);
|
||||
logging!(info, Type::Validate, "使用Clash内核验证配置文件: {}", config_path);
|
||||
Self::validate_config_internal(config_path).await
|
||||
}
|
||||
|
||||
@@ -275,13 +242,11 @@ impl CoreConfigValidator {
|
||||
logging!(info, Type::Validate, "验证目录: {}", app_dir_str);
|
||||
|
||||
// 使用子进程运行clash验证配置
|
||||
let command = app_handle.shell().sidecar(clash_core.as_str())?.args([
|
||||
"-t",
|
||||
"-d",
|
||||
app_dir_str,
|
||||
"-f",
|
||||
config_path,
|
||||
]);
|
||||
let command =
|
||||
app_handle
|
||||
.shell()
|
||||
.sidecar(clash_core.as_str())?
|
||||
.args(["-t", "-d", app_dir_str, "-f", config_path]);
|
||||
let output = command.output().await?;
|
||||
|
||||
let status = &output.status;
|
||||
|
||||
Reference in New Issue
Block a user