edition 2024 (#4702)

* feat: update Cargo.toml for 2024 edition and optimize release profiles

* feat: refactor environment variable settings for Linux and improve code organization

* Refactor conditional statements to use `&&` for improved readability

- Updated multiple files to combine nested `if let` statements using `&&` for better clarity and conciseness.
- This change enhances the readability of the code by reducing indentation levels and making the conditions more straightforward.
- Affected files include: media_unlock_checker.rs, profile.rs, clash.rs, profiles.rs, async_proxy_query.rs, core.rs, handle.rs, hotkey.rs, service.rs, timer.rs, tray/mod.rs, merge.rs, seq.rs, config.rs, proxy.rs, window.rs, general.rs, dirs.rs, i18n.rs, init.rs, network.rs, and window.rs in the resolve module.

* refactor: streamline conditional checks using `&&` for improved readability

* fix: update release profile settings for panic behavior and optimization

* fix: adjust optimization level in Cargo.toml and reorder imports in lightweight.rs
This commit is contained in:
Tunglies
2025-09-10 09:49:06 +08:00
committed by GitHub
parent ccbffa14f0
commit 251678493c
51 changed files with 772 additions and 784 deletions

View File

@@ -6,7 +6,7 @@ authors = ["zzzgydi", "Tunglies", "wonfen", "MystiPanda"]
license = "GPL-3.0-only" license = "GPL-3.0-only"
repository = "https://github.com/clash-verge-rev/clash-verge-rev.git" repository = "https://github.com/clash-verge-rev/clash-verge-rev.git"
default-run = "clash-verge" default-run = "clash-verge"
edition = "2021" edition = "2024"
build = "build.rs" build = "build.rs"
[package.metadata.bundle] [package.metadata.bundle]
@@ -118,26 +118,32 @@ tokio-trace = ["console-subscriber"]
[profile.release] [profile.release]
panic = "abort" panic = "abort"
codegen-units = 1 codegen-units = 16
lto = true lto = true
opt-level = "s" opt-level = 2
debug = false
strip = true strip = true
overflow-checks = false
rpath = false
[profile.dev] [profile.dev]
incremental = true incremental = true
codegen-units = 256 # 增加编译单元,提升编译速度 codegen-units = 64
opt-level = 0 # 禁用优化,进一步提升编译速度 opt-level = 0
debug = true # 保留调试信息 debug = true
strip = false # 不剥离符号,保留调试信息 strip = "none"
overflow-checks = true
lto = false
rpath = false
[profile.fast-release] [profile.fast-release]
inherits = "release" # 继承 release 的配置 inherits = "release"
panic = "abort" # 与 release 相同 panic = "abort"
codegen-units = 256 # 增加编译单元,提升编译速度 codegen-units = 64
lto = false # 禁用 LTO提升编译速度 lto = false
opt-level = 0 # 禁用优化,大幅提升编译速度 opt-level = 0
debug = true # 保留调试信息 debug = true
strip = false # 不剥离符号,保留调试信息 strip = false
[lib] [lib]
name = "app_lib" name = "app_lib"

View File

@@ -1,4 +1,4 @@
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{Criterion, criterion_group, criterion_main};
use std::hint::black_box; use std::hint::black_box;
// 业务模型 & Draft // 业务模型 & Draft

View File

@@ -1,7 +1,7 @@
use super::CmdResult; use super::CmdResult;
use crate::{ use crate::{
config::Config, config::Config,
core::{handle, CoreManager}, core::{CoreManager, handle},
}; };
use crate::{ use crate::{
config::*, config::*,
@@ -166,7 +166,7 @@ pub async fn save_dns_config(dns_config: Mapping) -> CmdResult {
pub async fn apply_dns_config(apply: bool) -> CmdResult { pub async fn apply_dns_config(apply: bool) -> CmdResult {
use crate::{ use crate::{
config::Config, config::Config,
core::{handle, CoreManager}, core::{CoreManager, handle},
utils::dirs, utils::dirs,
}; };

View File

@@ -618,8 +618,9 @@ async fn check_netflix(client: &Client) -> UnlockItem {
{ {
Ok(response) => { Ok(response) => {
// 检查重定向位置 // 检查重定向位置
if let Some(location) = response.headers().get("location") { if let Some(location) = response.headers().get("location")
if let Ok(location_str) = location.to_str() { && let Ok(location_str) = location.to_str()
{
// 解析位置获取区域 // 解析位置获取区域
let parts: Vec<&str> = location_str.split('/').collect(); let parts: Vec<&str> = location_str.split('/').collect();
if parts.len() >= 4 { if parts.len() >= 4 {
@@ -633,7 +634,6 @@ async fn check_netflix(client: &Client) -> UnlockItem {
}; };
} }
} }
}
// 如果没有重定向,假设是美国 // 如果没有重定向,假设是美国
let emoji = country_code_to_emoji("us"); let emoji = country_code_to_emoji("us");
UnlockItem { UnlockItem {
@@ -691,11 +691,10 @@ async fn check_netflix_cdn(client: &Client) -> UnlockItem {
match response.json::<serde_json::Value>().await { match response.json::<serde_json::Value>().await {
Ok(data) => { Ok(data) => {
// 尝试从数据中提取区域信息 // 尝试从数据中提取区域信息
if let Some(targets) = data.get("targets").and_then(|t| t.as_array()) { if let Some(targets) = data.get("targets").and_then(|t| t.as_array())
if !targets.is_empty() { && !targets.is_empty()
if let Some(location) = targets[0].get("location") { && let Some(location) = targets[0].get("location")
if let Some(country) = && let Some(country) = location.get("country").and_then(|c| c.as_str())
location.get("country").and_then(|c| c.as_str())
{ {
let emoji = country_code_to_emoji(country); let emoji = country_code_to_emoji(country);
return UnlockItem { return UnlockItem {
@@ -705,9 +704,6 @@ async fn check_netflix_cdn(client: &Client) -> UnlockItem {
check_time: Some(get_local_date_string()), check_time: Some(get_local_date_string()),
}; };
} }
}
}
}
// 如果无法解析区域信息 // 如果无法解析区域信息
UnlockItem { UnlockItem {

View File

@@ -1,5 +1,5 @@
use super::CmdResult; use super::CmdResult;
use crate::core::{async_proxy_query::AsyncProxyQuery, EventDrivenProxyManager}; use crate::core::{EventDrivenProxyManager, async_proxy_query::AsyncProxyQuery};
use crate::process::AsyncHandler; use crate::process::AsyncHandler;
use crate::wrap_err; use crate::wrap_err;
use network_interface::NetworkInterface; use network_interface::NetworkInterface;

View File

@@ -1,13 +1,14 @@
use super::CmdResult; use super::CmdResult;
use crate::{ use crate::{
config::{ config::{
Config, IProfiles, PrfItem, PrfOption,
profiles::{ profiles::{
profiles_append_item_with_filedata_safe, profiles_delete_item_safe, profiles_append_item_with_filedata_safe, profiles_delete_item_safe,
profiles_patch_item_safe, profiles_reorder_safe, profiles_save_file_safe, profiles_patch_item_safe, profiles_reorder_safe, profiles_save_file_safe,
}, },
profiles_append_item_safe, Config, IProfiles, PrfItem, PrfOption, profiles_append_item_safe,
}, },
core::{handle, timer::Timer, tray::Tray, CoreManager}, core::{CoreManager, handle, timer::Timer, tray::Tray},
feat, logging, feat, logging,
process::AsyncHandler, process::AsyncHandler,
ret_err, ret_err,
@@ -290,8 +291,9 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult<bool> {
logging!(info, Type::Cmd, true, "当前配置: {:?}", current_profile); logging!(info, Type::Cmd, true, "当前配置: {:?}", current_profile);
// 如果要切换配置,先检查目标配置文件是否有语法错误 // 如果要切换配置,先检查目标配置文件是否有语法错误
if let Some(new_profile) = profiles.current.as_ref() { if let Some(new_profile) = profiles.current.as_ref()
if current_profile.as_ref() != Some(new_profile) { && current_profile.as_ref() != Some(new_profile)
{
logging!(info, Type::Cmd, true, "正在切换到新配置: {}", new_profile); logging!(info, Type::Cmd, true, "正在切换到新配置: {}", new_profile);
// 获取目标配置文件路径 // 获取目标配置文件路径
@@ -378,10 +380,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult<bool> {
Ok(Err(err)) => { Ok(Err(err)) => {
let error_msg = format!("无法读取目标配置文件: {err}"); let error_msg = format!("无法读取目标配置文件: {err}");
logging!(error, Type::Cmd, true, "{}", error_msg); logging!(error, Type::Cmd, true, "{}", error_msg);
handle::Handle::notice_message( handle::Handle::notice_message("config_validate::file_read_error", &error_msg);
"config_validate::file_read_error",
&error_msg,
);
return Ok(false); return Ok(false);
} }
Err(_) => { Err(_) => {
@@ -396,7 +395,6 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult<bool> {
} }
} }
} }
}
// 检查请求有效性 // 检查请求有效性
let latest_sequence = CURRENT_REQUEST_SEQUENCE.load(Ordering::SeqCst); let latest_sequence = CURRENT_REQUEST_SEQUENCE.load(Ordering::SeqCst);
@@ -663,8 +661,9 @@ pub async fn patch_profile(index: String, profile: PrfItem) -> CmdResult {
#[tauri::command] #[tauri::command]
pub async fn view_profile(index: String) -> CmdResult { pub async fn view_profile(index: String) -> CmdResult {
let profiles = Config::profiles().await; let profiles = Config::profiles().await;
let profiles_ref = profiles.latest_ref();
let file = { let file = {
wrap_err!(profiles.latest_ref().get_item(&index))? wrap_err!(profiles_ref.get_item(&index))?
.file .file
.clone() .clone()
.ok_or("the file field is null") .ok_or("the file field is null")

View File

@@ -16,11 +16,12 @@ pub async fn get_runtime_yaml() -> CmdResult<String> {
let runtime = Config::runtime().await; let runtime = Config::runtime().await;
let runtime = runtime.latest_ref(); let runtime = runtime.latest_ref();
let config = runtime.config.as_ref(); let config = runtime.config.as_ref();
wrap_err!(config wrap_err!(
config
.ok_or(anyhow::anyhow!("failed to parse config to yaml file")) .ok_or(anyhow::anyhow!("failed to parse config to yaml file"))
.and_then( .and_then(|config| serde_yaml_ng::to_string(config)
|config| serde_yaml_ng::to_string(config).context("failed to convert config to yaml") .context("failed to convert config to yaml"))
)) )
} }
/// 获取运行时存在的键 /// 获取运行时存在的键

View File

@@ -1,6 +1,6 @@
use super::CmdResult; use super::CmdResult;
use crate::{ use crate::{
core::{service, CoreManager}, core::{CoreManager, service},
utils::i18n::t, utils::i18n::t,
}; };
use anyhow::Result; use anyhow::Result;

View File

@@ -1,6 +1,6 @@
use super::CmdResult; use super::CmdResult;
use crate::{ use crate::{
core::{handle, CoreManager}, core::{CoreManager, handle},
logging, logging,
module::sysinfo::PlatformSpecification, module::sysinfo::PlatformSpecification,
utils::logging::Type, utils::logging::Type,

View File

@@ -25,18 +25,18 @@ impl IClashTemp {
match map_result { match map_result {
Ok(mut map) => { Ok(mut map) => {
template.0.keys().for_each(|key| { template.0.keys().for_each(|key| {
if !map.contains_key(key) { if !map.contains_key(key)
if let Some(value) = template.0.get(key) { && let Some(value) = template.0.get(key)
{
map.insert(key.clone(), value.clone()); map.insert(key.clone(), value.clone());
} }
}
}); });
// 确保 secret 字段存在且不为空 // 确保 secret 字段存在且不为空
if let Some(Value::String(s)) = map.get_mut("secret") { if let Some(Value::String(s)) = map.get_mut("secret")
if s.is_empty() { && s.is_empty()
{
*s = "set-your-secret".to_string(); *s = "set-your-secret".to_string();
} }
}
Self(Self::guard(map)) Self(Self::guard(map))
} }
Err(err) => { Err(err) => {

View File

@@ -1,14 +1,14 @@
use super::{Draft, IClashTemp, IProfiles, IRuntime, IVerge}; use super::{Draft, IClashTemp, IProfiles, IRuntime, IVerge};
use crate::{ use crate::{
config::{profiles_append_item_safe, PrfItem}, config::{PrfItem, profiles_append_item_safe},
core::{handle, CoreManager}, core::{CoreManager, handle},
enhance, logging, enhance, logging,
utils::{dirs, help, logging::Type}, utils::{dirs, help, logging::Type},
}; };
use anyhow::{anyhow, Result}; use anyhow::{Result, anyhow};
use std::path::PathBuf; use std::path::PathBuf;
use tokio::sync::OnceCell; use tokio::sync::OnceCell;
use tokio::time::{sleep, Duration}; use tokio::time::{Duration, sleep};
pub const RUNTIME_CONFIG: &str = "clash-verge.yaml"; pub const RUNTIME_CONFIG: &str = "clash-verge.yaml";
pub const CHECK_CONFIG: &str = "clash-verge-check.yaml"; pub const CHECK_CONFIG: &str = "clash-verge-check.yaml";

View File

@@ -1,9 +1,9 @@
use crate::utils::dirs::get_encryption_key; use crate::utils::dirs::get_encryption_key;
use aes_gcm::{ use aes_gcm::{
aead::{Aead, KeyInit},
Aes256Gcm, Key, Aes256Gcm, Key,
aead::{Aead, KeyInit},
}; };
use base64::{engine::general_purpose::STANDARD, Engine}; use base64::{Engine, engine::general_purpose::STANDARD};
use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::{Deserialize, Deserializer, Serialize, Serializer};
const NONCE_LENGTH: usize = 12; const NONCE_LENGTH: usize = 12;

View File

@@ -3,7 +3,7 @@ use crate::utils::{
network::{NetworkManager, ProxyType}, network::{NetworkManager, ProxyType},
tmpl, tmpl,
}; };
use anyhow::{bail, Context, Result}; use anyhow::{Context, Result, bail};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_yaml_ng::Mapping; use serde_yaml_ng::Mapping;
use std::{fs, time::Duration}; use std::{fs, time::Duration};

View File

@@ -1,10 +1,10 @@
use super::{prfitem::PrfItem, PrfOption}; use super::{PrfOption, prfitem::PrfItem};
use crate::{ use crate::{
logging_error, logging_error,
process::AsyncHandler, process::AsyncHandler,
utils::{dirs, help, logging::Type}, utils::{dirs, help, logging::Type},
}; };
use anyhow::{bail, Context, Result}; use anyhow::{Context, Result, bail};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_yaml_ng::Mapping; use serde_yaml_ng::Mapping;
use std::collections::HashSet; use std::collections::HashSet;
@@ -88,14 +88,14 @@ impl IProfiles {
self.items = Some(vec![]); self.items = Some(vec![]);
} }
if let Some(current) = patch.current { if let Some(current) = patch.current
if let Some(items) = self.items.as_ref() { && let Some(items) = self.items.as_ref()
{
let some_uid = Some(current); let some_uid = Some(current);
if items.iter().any(|e| e.uid == some_uid) { if items.iter().any(|e| e.uid == some_uid) {
self.current = some_uid; self.current = some_uid;
} }
} }
}
Ok(()) Ok(())
} }
@@ -287,8 +287,9 @@ impl IProfiles {
break; break;
} }
} }
if let Some(index) = index { if let Some(index) = index
if let Some(file) = items.remove(index).file { && let Some(file) = items.remove(index).file
{
let _ = dirs::app_profiles_dir().map(async move |path| { let _ = dirs::app_profiles_dir().map(async move |path| {
let path = path.join(file); let path = path.join(file);
if path.exists() { if path.exists() {
@@ -305,7 +306,6 @@ impl IProfiles {
} }
}); });
} }
}
// get the merge index // get the merge index
for (i, _) in items.iter().enumerate() { for (i, _) in items.iter().enumerate() {
if items[i].uid == merge_uid { if items[i].uid == merge_uid {
@@ -313,8 +313,9 @@ impl IProfiles {
break; break;
} }
} }
if let Some(index) = merge_index { if let Some(index) = merge_index
if let Some(file) = items.remove(index).file { && let Some(file) = items.remove(index).file
{
let _ = dirs::app_profiles_dir().map(async move |path| { let _ = dirs::app_profiles_dir().map(async move |path| {
let path = path.join(file); let path = path.join(file);
if path.exists() { if path.exists() {
@@ -331,7 +332,6 @@ impl IProfiles {
} }
}); });
} }
}
// get the script index // get the script index
for (i, _) in items.iter().enumerate() { for (i, _) in items.iter().enumerate() {
if items[i].uid == script_uid { if items[i].uid == script_uid {
@@ -339,8 +339,9 @@ impl IProfiles {
break; break;
} }
} }
if let Some(index) = script_index { if let Some(index) = script_index
if let Some(file) = items.remove(index).file { && let Some(file) = items.remove(index).file
{
let _ = dirs::app_profiles_dir().map(async move |path| { let _ = dirs::app_profiles_dir().map(async move |path| {
let path = path.join(file); let path = path.join(file);
if path.exists() { if path.exists() {
@@ -357,7 +358,6 @@ impl IProfiles {
} }
}); });
} }
}
// get the rules index // get the rules index
for (i, _) in items.iter().enumerate() { for (i, _) in items.iter().enumerate() {
if items[i].uid == rules_uid { if items[i].uid == rules_uid {
@@ -365,8 +365,9 @@ impl IProfiles {
break; break;
} }
} }
if let Some(index) = rules_index { if let Some(index) = rules_index
if let Some(file) = items.remove(index).file { && let Some(file) = items.remove(index).file
{
let _ = dirs::app_profiles_dir().map(async move |path| { let _ = dirs::app_profiles_dir().map(async move |path| {
let path = path.join(file); let path = path.join(file);
if path.exists() { if path.exists() {
@@ -383,7 +384,6 @@ impl IProfiles {
} }
}); });
} }
}
// get the proxies index // get the proxies index
for (i, _) in items.iter().enumerate() { for (i, _) in items.iter().enumerate() {
if items[i].uid == proxies_uid { if items[i].uid == proxies_uid {
@@ -391,8 +391,9 @@ impl IProfiles {
break; break;
} }
} }
if let Some(index) = proxies_index { if let Some(index) = proxies_index
if let Some(file) = items.remove(index).file { && let Some(file) = items.remove(index).file
{
let _ = dirs::app_profiles_dir().map(async move |path| { let _ = dirs::app_profiles_dir().map(async move |path| {
let path = path.join(file); let path = path.join(file);
if path.exists() { if path.exists() {
@@ -409,7 +410,6 @@ impl IProfiles {
} }
}); });
} }
}
// get the groups index // get the groups index
for (i, _) in items.iter().enumerate() { for (i, _) in items.iter().enumerate() {
if items[i].uid == groups_uid { if items[i].uid == groups_uid {
@@ -417,8 +417,9 @@ impl IProfiles {
break; break;
} }
} }
if let Some(index) = groups_index { if let Some(index) = groups_index
if let Some(file) = items.remove(index).file { && let Some(file) = items.remove(index).file
{
let _ = dirs::app_profiles_dir().map(async move |path| { let _ = dirs::app_profiles_dir().map(async move |path| {
let path = path.join(file); let path = path.join(file);
if path.exists() { if path.exists() {
@@ -435,7 +436,6 @@ impl IProfiles {
} }
}); });
} }
}
// delete the original uid // delete the original uid
if current == uid { if current == uid {
self.current = None; self.current = None;
@@ -595,8 +595,9 @@ impl IProfiles {
total_files += 1; total_files += 1;
if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) { if let Some(file_name) = path.file_name().and_then(|n| n.to_str())
if Self::is_profile_file(file_name) { && Self::is_profile_file(file_name)
{
// 检查是否为全局扩展文件 // 检查是否为全局扩展文件
if protected_files.contains(file_name) { if protected_files.contains(file_name) {
log::debug!(target: "app", "保护全局扩展配置文件: {file_name}"); log::debug!(target: "app", "保护全局扩展配置文件: {file_name}");
@@ -618,7 +619,6 @@ impl IProfiles {
} }
} }
} }
}
let result = CleanupResult { let result = CleanupResult {
total_files, total_files,
@@ -659,54 +659,48 @@ impl IProfiles {
} }
// 对于主 profile 类型remote/local还需要收集其关联的扩展文件 // 对于主 profile 类型remote/local还需要收集其关联的扩展文件
if let Some(itype) = &item.itype { if let Some(itype) = &item.itype
if itype == "remote" || itype == "local" { && (itype == "remote" || itype == "local")
if let Some(option) = &item.option { && let Some(option) = &item.option
{
// 收集关联的扩展文件 // 收集关联的扩展文件
if let Some(merge_uid) = &option.merge { if let Some(merge_uid) = &option.merge
if let Ok(merge_item) = self.get_item(merge_uid) { && let Ok(merge_item) = self.get_item(merge_uid)
if let Some(file) = &merge_item.file { && let Some(file) = &merge_item.file
{
active_files.insert(file.clone()); active_files.insert(file.clone());
} }
}
}
if let Some(script_uid) = &option.script { if let Some(script_uid) = &option.script
if let Ok(script_item) = self.get_item(script_uid) { && let Ok(script_item) = self.get_item(script_uid)
if let Some(file) = &script_item.file { && let Some(file) = &script_item.file
{
active_files.insert(file.clone()); active_files.insert(file.clone());
} }
}
}
if let Some(rules_uid) = &option.rules { if let Some(rules_uid) = &option.rules
if let Ok(rules_item) = self.get_item(rules_uid) { && let Ok(rules_item) = self.get_item(rules_uid)
if let Some(file) = &rules_item.file { && let Some(file) = &rules_item.file
{
active_files.insert(file.clone()); active_files.insert(file.clone());
} }
}
}
if let Some(proxies_uid) = &option.proxies { if let Some(proxies_uid) = &option.proxies
if let Ok(proxies_item) = self.get_item(proxies_uid) { && let Ok(proxies_item) = self.get_item(proxies_uid)
if let Some(file) = &proxies_item.file { && let Some(file) = &proxies_item.file
{
active_files.insert(file.clone()); active_files.insert(file.clone());
} }
}
}
if let Some(groups_uid) = &option.groups { if let Some(groups_uid) = &option.groups
if let Ok(groups_item) = self.get_item(groups_uid) { && let Ok(groups_item) = self.get_item(groups_uid)
if let Some(file) = &groups_item.file { && let Some(file) = &groups_item.file
{
active_files.insert(file.clone()); active_files.insert(file.clone());
} }
} }
} }
} }
}
}
}
}
active_files active_files
} }

View File

@@ -1,5 +1,5 @@
use crate::{ use crate::{
config::{deserialize_encrypted, serialize_encrypted, DEFAULT_PAC}, config::{DEFAULT_PAC, deserialize_encrypted, serialize_encrypted},
logging, logging,
utils::{dirs, help, i18n, logging::Type}, utils::{dirs, help, i18n, logging::Type},
}; };

View File

@@ -2,7 +2,7 @@
use crate::process::AsyncHandler; use crate::process::AsyncHandler;
use anyhow::Result; use anyhow::Result;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use tokio::time::{timeout, Duration}; use tokio::time::{Duration, timeout};
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
use anyhow::anyhow; use anyhow::anyhow;
@@ -87,7 +87,7 @@ impl AsyncProxyQuery {
use std::ptr; use std::ptr;
use winapi::shared::minwindef::{DWORD, HKEY}; use winapi::shared::minwindef::{DWORD, HKEY};
use winapi::um::winnt::{KEY_READ, REG_DWORD, REG_SZ}; use winapi::um::winnt::{KEY_READ, REG_DWORD, REG_SZ};
use winapi::um::winreg::{RegCloseKey, RegOpenKeyExW, RegQueryValueExW, HKEY_CURRENT_USER}; use winapi::um::winreg::{HKEY_CURRENT_USER, RegCloseKey, RegOpenKeyExW, RegQueryValueExW};
unsafe { unsafe {
let key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\0" let key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\0"
@@ -209,14 +209,14 @@ impl AsyncProxyQuery {
// Linux: 检查环境变量和GNOME设置 // Linux: 检查环境变量和GNOME设置
// 首先检查环境变量 // 首先检查环境变量
if let Ok(auto_proxy) = std::env::var("auto_proxy") { if let Ok(auto_proxy) = std::env::var("auto_proxy")
if !auto_proxy.is_empty() { && !auto_proxy.is_empty()
{
return Ok(AsyncAutoproxy { return Ok(AsyncAutoproxy {
enable: true, enable: true,
url: auto_proxy, url: auto_proxy,
}); });
} }
}
// 尝试使用 gsettings 获取 GNOME 代理设置 // 尝试使用 gsettings 获取 GNOME 代理设置
let output = Command::new("gsettings") let output = Command::new("gsettings")
@@ -224,8 +224,9 @@ impl AsyncProxyQuery {
.output() .output()
.await; .await;
if let Ok(output) = output { if let Ok(output) = output
if output.status.success() { && output.status.success()
{
let mode = String::from_utf8_lossy(&output.stdout).trim().to_string(); let mode = String::from_utf8_lossy(&output.stdout).trim().to_string();
if mode.contains("auto") { if mode.contains("auto") {
// 获取 PAC URL // 获取 PAC URL
@@ -234,8 +235,9 @@ impl AsyncProxyQuery {
.output() .output()
.await; .await;
if let Ok(pac_output) = pac_output { if let Ok(pac_output) = pac_output
if pac_output.status.success() { && pac_output.status.success()
{
let pac_url = String::from_utf8_lossy(&pac_output.stdout) let pac_url = String::from_utf8_lossy(&pac_output.stdout)
.trim() .trim()
.trim_matches('\'') .trim_matches('\'')
@@ -251,8 +253,6 @@ impl AsyncProxyQuery {
} }
} }
} }
}
}
Ok(AsyncAutoproxy::default()) Ok(AsyncAutoproxy::default())
} }
@@ -271,7 +271,7 @@ impl AsyncProxyQuery {
use std::ptr; use std::ptr;
use winapi::shared::minwindef::{DWORD, HKEY}; use winapi::shared::minwindef::{DWORD, HKEY};
use winapi::um::winnt::{KEY_READ, REG_DWORD, REG_SZ}; use winapi::um::winnt::{KEY_READ, REG_DWORD, REG_SZ};
use winapi::um::winreg::{RegCloseKey, RegOpenKeyExW, RegQueryValueExW, HKEY_CURRENT_USER}; use winapi::um::winreg::{HKEY_CURRENT_USER, RegCloseKey, RegOpenKeyExW, RegQueryValueExW};
unsafe { unsafe {
let key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\0" let key_path = "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\0"
@@ -402,11 +402,11 @@ impl AsyncProxyQuery {
http_host = host_part.trim().to_string(); http_host = host_part.trim().to_string();
} }
} else if line.contains("HTTPPort") { } else if line.contains("HTTPPort") {
if let Some(port_part) = line.split(':').nth(1) { if let Some(port_part) = line.split(':').nth(1)
if let Ok(port) = port_part.trim().parse::<u16>() { && let Ok(port) = port_part.trim().parse::<u16>()
{
http_port = port; http_port = port;
} }
}
} else if line.contains("ExceptionsList") { } else if line.contains("ExceptionsList") {
// 解析异常列表 // 解析异常列表
if let Some(list_part) = line.split(':').nth(1) { if let Some(list_part) = line.split(':').nth(1) {
@@ -431,17 +431,17 @@ impl AsyncProxyQuery {
// Linux: 检查环境变量和桌面环境设置 // Linux: 检查环境变量和桌面环境设置
// 首先检查环境变量 // 首先检查环境变量
if let Ok(http_proxy) = std::env::var("http_proxy") { if let Ok(http_proxy) = std::env::var("http_proxy")
if let Ok(proxy_info) = Self::parse_proxy_url(&http_proxy) { && let Ok(proxy_info) = Self::parse_proxy_url(&http_proxy)
{
return Ok(proxy_info); return Ok(proxy_info);
} }
}
if let Ok(https_proxy) = std::env::var("https_proxy") { if let Ok(https_proxy) = std::env::var("https_proxy")
if let Ok(proxy_info) = Self::parse_proxy_url(&https_proxy) { && let Ok(proxy_info) = Self::parse_proxy_url(&https_proxy)
{
return Ok(proxy_info); return Ok(proxy_info);
} }
}
// 尝试使用 gsettings 获取 GNOME 代理设置 // 尝试使用 gsettings 获取 GNOME 代理设置
let mode_output = Command::new("gsettings") let mode_output = Command::new("gsettings")
@@ -449,8 +449,9 @@ impl AsyncProxyQuery {
.output() .output()
.await; .await;
if let Ok(mode_output) = mode_output { if let Ok(mode_output) = mode_output
if mode_output.status.success() { && mode_output.status.success()
{
let mode = String::from_utf8_lossy(&mode_output.stdout) let mode = String::from_utf8_lossy(&mode_output.stdout)
.trim() .trim()
.to_string(); .to_string();
@@ -466,8 +467,10 @@ impl AsyncProxyQuery {
.output() .output()
.await; .await;
if let (Ok(host_output), Ok(port_output)) = (host_result, port_result) { if let (Ok(host_output), Ok(port_output)) = (host_result, port_result)
if host_output.status.success() && port_output.status.success() { && host_output.status.success()
&& port_output.status.success()
{
let host = String::from_utf8_lossy(&host_output.stdout) let host = String::from_utf8_lossy(&host_output.stdout)
.trim() .trim()
.trim_matches('\'') .trim_matches('\'')
@@ -490,8 +493,6 @@ impl AsyncProxyQuery {
} }
} }
} }
}
}
Ok(AsyncSysproxy::default()) Ok(AsyncSysproxy::default())
} }

View File

@@ -19,12 +19,12 @@ use chrono::Local;
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{ use std::{
fmt, fmt,
fs::{create_dir_all, File}, fs::{File, create_dir_all},
io::Write, io::Write,
path::PathBuf, path::PathBuf,
sync::Arc, sync::Arc,
}; };
use tauri_plugin_shell::{process::CommandChild, ShellExt}; use tauri_plugin_shell::{ShellExt, process::CommandChild};
#[derive(Debug)] #[derive(Debug)]
pub struct CoreManager { pub struct CoreManager {
@@ -467,8 +467,9 @@ impl CoreManager {
Ok((pids, process_name)) => { Ok((pids, process_name)) => {
for pid in pids { for pid in pids {
// 跳过当前管理的进程 // 跳过当前管理的进程
if let Some(current) = current_pid { if let Some(current) = current_pid
if pid == current { && pid == current
{
logging!( logging!(
debug, debug,
Type::Core, Type::Core,
@@ -479,7 +480,6 @@ impl CoreManager {
); );
continue; continue;
} }
}
pids_to_kill.push((pid, process_name.clone())); pids_to_kill.push((pid, process_name.clone()));
} }
} }
@@ -527,7 +527,7 @@ impl CoreManager {
use std::mem; use std::mem;
use winapi::um::handleapi::CloseHandle; use winapi::um::handleapi::CloseHandle;
use winapi::um::tlhelp32::{ use winapi::um::tlhelp32::{
CreateToolhelp32Snapshot, Process32FirstW, Process32NextW, PROCESSENTRY32W, CreateToolhelp32Snapshot, PROCESSENTRY32W, Process32FirstW, Process32NextW,
TH32CS_SNAPPROCESS, TH32CS_SNAPPROCESS,
}; };
use winapi::um::winnt::HANDLE; use winapi::um::winnt::HANDLE;
@@ -703,7 +703,7 @@ impl CoreManager {
use winapi::um::processthreadsapi::OpenProcess; use winapi::um::processthreadsapi::OpenProcess;
use winapi::um::winnt::{HANDLE, PROCESS_QUERY_INFORMATION}; use winapi::um::winnt::{HANDLE, PROCESS_QUERY_INFORMATION};
let result = AsyncHandler::spawn_blocking(move || -> Result<bool> { AsyncHandler::spawn_blocking(move || -> Result<bool> {
unsafe { unsafe {
let process_handle: HANDLE = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid); let process_handle: HANDLE = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid);
if process_handle.is_null() { if process_handle.is_null() {
@@ -719,9 +719,7 @@ impl CoreManager {
Ok(exit_code == 259) Ok(exit_code == 259)
} }
}) })
.await?; .await?
result
} }
#[cfg(not(windows))] #[cfg(not(windows))]
@@ -767,8 +765,9 @@ impl CoreManager {
AsyncHandler::spawn(move || async move { AsyncHandler::spawn(move || async move {
while let Some(event) = rx.recv().await { while let Some(event) = rx.recv().await {
if let tauri_plugin_shell::process::CommandEvent::Stdout(line) = event { if let tauri_plugin_shell::process::CommandEvent::Stdout(line) = event
if let Err(e) = writeln!(log_file, "{}", String::from_utf8_lossy(&line)) { && let Err(e) = writeln!(log_file, "{}", String::from_utf8_lossy(&line))
{
logging!( logging!(
error, error,
Type::Core, Type::Core,
@@ -778,7 +777,6 @@ impl CoreManager {
); );
} }
} }
}
}); });
let pid = child.pid(); let pid = child.pid();

View File

@@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::RwLock; use tokio::sync::RwLock;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use tokio::time::{sleep, timeout, Duration}; use tokio::time::{Duration, sleep, timeout};
use tokio_stream::{wrappers::UnboundedReceiverStream, StreamExt}; use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
use crate::config::{Config, IVerge}; use crate::config::{Config, IVerge};
use crate::core::async_proxy_query::AsyncProxyQuery; use crate::core::async_proxy_query::AsyncProxyQuery;

View File

@@ -2,8 +2,9 @@ use crate::singleton;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::{ use std::{
sync::{ sync::{
Arc,
atomic::{AtomicU64, Ordering}, atomic::{AtomicU64, Ordering},
mpsc, Arc, mpsc,
}, },
thread, thread,
time::{Duration, Instant}, time::{Duration, Instant},
@@ -97,16 +98,14 @@ impl NotificationSystem {
let is_emergency = *system.emergency_mode.read(); let is_emergency = *system.emergency_mode.read();
if is_emergency { if is_emergency
if let FrontendEvent::NoticeMessage { ref status, .. } = event { && let FrontendEvent::NoticeMessage { ref status, .. } = event
if status == "info" { && status == "info" {
log::warn!( log::warn!(
"Emergency mode active, skipping info message" "Emergency mode active, skipping info message"
); );
continue; continue;
} }
}
}
if let Some(window) = handle.get_window() { if let Some(window) = handle.get_window() {
*system.last_emit_time.write() = Instant::now(); *system.last_emit_time.write() = Instant::now();
@@ -199,14 +198,13 @@ impl NotificationSystem {
/// 发送事件到队列 /// 发送事件到队列
fn send_event(&self, event: FrontendEvent) -> bool { fn send_event(&self, event: FrontendEvent) -> bool {
if *self.emergency_mode.read() { if *self.emergency_mode.read()
if let FrontendEvent::NoticeMessage { ref status, .. } = event { && let FrontendEvent::NoticeMessage { ref status, .. } = event
if status == "info" { && status == "info"
{
log::info!("Skipping info message in emergency mode"); log::info!("Skipping info message in emergency mode");
return false; return false;
} }
}
}
if let Some(sender) = &self.sender { if let Some(sender) = &self.sender {
match sender.send(event) { match sender.send(event) {
@@ -372,7 +370,9 @@ impl Handle {
if let Some(system) = system_opt.as_ref() { if let Some(system) = system_opt.as_ref() {
system.send_event(FrontendEvent::ProfileUpdateStarted { uid }); system.send_event(FrontendEvent::ProfileUpdateStarted { uid });
} else { } else {
log::warn!("Notification system not initialized when trying to send ProfileUpdateStarted event."); log::warn!(
"Notification system not initialized when trying to send ProfileUpdateStarted event."
);
} }
} }
@@ -386,7 +386,9 @@ impl Handle {
if let Some(system) = system_opt.as_ref() { if let Some(system) = system_opt.as_ref() {
system.send_event(FrontendEvent::ProfileUpdateCompleted { uid }); system.send_event(FrontendEvent::ProfileUpdateCompleted { uid });
} else { } else {
log::warn!("Notification system not initialized when trying to send ProfileUpdateCompleted event."); log::warn!(
"Notification system not initialized when trying to send ProfileUpdateCompleted event."
);
} }
} }

View File

@@ -1,10 +1,10 @@
use crate::process::AsyncHandler; use crate::process::AsyncHandler;
use crate::utils::notification::{notify_event, NotificationEvent}; use crate::utils::notification::{NotificationEvent, notify_event};
use crate::{ use crate::{
config::Config, core::handle, feat, logging, logging_error, config::Config, core::handle, feat, logging, logging_error,
module::lightweight::entry_lightweight_mode, singleton_with_logging, utils::logging::Type, module::lightweight::entry_lightweight_mode, singleton_with_logging, utils::logging::Type,
}; };
use anyhow::{bail, Result}; use anyhow::{Result, bail};
use parking_lot::Mutex; use parking_lot::Mutex;
use std::{collections::HashMap, fmt, str::FromStr, sync::Arc}; use std::{collections::HashMap, fmt, str::FromStr, sync::Arc};
use tauri::{AppHandle, Manager}; use tauri::{AppHandle, Manager};
@@ -243,12 +243,12 @@ impl Hotkey {
); );
if hotkey_event_owned.key == Code::KeyQ && is_quit_owned { if hotkey_event_owned.key == Code::KeyQ && is_quit_owned {
if let Some(window) = app_handle_cloned.get_webview_window("main") { if let Some(window) = app_handle_cloned.get_webview_window("main")
if window.is_focused().unwrap_or(false) { && window.is_focused().unwrap_or(false)
{
logging!(debug, Type::Hotkey, "Executing quit function"); logging!(debug, Type::Hotkey, "Executing quit function");
Self::execute_function(function_owned, &app_handle_cloned); Self::execute_function(function_owned, &app_handle_cloned);
} }
}
} else { } else {
logging!(debug, Type::Hotkey, "Executing function directly"); logging!(debug, Type::Hotkey, "Executing function directly");

View File

@@ -1,10 +1,10 @@
use crate::{ use crate::{
config::Config, config::Config,
core::service_ipc::{send_ipc_request, IpcCommand}, core::service_ipc::{IpcCommand, send_ipc_request},
logging, logging,
utils::{dirs, logging::Type}, utils::{dirs, logging::Type},
}; };
use anyhow::{bail, Context, Result}; use anyhow::{Context, Result, bail};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{ use std::{
env::current_exe, env::current_exe,
@@ -617,18 +617,12 @@ pub async fn check_service_version() -> Result<String> {
match response.data { match response.data {
Some(data) => { Some(data) => {
if let Some(nested_data) = data.get("data") { if let Some(nested_data) = data.get("data") {
if let Some(version) = nested_data.get("version") { if let Some(version) = nested_data.get("version")
if let Some(version_str) = version.as_str() { && let Some(version_str) = version.as_str()
logging!( {
info, logging!(info, Type::Service, true, "获取到服务版本: {}", version_str);
Type::Service,
true,
"获取到服务版本: {}",
version_str
);
return Ok(version_str.to_string()); return Ok(version_str.to_string());
} }
}
logging!( logging!(
error, error,
Type::Service, Type::Service,
@@ -792,8 +786,9 @@ pub(super) async fn start_with_existing_service(config_file: &PathBuf) -> Result
} }
// 添加对嵌套JSON结构的处理 // 添加对嵌套JSON结构的处理
if let Some(data) = &response.data { if let Some(data) = &response.data
if let Some(code) = data.get("code") { && let Some(code) = data.get("code")
{
let code_value = code.as_u64().unwrap_or(1); let code_value = code.as_u64().unwrap_or(1);
let msg = data let msg = data
.get("msg") .get("msg")
@@ -812,7 +807,6 @@ pub(super) async fn start_with_existing_service(config_file: &PathBuf) -> Result
bail!("启动核心失败: {}", msg); bail!("启动核心失败: {}", msg);
} }
} }
}
logging!(info, Type::Service, true, "服务成功启动核心"); logging!(info, Type::Service, true, "服务成功启动核心");
Ok(()) Ok(())
@@ -918,8 +912,9 @@ pub(super) async fn stop_core_by_service() -> Result<()> {
bail!(response.error.unwrap_or_else(|| "停止核心失败".to_string())); bail!(response.error.unwrap_or_else(|| "停止核心失败".to_string()));
} }
if let Some(data) = &response.data { if let Some(data) = &response.data
if let Some(code) = data.get("code") { && let Some(code) = data.get("code")
{
let code_value = code.as_u64().unwrap_or(1); let code_value = code.as_u64().unwrap_or(1);
let msg = data let msg = data
.get("msg") .get("msg")
@@ -938,7 +933,6 @@ pub(super) async fn stop_core_by_service() -> Result<()> {
bail!("停止核心失败: {}", msg); bail!("停止核心失败: {}", msg);
} }
} }
}
Ok(()) Ok(())
} }

View File

@@ -1,7 +1,7 @@
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use crate::process::AsyncHandler; use crate::process::AsyncHandler;
use crate::{logging, utils::logging::Type}; use crate::{logging, utils::logging::Type};
use anyhow::{bail, Context, Result}; use anyhow::{Context, Result, bail};
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};

View File

@@ -2,7 +2,7 @@
use crate::utils::autostart as startup_shortcut; use crate::utils::autostart as startup_shortcut;
use crate::{ use crate::{
config::{Config, IVerge}, config::{Config, IVerge},
core::{handle::Handle, EventDrivenProxyManager}, core::{EventDrivenProxyManager, handle::Handle},
logging, logging_error, singleton_lazy, logging, logging_error, singleton_lazy,
utils::logging::Type, utils::logging::Type,
}; };
@@ -24,8 +24,7 @@ static DEFAULT_BYPASS: &str = "localhost;127.*;192.168.*;10.*;172.16.*;172.17.*;
static DEFAULT_BYPASS: &str = static DEFAULT_BYPASS: &str =
"localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,172.29.0.0/16,::1"; "localhost,127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,172.29.0.0/16,::1";
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
static DEFAULT_BYPASS: &str = static DEFAULT_BYPASS: &str = "127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,172.29.0.0/16,localhost,*.local,*.crashlytics.com,<local>";
"127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,172.29.0.0/16,localhost,*.local,*.crashlytics.com,<local>";
async fn get_bypass() -> String { async fn get_bypass() -> String {
let use_default = Config::verge() let use_default = Config::verge()

View File

@@ -6,8 +6,8 @@ use std::{
collections::HashMap, collections::HashMap,
pin::Pin, pin::Pin,
sync::{ sync::{
atomic::{AtomicBool, AtomicU64, Ordering},
Arc, Arc,
atomic::{AtomicBool, AtomicU64, Ordering},
}, },
}; };
@@ -242,9 +242,10 @@ impl Timer {
if let Some(items) = Config::profiles().await.latest_ref().get_items() { if let Some(items) = Config::profiles().await.latest_ref().get_items() {
for item in items.iter() { for item in items.iter() {
if let Some(option) = item.option.as_ref() { if let Some(option) = item.option.as_ref()
if let (Some(interval), Some(uid)) = (option.update_interval, &item.uid) { && let (Some(interval), Some(uid)) = (option.update_interval, &item.uid)
if interval > 0 { && interval > 0
{
logging!( logging!(
debug, debug,
Type::Timer, Type::Timer,
@@ -256,8 +257,6 @@ impl Timer {
} }
} }
} }
}
}
logging!( logging!(
debug, debug,
@@ -390,7 +389,8 @@ impl Timer {
}; };
// Get the profile updated timestamp - now safe to await // Get the profile updated timestamp - now safe to await
let profiles = { Config::profiles().await.clone().data_ref() }.clone(); let config_profiles = Config::profiles().await;
let profiles = config_profiles.data_ref().clone();
let items = match profiles.get_items() { let items = match profiles.get_items() {
Some(i) => i, Some(i) => i,
None => { None => {

View File

@@ -1,6 +1,6 @@
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use tauri::tray::TrayIconBuilder;
use tauri::Emitter; use tauri::Emitter;
use tauri::tray::TrayIconBuilder;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
pub mod speed_rate; pub mod speed_rate;
use crate::ipc::Rate; use crate::ipc::Rate;
@@ -8,7 +8,7 @@ use crate::module::lightweight;
use crate::process::AsyncHandler; use crate::process::AsyncHandler;
use crate::utils::window_manager::WindowManager; use crate::utils::window_manager::WindowManager;
use crate::{ use crate::{
cmd, Type, cmd,
config::Config, config::Config,
feat, feat,
ipc::IpcManager, ipc::IpcManager,
@@ -16,7 +16,6 @@ use crate::{
module::lightweight::is_in_lightweight_mode, module::lightweight::is_in_lightweight_mode,
singleton_lazy, singleton_lazy,
utils::{dirs::find_target_icons, i18n::t}, utils::{dirs::find_target_icons, i18n::t},
Type,
}; };
use super::handle; use super::handle;
@@ -29,9 +28,9 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use tauri::{ use tauri::{
AppHandle, Wry,
menu::{CheckMenuItem, IsMenuItem, MenuEvent, MenuItem, PredefinedMenuItem, Submenu}, menu::{CheckMenuItem, IsMenuItem, MenuEvent, MenuItem, PredefinedMenuItem, Submenu},
tray::{MouseButton, MouseButtonState, TrayIconEvent}, tray::{MouseButton, MouseButtonState, TrayIconEvent},
AppHandle, Wry,
}; };
#[derive(Clone)] #[derive(Clone)]
@@ -76,13 +75,12 @@ impl TrayState {
pub async fn get_common_tray_icon() -> (bool, Vec<u8>) { pub async fn get_common_tray_icon() -> (bool, Vec<u8>) {
let verge = Config::verge().await.latest_ref().clone(); let verge = Config::verge().await.latest_ref().clone();
let is_common_tray_icon = verge.common_tray_icon.unwrap_or(false); let is_common_tray_icon = verge.common_tray_icon.unwrap_or(false);
if is_common_tray_icon { if is_common_tray_icon
if let Ok(Some(common_icon_path)) = find_target_icons("common") { && let Ok(Some(common_icon_path)) = find_target_icons("common")
if let Ok(icon_data) = fs::read(common_icon_path) { && let Ok(icon_data) = fs::read(common_icon_path)
{
return (true, icon_data); return (true, icon_data);
} }
}
}
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
let tray_icon_colorful = verge.tray_icon.unwrap_or("monochrome".to_string()); let tray_icon_colorful = verge.tray_icon.unwrap_or("monochrome".to_string());
@@ -111,13 +109,12 @@ impl TrayState {
pub async fn get_sysproxy_tray_icon() -> (bool, Vec<u8>) { pub async fn get_sysproxy_tray_icon() -> (bool, Vec<u8>) {
let verge = Config::verge().await.latest_ref().clone(); let verge = Config::verge().await.latest_ref().clone();
let is_sysproxy_tray_icon = verge.sysproxy_tray_icon.unwrap_or(false); let is_sysproxy_tray_icon = verge.sysproxy_tray_icon.unwrap_or(false);
if is_sysproxy_tray_icon { if is_sysproxy_tray_icon
if let Ok(Some(sysproxy_icon_path)) = find_target_icons("sysproxy") { && let Ok(Some(sysproxy_icon_path)) = find_target_icons("sysproxy")
if let Ok(icon_data) = fs::read(sysproxy_icon_path) { && let Ok(icon_data) = fs::read(sysproxy_icon_path)
{
return (true, icon_data); return (true, icon_data);
} }
}
}
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string()); let tray_icon_colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string());
@@ -146,13 +143,12 @@ impl TrayState {
pub async fn get_tun_tray_icon() -> (bool, Vec<u8>) { pub async fn get_tun_tray_icon() -> (bool, Vec<u8>) {
let verge = Config::verge().await.latest_ref().clone(); let verge = Config::verge().await.latest_ref().clone();
let is_tun_tray_icon = verge.tun_tray_icon.unwrap_or(false); let is_tun_tray_icon = verge.tun_tray_icon.unwrap_or(false);
if is_tun_tray_icon { if is_tun_tray_icon
if let Ok(Some(tun_icon_path)) = find_target_icons("tun") { && let Ok(Some(tun_icon_path)) = find_target_icons("tun")
if let Ok(icon_data) = fs::read(tun_icon_path) { && let Ok(icon_data) = fs::read(tun_icon_path)
{
return (true, icon_data); return (true, icon_data);
} }
}
}
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
{ {
let tray_icon_colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string()); let tray_icon_colorful = verge.tray_icon.clone().unwrap_or("monochrome".to_string());
@@ -431,15 +427,15 @@ impl Tray {
{ {
let profiles = Config::profiles().await; let profiles = Config::profiles().await;
let profiles = profiles.latest_ref(); let profiles = profiles.latest_ref();
if let Some(current_profile_uid) = profiles.get_current() { if let Some(current_profile_uid) = profiles.get_current()
if let Ok(profile) = profiles.get_item(&current_profile_uid) { && let Ok(profile) = profiles.get_item(&current_profile_uid)
{
current_profile_name = match &profile.name { current_profile_name = match &profile.name {
Some(profile_name) => profile_name.to_string(), Some(profile_name) => profile_name.to_string(),
None => current_profile_name, None => current_profile_name,
}; };
} }
} }
}
// Get localized strings before using them // Get localized strings before using them
let sys_proxy_text = t("SysProxy").await; let sys_proxy_text = t("SysProxy").await;

View File

@@ -1,7 +1,7 @@
#![cfg(target_os = "windows")] #![cfg(target_os = "windows")]
use crate::utils::dirs; use crate::utils::dirs;
use anyhow::{bail, Result}; use anyhow::{Result, bail};
use deelevate::{PrivilegeLevel, Token}; use deelevate::{PrivilegeLevel, Token};
use runas::Command as RunasCommand; use runas::Command as RunasCommand;
use std::process::Command as StdCommand; use std::process::Command as StdCommand;

View File

@@ -18,12 +18,10 @@ pub fn use_merge(merge: Mapping, config: Mapping) -> Mapping {
deep_merge(&mut config, &Value::from(merge)); deep_merge(&mut config, &Value::from(merge));
let config = config.as_mapping().cloned().unwrap_or_else(|| { config.as_mapping().cloned().unwrap_or_else(|| {
log::error!("Failed to convert merged config to mapping, using empty mapping"); log::error!("Failed to convert merged config to mapping, using empty mapping");
Mapping::new() Mapping::new()
}); })
config
} }
#[test] #[test]

View File

@@ -384,18 +384,17 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
if let Ok(app_dir) = dirs::app_home_dir() { if let Ok(app_dir) = dirs::app_home_dir() {
let dns_path = app_dir.join("dns_config.yaml"); let dns_path = app_dir.join("dns_config.yaml");
if dns_path.exists() { if dns_path.exists()
if let Ok(dns_yaml) = fs::read_to_string(&dns_path) { && let Ok(dns_yaml) = fs::read_to_string(&dns_path)
if let Ok(dns_config) = && let Ok(dns_config) = serde_yaml_ng::from_str::<serde_yaml_ng::Mapping>(&dns_yaml)
serde_yaml_ng::from_str::<serde_yaml_ng::Mapping>(&dns_yaml)
{ {
// 处理hosts配置 // 处理hosts配置
if let Some(hosts_value) = dns_config.get("hosts") { if let Some(hosts_value) = dns_config.get("hosts")
if hosts_value.is_mapping() { && hosts_value.is_mapping()
{
config.insert("hosts".into(), hosts_value.clone()); config.insert("hosts".into(), hosts_value.clone());
log::info!(target: "app", "apply hosts configuration"); log::info!(target: "app", "apply hosts configuration");
} }
}
if let Some(dns_value) = dns_config.get("dns") { if let Some(dns_value) = dns_config.get("dns") {
if let Some(dns_mapping) = dns_value.as_mapping() { if let Some(dns_mapping) = dns_value.as_mapping() {
@@ -409,8 +408,6 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
} }
} }
} }
}
}
let mut exists_set = HashSet::new(); let mut exists_set = HashSet::new();
exists_set.extend(exists_keys); exists_set.extend(exists_keys);

View File

@@ -7,7 +7,7 @@ pub fn use_script(
config: Mapping, config: Mapping,
name: String, name: String,
) -> Result<(Mapping, Vec<(String, String)>)> { ) -> Result<(Mapping, Vec<(String, String)>)> {
use boa_engine::{native_function::NativeFunction, Context, JsString, JsValue, Source}; use boa_engine::{Context, JsString, JsValue, Source, native_function::NativeFunction};
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, rc::Rc};
let mut context = Context::default(); let mut context = Context::default();

View File

@@ -44,8 +44,9 @@ pub fn use_seq(seq: SeqMap, mut config: Mapping, field: &str) -> Mapping {
config.insert(Value::String(field.into()), Value::Sequence(new_seq)); config.insert(Value::String(field.into()), Value::Sequence(new_seq));
// If this is proxies field, we also need to filter proxy-groups // If this is proxies field, we also need to filter proxy-groups
if field == "proxies" { if field == "proxies"
if let Some(Value::Sequence(groups)) = config.get_mut("proxy-groups") { && let Some(Value::Sequence(groups)) = config.get_mut("proxy-groups")
{
let mut new_groups = Sequence::new(); let mut new_groups = Sequence::new();
for group in groups { for group in groups {
if let Value::Mapping(group_map) = group { if let Value::Mapping(group_map) = group {
@@ -77,7 +78,6 @@ pub fn use_seq(seq: SeqMap, mut config: Mapping, field: &str) -> Mapping {
Value::Sequence(new_groups), Value::Sequence(new_groups),
); );
} }
}
config config
} }

View File

@@ -1,6 +1,6 @@
use crate::{ use crate::{
config::Config, config::Config,
core::{handle, tray, CoreManager}, core::{CoreManager, handle, tray},
ipc::IpcManager, ipc::IpcManager,
logging_error, logging_error,
process::AsyncHandler, process::AsyncHandler,

View File

@@ -1,6 +1,6 @@
use crate::{ use crate::{
config::{Config, IVerge}, config::{Config, IVerge},
core::{handle, hotkey, sysopt, tray, CoreManager}, core::{CoreManager, handle, hotkey, sysopt, tray},
logging_error, logging_error,
module::lightweight, module::lightweight,
utils::logging::Type, utils::logging::Type,
@@ -202,11 +202,11 @@ pub async fn patch_verge(patch: IVerge, not_save_file: bool) -> Result<()> {
if (update_flags & (UpdateFlags::SysProxy as i32)) != 0 { if (update_flags & (UpdateFlags::SysProxy as i32)) != 0 {
sysopt::Sysopt::global().update_sysproxy().await?; sysopt::Sysopt::global().update_sysproxy().await?;
} }
if (update_flags & (UpdateFlags::Hotkey as i32)) != 0 { if (update_flags & (UpdateFlags::Hotkey as i32)) != 0
if let Some(hotkeys) = patch.hotkeys { && let Some(hotkeys) = patch.hotkeys
{
hotkey::Hotkey::global().update(hotkeys).await?; hotkey::Hotkey::global().update(hotkeys).await?;
} }
}
if (update_flags & (UpdateFlags::SystrayMenu as i32)) != 0 { if (update_flags & (UpdateFlags::SystrayMenu as i32)) != 0 {
tray::Tray::global().update_menu().await?; tray::Tray::global().update_menu().await?;
} }

View File

@@ -1,11 +1,11 @@
use crate::{ use crate::{
cmd, cmd,
config::{profiles::profiles_draft_update_item_safe, Config, PrfItem, PrfOption}, config::{Config, PrfItem, PrfOption, profiles::profiles_draft_update_item_safe},
core::{handle, tray, CoreManager}, core::{CoreManager, handle, tray},
logging, logging,
utils::logging::Type, utils::logging::Type,
}; };
use anyhow::{bail, Result}; use anyhow::{Result, bail};
/// Toggle proxy profile /// Toggle proxy profile
pub async fn toggle_proxy_profile(profile_index: String) { pub async fn toggle_proxy_profile(profile_index: String) {

View File

@@ -13,22 +13,23 @@ pub async fn toggle_system_proxy() {
// 获取当前系统代理状态 // 获取当前系统代理状态
let enable = { let enable = {
let verge = Config::verge().await; let verge = Config::verge().await;
let enable = verge.latest_ref().enable_system_proxy.unwrap_or(false);
enable verge.latest_ref().enable_system_proxy.unwrap_or(false)
}; };
// 获取自动关闭连接设置 // 获取自动关闭连接设置
let auto_close_connection = { let auto_close_connection = {
let verge = Config::verge().await; let verge = Config::verge().await;
let auto_close = verge.latest_ref().auto_close_connection.unwrap_or(false);
auto_close verge.latest_ref().auto_close_connection.unwrap_or(false)
}; };
// 如果当前系统代理即将关闭且自动关闭连接设置为true则关闭所有连接 // 如果当前系统代理即将关闭且自动关闭连接设置为true则关闭所有连接
if enable && auto_close_connection { if enable
if let Err(err) = IpcManager::global().close_all_connections().await { && auto_close_connection
&& let Err(err) = IpcManager::global().close_all_connections().await
{
log::error!(target: "app", "Failed to close all connections: {err}"); log::error!(target: "app", "Failed to close all connections: {err}");
} }
}
let patch_result = super::patch_verge( let patch_result = super::patch_verge(
IVerge { IVerge {

View File

@@ -1,7 +1,7 @@
use crate::utils::window_manager::WindowManager; use crate::utils::window_manager::WindowManager;
use crate::{ use crate::{
config::Config, config::Config,
core::{handle, sysopt, CoreManager}, core::{CoreManager, handle, sysopt},
ipc::IpcManager, ipc::IpcManager,
logging, logging,
module::lightweight, module::lightweight,
@@ -56,7 +56,7 @@ pub async fn quit() {
} }
async fn clean_async() -> bool { async fn clean_async() -> bool {
use tokio::time::{timeout, Duration}; use tokio::time::{Duration, timeout};
logging!(info, Type::System, true, "开始执行异步清理操作..."); logging!(info, Type::System, true, "开始执行异步清理操作...");
@@ -216,10 +216,10 @@ pub async fn hide() {
add_light_weight_timer().await; add_light_weight_timer().await;
} }
if let Some(window) = handle::Handle::global().get_window() { if let Some(window) = handle::Handle::global().get_window()
if window.is_visible().unwrap_or(false) { && window.is_visible().unwrap_or(false)
{
let _ = window.hide(); let _ = window.hide();
} }
}
handle::Handle::global().set_activation_policy_accessory(); handle::Handle::global().set_activation_policy_accessory();
} }

View File

@@ -1,10 +1,10 @@
use std::time::Duration; use std::time::Duration;
use kode_bridge::{ use kode_bridge::{
errors::{AnyError, AnyResult},
ClientConfig, IpcHttpClient, LegacyResponse, ClientConfig, IpcHttpClient, LegacyResponse,
errors::{AnyError, AnyResult},
}; };
use percent_encoding::{utf8_percent_encode, AsciiSet, CONTROLS}; use percent_encoding::{AsciiSet, CONTROLS, utf8_percent_encode};
use crate::{ use crate::{
logging, singleton_with_logging, logging, singleton_with_logging,
@@ -199,8 +199,7 @@ impl IpcManager {
// 测速URL不再编码直接传递 // 测速URL不再编码直接传递
let url = format!("/proxies/{encoded_name}/delay?url={test_url}&timeout={timeout}"); let url = format!("/proxies/{encoded_name}/delay?url={test_url}&timeout={timeout}");
let response = self.send_request("GET", &url, None).await; self.send_request("GET", &url, None).await
response
} }
// 版本和配置相关 // 版本和配置相关
@@ -340,8 +339,7 @@ impl IpcManager {
// 测速URL不再编码直接传递 // 测速URL不再编码直接传递
let url = format!("/group/{encoded_group_name}/delay?url={test_url}&timeout={timeout}"); let url = format!("/group/{encoded_group_name}/delay?url={test_url}&timeout={timeout}");
let response = self.send_request("GET", &url, None).await; self.send_request("GET", &url, None).await
response
} }
// 调试相关 // 调试相关

View File

@@ -26,7 +26,7 @@ use tauri::Manager;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
use tauri_plugin_autostart::MacosLauncher; use tauri_plugin_autostart::MacosLauncher;
use tauri_plugin_deep_link::DeepLinkExt; use tauri_plugin_deep_link::DeepLinkExt;
use tokio::time::{timeout, Duration}; use tokio::time::{Duration, timeout};
use utils::logging::Type; use utils::logging::Type;
/// Application initialization helper functions /// Application initialization helper functions
@@ -134,8 +134,8 @@ mod app_init {
} }
/// Generate all command handlers for the application /// Generate all command handlers for the application
pub fn generate_handlers( pub fn generate_handlers()
) -> impl Fn(tauri::ipc::Invoke<tauri::Wry>) -> bool + Send + Sync + 'static { -> impl Fn(tauri::ipc::Invoke<tauri::Wry>) -> bool + Send + Sync + 'static {
tauri::generate_handler![ tauri::generate_handler![
// Common commands // Common commands
cmd::get_sys_proxy, cmd::get_sys_proxy,
@@ -275,7 +275,9 @@ pub fn run() {
// Set Linux environment variable // Set Linux environment variable
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
{ {
unsafe {
std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");
}
let desktop_env = std::env::var("XDG_CURRENT_DESKTOP") let desktop_env = std::env::var("XDG_CURRENT_DESKTOP")
.unwrap_or_default() .unwrap_or_default()
@@ -284,7 +286,9 @@ pub fn run() {
let is_plasma_desktop = desktop_env.contains("PLASMA"); let is_plasma_desktop = desktop_env.contains("PLASMA");
if is_kde_desktop || is_plasma_desktop { if is_kde_desktop || is_plasma_desktop {
unsafe {
std::env::set_var("GTK_CSD", "0"); std::env::set_var("GTK_CSD", "0");
}
logging!( logging!(
info, info,
Type::Setup, Type::Setup,
@@ -438,11 +442,11 @@ pub fn run() {
} }
} }
if !is_enable_global_hotkey { if !is_enable_global_hotkey
if let Err(e) = hotkey::Hotkey::global().init().await { && let Err(e) = hotkey::Hotkey::global().init().await
{
logging!(error, Type::Hotkey, true, "Failed to init hotkeys: {}", e); logging!(error, Type::Hotkey, true, "Failed to init hotkeys: {}", e);
} }
}
return; return;
} }
@@ -474,11 +478,9 @@ pub fn run() {
} }
} }
if !is_enable_global_hotkey { if !is_enable_global_hotkey && let Err(e) = hotkey::Hotkey::global().reset() {
if let Err(e) = hotkey::Hotkey::global().reset() {
logging!(error, Type::Hotkey, true, "Failed to reset hotkeys: {}", e); logging!(error, Type::Hotkey, true, "Failed to reset hotkeys: {}", e);
} }
}
}); });
} }

View File

@@ -13,7 +13,7 @@ use crate::logging_error;
use crate::utils::window_manager::WindowManager; use crate::utils::window_manager::WindowManager;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use delay_timer::prelude::TaskBuilder; use delay_timer::prelude::TaskBuilder;
use std::sync::atomic::{AtomicU32, AtomicU8, Ordering}; use std::sync::atomic::{AtomicU8, AtomicU32, Ordering};
use tauri::Listener; use tauri::Listener;
const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task"; const LIGHT_WEIGHT_TASK_UID: &str = "light_weight_task";

View File

@@ -1,6 +1,6 @@
use crate::{ use crate::{
cmd::system, cmd::system,
core::{handle, CoreManager}, core::{CoreManager, handle},
}; };
use std::fmt::{self, Debug, Formatter}; use std::fmt::{self, Debug, Formatter};
use sysinfo::System; use sysinfo::System;
@@ -20,7 +20,13 @@ impl Debug for PlatformSpecification {
write!( write!(
f, f,
"System Name: {}\nSystem Version: {}\nSystem kernel Version: {}\nSystem Arch: {}\nVerge Version: {}\nRunning Mode: {}\nIs Admin: {}", "System Name: {}\nSystem Version: {}\nSystem kernel Version: {}\nSystem Arch: {}\nVerge Version: {}\nRunning Mode: {}\nIs Admin: {}",
self.system_name, self.system_version, self.system_kernel_version, self.system_arch, self.verge_version, self.running_mode, self.is_admin self.system_name,
self.system_version,
self.system_kernel_version,
self.system_arch,
self.verge_version,
self.running_mode,
self.is_admin
) )
} }
} }

View File

@@ -67,12 +67,18 @@ impl AsyncHandler {
location.column() location.column()
); );
println!("┌────────────────────┬─────────────────────────────────────────────────────────────────────────────┐"); println!(
"┌────────────────────┬─────────────────────────────────────────────────────────────────────────────┐"
);
println!("{:<18}{:<80}", "Field", "Value"); println!("{:<18}{:<80}", "Field", "Value");
println!("├────────────────────┼─────────────────────────────────────────────────────────────────────────────┤"); println!(
"├────────────────────┼─────────────────────────────────────────────────────────────────────────────┤"
);
println!("{:<18}{:<80}", "Type of task", type_str); println!("{:<18}{:<80}", "Type of task", type_str);
println!("{:<18}{:<80}", "Size of task", size_str); println!("{:<18}{:<80}", "Size of task", size_str);
println!("{:<18}{:<80}", "Called from", loc_str); println!("{:<18}{:<80}", "Called from", loc_str);
println!("└────────────────────┴─────────────────────────────────────────────────────────────────────────────┘"); println!(
"└────────────────────┴─────────────────────────────────────────────────────────────────────────────┘"
);
} }
} }

View File

@@ -1,5 +1,5 @@
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use anyhow::{anyhow, Result}; use anyhow::{Result, anyhow};
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
use log::info; use log::info;

View File

@@ -151,14 +151,13 @@ pub fn find_target_icons(target: &str) -> Result<Option<String>> {
let entry = entry?; let entry = entry?;
let path = entry.path(); let path = entry.path();
if let Some(file_name) = path.file_name().and_then(|n| n.to_str()) { if let Some(file_name) = path.file_name().and_then(|n| n.to_str())
if file_name.starts_with(target) && file_name.starts_with(target)
&& (file_name.ends_with(".ico") || file_name.ends_with(".png")) && (file_name.ends_with(".ico") || file_name.ends_with(".png"))
{ {
matching_files.push(path); matching_files.push(path);
} }
} }
}
if matching_files.is_empty() { if matching_files.is_empty() {
Ok(None) Ok(None)

View File

@@ -1,7 +1,7 @@
use crate::{enhance::seq::SeqMap, logging, utils::logging::Type}; use crate::{enhance::seq::SeqMap, logging, utils::logging::Type};
use anyhow::{anyhow, bail, Context, Result}; use anyhow::{Context, Result, anyhow, bail};
use nanoid::nanoid; use nanoid::nanoid;
use serde::{de::DeserializeOwned, Serialize}; use serde::{Serialize, de::DeserializeOwned};
use serde_yaml_ng::Mapping; use serde_yaml_ng::Mapping;
use std::{path::PathBuf, str::FromStr}; use std::{path::PathBuf, str::FromStr};
@@ -154,10 +154,6 @@ macro_rules! ret_err {
#[macro_export] #[macro_export]
macro_rules! t { macro_rules! t {
($en:expr, $zh:expr, $use_zh:expr) => { ($en:expr, $zh:expr, $use_zh:expr) => {
if $use_zh { if $use_zh { $zh } else { $en }
$zh
} else {
$en
}
}; };
} }

View File

@@ -15,17 +15,17 @@ fn get_locales_dir() -> Option<PathBuf> {
pub fn get_supported_languages() -> Vec<String> { pub fn get_supported_languages() -> Vec<String> {
let mut languages = Vec::new(); let mut languages = Vec::new();
if let Some(locales_dir) = get_locales_dir() { if let Some(locales_dir) = get_locales_dir()
if let Ok(entries) = fs::read_dir(locales_dir) { && let Ok(entries) = fs::read_dir(locales_dir)
{
for entry in entries.flatten() { for entry in entries.flatten() {
if let Some(file_name) = entry.file_name().to_str() { if let Some(file_name) = entry.file_name().to_str()
if let Some(lang) = file_name.strip_suffix(".json") { && let Some(lang) = file_name.strip_suffix(".json")
{
languages.push(lang.to_string()); languages.push(lang.to_string());
} }
} }
} }
}
}
if languages.is_empty() { if languages.is_empty() {
languages.push(DEFAULT_LANGUAGE.to_string()); languages.push(DEFAULT_LANGUAGE.to_string());
@@ -39,13 +39,13 @@ static TRANSLATIONS: Lazy<HashMap<String, Value>> = Lazy::new(|| {
if let Some(locales_dir) = get_locales_dir() { if let Some(locales_dir) = get_locales_dir() {
for lang in get_supported_languages() { for lang in get_supported_languages() {
let file_path = locales_dir.join(format!("{lang}.json")); let file_path = locales_dir.join(format!("{lang}.json"));
if let Ok(content) = fs::read_to_string(file_path) { if let Ok(content) = fs::read_to_string(file_path)
if let Ok(json) = serde_json::from_str(&content) { && let Ok(json) = serde_json::from_str(&content)
{
translations.insert(lang.to_string(), json); translations.insert(lang.to_string(), json);
} }
} }
} }
}
translations translations
}); });
@@ -76,15 +76,14 @@ pub async fn t(key: &str) -> String {
return text.to_string(); return text.to_string();
} }
if current_lang != DEFAULT_LANGUAGE { if current_lang != DEFAULT_LANGUAGE
if let Some(text) = TRANSLATIONS && let Some(text) = TRANSLATIONS
.get(DEFAULT_LANGUAGE) .get(DEFAULT_LANGUAGE)
.and_then(|trans| trans.get(&key)) .and_then(|trans| trans.get(&key))
.and_then(|val| val.as_str()) .and_then(|val| val.as_str())
{ {
return text.to_string(); return text.to_string();
} }
}
key key
} }

View File

@@ -296,8 +296,9 @@ async fn ensure_directories() -> Result<()> {
/// 初始化配置文件 /// 初始化配置文件
async fn initialize_config_files() -> Result<()> { async fn initialize_config_files() -> Result<()> {
if let Ok(path) = dirs::clash_path() { if let Ok(path) = dirs::clash_path()
if !path.exists() { && !path.exists()
{
let template = IClashTemp::template().0; let template = IClashTemp::template().0;
help::save_yaml(&path, &template, Some("# Clash Verge")) help::save_yaml(&path, &template, Some("# Clash Verge"))
.await .await
@@ -310,10 +311,10 @@ async fn initialize_config_files() -> Result<()> {
path path
); );
} }
}
if let Ok(path) = dirs::verge_path() { if let Ok(path) = dirs::verge_path()
if !path.exists() { && !path.exists()
{
let template = IVerge::template(); let template = IVerge::template();
help::save_yaml(&path, &template, Some("# Clash Verge")) help::save_yaml(&path, &template, Some("# Clash Verge"))
.await .await
@@ -326,10 +327,10 @@ async fn initialize_config_files() -> Result<()> {
path path
); );
} }
}
if let Ok(path) = dirs::profiles_path() { if let Ok(path) = dirs::profiles_path()
if !path.exists() { && !path.exists()
{
let template = IProfiles::template(); let template = IProfiles::template();
help::save_yaml(&path, &template, Some("# Clash Verge")) help::save_yaml(&path, &template, Some("# Clash Verge"))
.await .await
@@ -342,7 +343,6 @@ async fn initialize_config_files() -> Result<()> {
path path
); );
} }
}
// 验证并修正verge配置 // 验证并修正verge配置
IVerge::validate_and_fix_config() IVerge::validate_and_fix_config()
@@ -459,7 +459,7 @@ pub async fn init_resources() -> Result<()> {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub fn init_scheme() -> Result<()> { pub fn init_scheme() -> Result<()> {
use tauri::utils::platform::current_exe; use tauri::utils::platform::current_exe;
use winreg::{enums::*, RegKey}; use winreg::{RegKey, enums::*};
let app_exe = current_exe()?; let app_exe = current_exe()?;
let app_exe = dunce::canonicalize(app_exe)?; let app_exe = dunce::canonicalize(app_exe)?;

View File

@@ -1,14 +1,14 @@
use anyhow::Result; use anyhow::Result;
use base64::{engine::general_purpose, Engine as _}; use base64::{Engine as _, engine::general_purpose};
use isahc::prelude::*; use isahc::prelude::*;
use isahc::{HttpClient, config::SslOption};
use isahc::{ use isahc::{
config::RedirectPolicy, config::RedirectPolicy,
http::{ http::{
header::{HeaderMap, HeaderValue, USER_AGENT},
StatusCode, Uri, StatusCode, Uri,
header::{HeaderMap, HeaderValue, USER_AGENT},
}, },
}; };
use isahc::{config::SslOption, HttpClient};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use sysproxy::Sysproxy; use sysproxy::Sysproxy;
use tauri::Url; use tauri::Url;
@@ -88,11 +88,12 @@ impl NetworkManager {
return true; return true;
} }
if let Some((time, _)) = &*last_error_guard { if let Some((time, _)) = &*last_error_guard
if time.elapsed() < Duration::from_secs(30) && count > 2 { && time.elapsed() < Duration::from_secs(30)
&& count > 2
{
return true; return true;
} }
}
false false
} }
@@ -113,7 +114,8 @@ impl NetworkManager {
) -> Result<HttpClient> { ) -> Result<HttpClient> {
let proxy_uri_clone = proxy_uri.clone(); let proxy_uri_clone = proxy_uri.clone();
let headers_clone = default_headers.clone(); let headers_clone = default_headers.clone();
let client = {
{
let mut builder = HttpClient::builder(); let mut builder = HttpClient::builder();
builder = match proxy_uri_clone { builder = match proxy_uri_clone {
@@ -136,9 +138,7 @@ impl NetworkManager {
builder = builder.redirect_policy(RedirectPolicy::Follow); builder = builder.redirect_policy(RedirectPolicy::Follow);
Ok(builder.build()?) Ok(builder.build()?)
}; }
client
} }
pub async fn create_request( pub async fn create_request(
@@ -200,8 +200,9 @@ impl NetworkManager {
let parsed = Url::parse(url)?; let parsed = Url::parse(url)?;
let mut extra_headers = HeaderMap::new(); let mut extra_headers = HeaderMap::new();
if !parsed.username().is_empty() { if !parsed.username().is_empty()
if let Some(pass) = parsed.password() { && let Some(pass) = parsed.password()
{
let auth_str = format!("{}:{}", parsed.username(), pass); let auth_str = format!("{}:{}", parsed.username(), pass);
let encoded = general_purpose::STANDARD.encode(auth_str); let encoded = general_purpose::STANDARD.encode(auth_str);
extra_headers.insert( extra_headers.insert(
@@ -209,7 +210,6 @@ impl NetworkManager {
HeaderValue::from_str(&format!("Basic {}", encoded))?, HeaderValue::from_str(&format!("Basic {}", encoded))?,
); );
} }
}
let clean_url = { let clean_url = {
let mut no_auth = parsed.clone(); let mut no_auth = parsed.clone();

View File

@@ -3,7 +3,7 @@ use tauri::AppHandle;
use crate::{ use crate::{
config::Config, config::Config,
core::{handle, hotkey::Hotkey, sysopt, tray::Tray, CoreManager, Timer}, core::{CoreManager, Timer, handle, hotkey::Hotkey, sysopt, tray::Tray},
logging, logging_error, logging, logging_error,
module::lightweight::auto_lightweight_mode_init, module::lightweight::auto_lightweight_mode_init,
process::AsyncHandler, process::AsyncHandler,

View File

@@ -1,4 +1,4 @@
use anyhow::{bail, Result}; use anyhow::{Result, bail};
use percent_encoding::percent_decode_str; use percent_encoding::percent_decode_str;
use tauri::Url; use tauri::Url;

View File

@@ -1,8 +1,8 @@
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use parking_lot::RwLock; use parking_lot::RwLock;
use std::sync::{ use std::sync::{
atomic::{AtomicBool, Ordering},
Arc, Arc,
atomic::{AtomicBool, Ordering},
}; };
use tokio::sync::Notify; use tokio::sync::Notify;

View File

@@ -10,7 +10,7 @@ use crate::{
utils::{ utils::{
logging::Type, logging::Type,
resolve::{ resolve::{
ui::{get_ui_ready, update_ui_ready_stage, wait_for_ui_ready, UiReadyStage}, ui::{UiReadyStage, get_ui_ready, update_ui_ready_stage, wait_for_ui_ready},
window_script::{INITIAL_LOADING_OVERLAY, WINDOW_INITIAL_SCRIPT}, window_script::{INITIAL_LOADING_OVERLAY, WINDOW_INITIAL_SCRIPT},
}, },
}, },
@@ -37,8 +37,9 @@ fn get_current_timestamp() -> u32 {
/// 检查是否已存在窗口,如果存在则显示并返回 true /// 检查是否已存在窗口,如果存在则显示并返回 true
fn check_existing_window(is_show: bool) -> Option<bool> { fn check_existing_window(is_show: bool) -> Option<bool> {
if let Some(app_handle) = handle::Handle::global().app_handle() { if let Some(app_handle) = handle::Handle::global().app_handle()
if let Some(window) = app_handle.get_webview_window("main") { && let Some(window) = app_handle.get_webview_window("main")
{
logging!(info, Type::Window, true, "主窗口已存在,将显示现有窗口"); logging!(info, Type::Window, true, "主窗口已存在,将显示现有窗口");
if is_show { if is_show {
if window.is_minimized().unwrap_or(false) { if window.is_minimized().unwrap_or(false) {
@@ -53,7 +54,6 @@ fn check_existing_window(is_show: bool) -> Option<bool> {
} }
return Some(true); return Some(true);
} }
}
None None
} }

View File

@@ -1,11 +1,11 @@
use super::resolve; use super::resolve;
use crate::{ use crate::{
config::{Config, IVerge, DEFAULT_PAC}, config::{Config, DEFAULT_PAC, IVerge},
logging_error, logging_error,
process::AsyncHandler, process::AsyncHandler,
utils::logging::Type, utils::logging::Type,
}; };
use anyhow::{bail, Result}; use anyhow::{Result, bail};
use port_scanner::local_port_available; use port_scanner::local_port_available;
use warp::Filter; use warp::Filter;