mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-30 18:52:12 +08:00
* refactor: improve code quality with clippy fixes and standardized logging
- Replace dangerous unwrap()/expect() calls with proper error handling
- Standardize logging from log:: to logging\! macro with Type:: classifications
- Fix app handle panics with graceful fallback patterns
- Improve error resilience across 35+ modules without breaking functionality
- Reduce clippy warnings from 300+ to 0 in main library code
* chore: update Cargo.toml configuration
* refactor: resolve all clippy warnings
- Fix Arc clone warnings using explicit Arc::clone syntax across 9 files
- Add #[allow(clippy::expect_used)] to test functions for appropriate expect usage
- Remove no-effect statements from debug code cleanup
- Apply clippy auto-fixes for dbg\! macro removals and path statements
- Achieve zero clippy warnings on all targets with -D warnings flag
* chore: update Cargo.toml clippy configuration
* refactor: simplify macOS job configuration and improve caching
* refactor: remove unnecessary async/await from service and proxy functions
* refactor: streamline pnpm installation in CI configuration
* refactor: simplify error handling and remove unnecessary else statements
* refactor: replace async/await with synchronous locks for core management
* refactor: add workflow_dispatch trigger to clippy job
* refactor: convert async functions to synchronous for service management
* refactor: convert async functions to synchronous for UWP tool invocation
* fix: change wrong logging
* refactor: convert proxy restoration functions to async
* Revert "refactor: convert proxy restoration functions to async"
This reverts commit b82f5d250b.
* refactor: update proxy restoration functions to return Result types
* fix: handle errors during proxy restoration and update async function signatures
* fix: handle errors during proxy restoration and update async function signatures
* refactor: update restore_pac_proxy and restore_sys_proxy functions to async
* fix: convert restore_pac_proxy and restore_sys_proxy functions to async
* fix: await restore_sys_proxy calls in proxy restoration logic
* fix: suppress clippy warnings for unused async functions in proxy restoration
* fix: suppress clippy warnings for unused async functions in proxy restoration
179 lines
7.1 KiB
Rust
179 lines
7.1 KiB
Rust
use crate::{
|
|
cmd,
|
|
config::{Config, PrfItem, PrfOption},
|
|
core::{handle, CoreManager, *},
|
|
logging,
|
|
process::AsyncHandler,
|
|
utils::logging::Type,
|
|
};
|
|
use anyhow::{bail, Result};
|
|
|
|
/// Toggle proxy profile
|
|
pub fn toggle_proxy_profile(profile_index: String) {
|
|
AsyncHandler::spawn(|| async move {
|
|
let Some(app_handle) = handle::Handle::global().app_handle() else {
|
|
logging!(
|
|
error,
|
|
Type::Config,
|
|
"Failed to get app handle for profile toggle"
|
|
);
|
|
return;
|
|
};
|
|
match cmd::patch_profiles_config_by_profile_index(app_handle, profile_index).await {
|
|
Ok(_) => {
|
|
let _ = tray::Tray::global().update_menu();
|
|
}
|
|
Err(err) => {
|
|
log::error!(target: "app", "{err}");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/// Update a profile
|
|
/// If updating current profile, activate it
|
|
/// auto_refresh: 是否自动更新配置和刷新前端
|
|
pub async fn update_profile(
|
|
uid: String,
|
|
option: Option<PrfOption>,
|
|
auto_refresh: Option<bool>,
|
|
) -> Result<()> {
|
|
logging!(info, Type::Config, true, "[订阅更新] 开始更新订阅 {}", uid);
|
|
let auto_refresh = auto_refresh.unwrap_or(true); // 默认为true,保持兼容性
|
|
|
|
let url_opt = {
|
|
let profiles = Config::profiles();
|
|
let profiles = profiles.latest_ref();
|
|
let item = profiles.get_item(&uid)?;
|
|
let is_remote = item.itype.as_ref().is_some_and(|s| s == "remote");
|
|
|
|
if !is_remote {
|
|
log::info!(target: "app", "[订阅更新] {uid} 不是远程订阅,跳过更新");
|
|
None // 非远程订阅直接更新
|
|
} else if item.url.is_none() {
|
|
log::warn!(target: "app", "[订阅更新] {uid} 缺少URL,无法更新");
|
|
bail!("failed to get the profile item url");
|
|
} else {
|
|
log::info!(target: "app",
|
|
"[订阅更新] {} 是远程订阅,URL: {}",
|
|
uid,
|
|
item.url.clone().ok_or_else(|| anyhow::anyhow!("Profile URL is None"))?
|
|
);
|
|
Some((
|
|
item.url
|
|
.clone()
|
|
.ok_or_else(|| anyhow::anyhow!("Profile URL is None"))?,
|
|
item.option.clone(),
|
|
))
|
|
}
|
|
};
|
|
|
|
let should_update = match url_opt {
|
|
Some((url, opt)) => {
|
|
log::info!(target: "app", "[订阅更新] 开始下载新的订阅内容");
|
|
let merged_opt = PrfOption::merge(opt.clone(), option.clone());
|
|
|
|
// 尝试使用正常设置更新
|
|
match PrfItem::from_url(&url, None, None, merged_opt.clone()).await {
|
|
Ok(item) => {
|
|
log::info!(target: "app", "[订阅更新] 更新订阅配置成功");
|
|
let profiles = Config::profiles();
|
|
let mut profiles = profiles.draft_mut();
|
|
profiles.update_item(uid.clone(), item)?;
|
|
|
|
let is_current = Some(uid.clone()) == profiles.get_current();
|
|
log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {is_current}");
|
|
is_current && auto_refresh
|
|
}
|
|
Err(err) => {
|
|
// 首次更新失败,尝试使用Clash代理
|
|
log::warn!(target: "app", "[订阅更新] 正常更新失败: {err},尝试使用Clash代理更新");
|
|
|
|
// 发送通知
|
|
handle::Handle::notice_message("update_retry_with_clash", uid.clone());
|
|
|
|
// 保存原始代理设置
|
|
let original_with_proxy = merged_opt.as_ref().and_then(|o| o.with_proxy);
|
|
let original_self_proxy = merged_opt.as_ref().and_then(|o| o.self_proxy);
|
|
|
|
// 创建使用Clash代理的选项
|
|
let mut fallback_opt = merged_opt.unwrap_or_default();
|
|
fallback_opt.with_proxy = Some(false);
|
|
fallback_opt.self_proxy = Some(true);
|
|
|
|
// 使用Clash代理重试
|
|
match PrfItem::from_url(&url, None, None, Some(fallback_opt)).await {
|
|
Ok(mut item) => {
|
|
log::info!(target: "app", "[订阅更新] 使用Clash代理更新成功");
|
|
|
|
// 恢复原始代理设置到item
|
|
if let Some(option) = item.option.as_mut() {
|
|
option.with_proxy = original_with_proxy;
|
|
option.self_proxy = original_self_proxy;
|
|
}
|
|
|
|
// 更新到配置
|
|
let profiles = Config::profiles();
|
|
let mut profiles = profiles.draft_mut();
|
|
profiles.update_item(uid.clone(), item.clone())?;
|
|
|
|
// 获取配置名称用于通知
|
|
let profile_name = item.name.clone().unwrap_or_else(|| uid.clone());
|
|
|
|
// 发送通知告知用户自动更新使用了回退机制
|
|
handle::Handle::notice_message("update_with_clash_proxy", profile_name);
|
|
|
|
let is_current = Some(uid.clone()) == profiles.get_current();
|
|
log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {is_current}");
|
|
is_current && auto_refresh
|
|
}
|
|
Err(retry_err) => {
|
|
log::error!(target: "app", "[订阅更新] 使用Clash代理更新仍然失败: {retry_err}");
|
|
handle::Handle::notice_message(
|
|
"update_failed_even_with_clash",
|
|
format!("{retry_err}"),
|
|
);
|
|
return Err(retry_err);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
None => auto_refresh,
|
|
};
|
|
|
|
if should_update {
|
|
logging!(info, Type::Config, true, "[订阅更新] 更新内核配置");
|
|
match CoreManager::global().update_config().await {
|
|
Ok(_) => {
|
|
logging!(info, Type::Config, true, "[订阅更新] 更新成功");
|
|
handle::Handle::refresh_clash();
|
|
if let Err(err) = cmd::proxy::force_refresh_proxies().await {
|
|
logging!(
|
|
error,
|
|
Type::Config,
|
|
true,
|
|
"[订阅更新] 代理组刷新失败: {}",
|
|
err
|
|
);
|
|
}
|
|
}
|
|
Err(err) => {
|
|
logging!(error, Type::Config, true, "[订阅更新] 更新失败: {}", err);
|
|
handle::Handle::notice_message("update_failed", format!("{err}"));
|
|
log::error!(target: "app", "{err}");
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// 增强配置
|
|
pub async fn enhance_profiles() -> Result<()> {
|
|
crate::core::CoreManager::global()
|
|
.update_config()
|
|
.await
|
|
.map(|_| ())
|
|
}
|