refactor: reduce clone operation (#5268)
* refactor: optimize item handling and improve profile management * refactor: update IVerge references to use references instead of owned values * refactor: update patch_verge to use data_ref for improved data handling * refactor: move handle_copy function to improve resource initialization logic * refactor: update profile handling to use references for improved memory efficiency * refactor: simplify get_item method and update profile item retrieval to use string slices * refactor: update profile validation and patching to use references for improved performance * refactor: update profile functions to use references for improved performance and memory efficiency * refactor: update profile patching functions to use references for improved memory efficiency * refactor: simplify merge function in PrfOption to enhance readability * refactor: update change_core function to accept a reference for improved memory efficiency * refactor: update PrfItem and profile functions to use references for improved memory efficiency * refactor: update resolve_scheme function to accept a reference for improved memory efficiency * refactor: update resolve_scheme function to accept a string slice for improved flexibility * refactor: simplify update_profile parameters and logic
This commit is contained in:
12
src-tauri/Cargo.lock
generated
12
src-tauri/Cargo.lock
generated
@@ -962,9 +962,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.44"
|
version = "1.2.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
|
checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
@@ -1161,8 +1161,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clash_verge_logger"
|
name = "clash_verge_logger"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/clash-verge-rev/clash-verge-logger#955f1b709890640ff01fd30009df0f35816bbca6"
|
source = "git+https://github.com/clash-verge-rev/clash-verge-logger#9bb189b5b5c4c2eee35168ff4997e8fb10901c81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arraydeque",
|
"arraydeque",
|
||||||
"compact_str",
|
"compact_str",
|
||||||
@@ -8752,9 +8752,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version-compare"
|
name = "version-compare"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
|
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
|
|||||||
@@ -41,10 +41,7 @@ pub async fn patch_clash_mode(payload: String) -> CmdResult {
|
|||||||
pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<String>> {
|
pub async fn change_clash_core(clash_core: String) -> CmdResult<Option<String>> {
|
||||||
logging!(info, Type::Config, "changing core to {clash_core}");
|
logging!(info, Type::Config, "changing core to {clash_core}");
|
||||||
|
|
||||||
match CoreManager::global()
|
match CoreManager::global().change_core(&clash_core).await {
|
||||||
.change_core(Some(clash_core.clone()))
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// 切换内核后重启内核
|
// 切换内核后重启内核
|
||||||
match CoreManager::global().restart_core().await {
|
match CoreManager::global().restart_core().await {
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ pub async fn import_profile(url: std::string::String, option: Option<PrfOption>)
|
|||||||
logging!(info, Type::Cmd, "[导入订阅] 开始导入: {}", url);
|
logging!(info, Type::Cmd, "[导入订阅] 开始导入: {}", url);
|
||||||
|
|
||||||
// 直接依赖 PrfItem::from_url 自身的超时/重试逻辑,不再使用 tokio::time::timeout 包裹
|
// 直接依赖 PrfItem::from_url 自身的超时/重试逻辑,不再使用 tokio::time::timeout 包裹
|
||||||
let item = match PrfItem::from_url(&url, None, None, option).await {
|
let item = &mut match PrfItem::from_url(&url, None, None, option.as_ref()).await {
|
||||||
Ok(it) => {
|
Ok(it) => {
|
||||||
logging!(info, Type::Cmd, "[导入订阅] 下载完成,开始保存配置");
|
logging!(info, Type::Cmd, "[导入订阅] 下载完成,开始保存配置");
|
||||||
it
|
it
|
||||||
@@ -110,7 +110,7 @@ pub async fn import_profile(url: std::string::String, option: Option<PrfOption>)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match profiles_append_item_safe(item.clone()).await {
|
match profiles_append_item_safe(item).await {
|
||||||
Ok(_) => match profiles_save_file_safe().await {
|
Ok(_) => match profiles_save_file_safe().await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
logging!(info, Type::Cmd, "[导入订阅] 配置文件保存成功");
|
logging!(info, Type::Cmd, "[导入订阅] 配置文件保存成功");
|
||||||
@@ -145,7 +145,7 @@ pub async fn import_profile(url: std::string::String, option: Option<PrfOption>)
|
|||||||
/// 调整profile的顺序
|
/// 调整profile的顺序
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn reorder_profile(active_id: String, over_id: String) -> CmdResult {
|
pub async fn reorder_profile(active_id: String, over_id: String) -> CmdResult {
|
||||||
match profiles_reorder_safe(active_id, over_id).await {
|
match profiles_reorder_safe(&active_id, &over_id).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
log::info!(target: "app", "重新排序配置文件");
|
log::info!(target: "app", "重新排序配置文件");
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -161,7 +161,7 @@ pub async fn reorder_profile(active_id: String, over_id: String) -> CmdResult {
|
|||||||
/// 创建一个新的配置文件
|
/// 创建一个新的配置文件
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResult {
|
pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResult {
|
||||||
match profiles_append_item_with_filedata_safe(item.clone(), file_data).await {
|
match profiles_append_item_with_filedata_safe(&item, file_data).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
// 发送配置变更通知
|
// 发送配置变更通知
|
||||||
if let Some(uid) = &item.uid {
|
if let Some(uid) = &item.uid {
|
||||||
@@ -180,7 +180,7 @@ pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResu
|
|||||||
/// 更新配置文件
|
/// 更新配置文件
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn update_profile(index: String, option: Option<PrfOption>) -> CmdResult {
|
pub async fn update_profile(index: String, option: Option<PrfOption>) -> CmdResult {
|
||||||
match feat::update_profile(index, option, Some(true), Some(true)).await {
|
match feat::update_profile(&index, option.as_ref(), true, true).await {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!(target: "app", "{}", e);
|
log::error!(target: "app", "{}", e);
|
||||||
@@ -194,9 +194,7 @@ pub async fn update_profile(index: String, option: Option<PrfOption>) -> CmdResu
|
|||||||
pub async fn delete_profile(index: String) -> CmdResult {
|
pub async fn delete_profile(index: String) -> CmdResult {
|
||||||
println!("delete_profile: {}", index);
|
println!("delete_profile: {}", index);
|
||||||
// 使用Send-safe helper函数
|
// 使用Send-safe helper函数
|
||||||
let should_update = profiles_delete_item_safe(index.clone())
|
let should_update = profiles_delete_item_safe(&index).await.stringify_err()?;
|
||||||
.await
|
|
||||||
.stringify_err()?;
|
|
||||||
profiles_save_file_safe().await.stringify_err()?;
|
profiles_save_file_safe().await.stringify_err()?;
|
||||||
|
|
||||||
if should_update {
|
if should_update {
|
||||||
@@ -585,7 +583,7 @@ pub async fn patch_profile(index: String, profile: PrfItem) -> CmdResult {
|
|||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
profiles_patch_item_safe(index.clone(), profile)
|
profiles_patch_item_safe(&index, &profile)
|
||||||
.await
|
.await
|
||||||
.stringify_err()?;
|
.stringify_err()?;
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ async fn handle_full_validation(
|
|||||||
Type::Config,
|
Type::Config,
|
||||||
"[cmd配置save] YAML配置文件验证失败,发送通知"
|
"[cmd配置save] YAML配置文件验证失败,发送通知"
|
||||||
);
|
);
|
||||||
let result = (false, error_msg.clone());
|
let result = (false, error_msg.to_owned());
|
||||||
crate::cmd::validate::handle_yaml_validation_notice(&result, "YAML配置文件");
|
crate::cmd::validate::handle_yaml_validation_notice(&result, "YAML配置文件");
|
||||||
} else if is_script_error(&error_msg, file_path_str) {
|
} else if is_script_error(&error_msg, file_path_str) {
|
||||||
logging!(
|
logging!(
|
||||||
@@ -149,7 +149,7 @@ async fn handle_full_validation(
|
|||||||
Type::Config,
|
Type::Config,
|
||||||
"[cmd配置save] 脚本文件验证失败,发送通知"
|
"[cmd配置save] 脚本文件验证失败,发送通知"
|
||||||
);
|
);
|
||||||
let result = (false, error_msg.clone());
|
let result = (false, error_msg.to_owned());
|
||||||
crate::cmd::validate::handle_script_validation_notice(&result, "脚本文件");
|
crate::cmd::validate::handle_script_validation_notice(&result, "脚本文件");
|
||||||
} else {
|
} else {
|
||||||
logging!(
|
logging!(
|
||||||
|
|||||||
@@ -9,12 +9,12 @@ pub async fn get_verge_config() -> CmdResult<IVergeResponse> {
|
|||||||
let ref_data = verge.latest_ref();
|
let ref_data = verge.latest_ref();
|
||||||
ref_data.clone()
|
ref_data.clone()
|
||||||
};
|
};
|
||||||
let verge_response = IVergeResponse::from(*verge_data);
|
let verge_response = IVergeResponse::from(verge_data);
|
||||||
Ok(verge_response)
|
Ok(verge_response)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 修改Verge配置
|
/// 修改Verge配置
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn patch_verge_config(payload: IVerge) -> CmdResult {
|
pub async fn patch_verge_config(payload: IVerge) -> CmdResult {
|
||||||
feat::patch_verge(payload, false).await.stringify_err()
|
feat::patch_verge(&payload, false).await.stringify_err()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,7 @@ pub async fn save_webdav_config(url: String, username: String, password: String)
|
|||||||
webdav_password: Some(password),
|
webdav_password: Some(password),
|
||||||
..IVerge::default()
|
..IVerge::default()
|
||||||
};
|
};
|
||||||
Config::verge()
|
Config::verge().await.draft_mut().patch_config(&patch);
|
||||||
.await
|
|
||||||
.draft_mut()
|
|
||||||
.patch_config(patch.clone());
|
|
||||||
Config::verge().await.apply();
|
Config::verge().await.apply();
|
||||||
|
|
||||||
// 分离数据获取和异步调用
|
// 分离数据获取和异步调用
|
||||||
|
|||||||
@@ -83,13 +83,13 @@ impl Config {
|
|||||||
// Ensure "Merge" and "Script" profile items exist, adding them if missing.
|
// Ensure "Merge" and "Script" profile items exist, adding them if missing.
|
||||||
async fn ensure_default_profile_items() -> Result<()> {
|
async fn ensure_default_profile_items() -> Result<()> {
|
||||||
let profiles = Self::profiles().await;
|
let profiles = Self::profiles().await;
|
||||||
if profiles.latest_ref().get_item(&"Merge".into()).is_err() {
|
if profiles.latest_ref().get_item("Merge").is_err() {
|
||||||
let merge_item = PrfItem::from_merge(Some("Merge".into()))?;
|
let merge_item = &mut PrfItem::from_merge(Some("Merge".into()))?;
|
||||||
profiles_append_item_safe(merge_item.clone()).await?;
|
profiles_append_item_safe(merge_item).await?;
|
||||||
}
|
}
|
||||||
if profiles.latest_ref().get_item(&"Script".into()).is_err() {
|
if profiles.latest_ref().get_item("Script").is_err() {
|
||||||
let script_item = PrfItem::from_script(Some("Script".into()))?;
|
let script_item = &mut PrfItem::from_script(Some("Script".into()))?;
|
||||||
profiles_append_item_safe(script_item.clone()).await?;
|
profiles_append_item_safe(script_item).await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
use crate::utils::{
|
use crate::{
|
||||||
|
config::profiles,
|
||||||
|
utils::{
|
||||||
dirs, help,
|
dirs, help,
|
||||||
network::{NetworkManager, ProxyType},
|
network::{NetworkManager, ProxyType},
|
||||||
tmpl,
|
tmpl,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -119,26 +122,29 @@ pub struct PrfOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PrfOption {
|
impl PrfOption {
|
||||||
pub fn merge(one: Option<Self>, other: Option<Self>) -> Option<Self> {
|
pub fn merge(one: Option<&Self>, other: Option<&Self>) -> Option<Self> {
|
||||||
match (one, other) {
|
match (one, other) {
|
||||||
(Some(mut a), Some(b)) => {
|
(Some(a_ref), Some(b_ref)) => {
|
||||||
a.user_agent = b.user_agent.or(a.user_agent);
|
let mut result = a_ref.clone();
|
||||||
a.with_proxy = b.with_proxy.or(a.with_proxy);
|
result.user_agent = b_ref.user_agent.clone().or(result.user_agent);
|
||||||
a.self_proxy = b.self_proxy.or(a.self_proxy);
|
result.with_proxy = b_ref.with_proxy.or(result.with_proxy);
|
||||||
a.danger_accept_invalid_certs = b
|
result.self_proxy = b_ref.self_proxy.or(result.self_proxy);
|
||||||
|
result.danger_accept_invalid_certs = b_ref
|
||||||
.danger_accept_invalid_certs
|
.danger_accept_invalid_certs
|
||||||
.or(a.danger_accept_invalid_certs);
|
.or(result.danger_accept_invalid_certs);
|
||||||
a.allow_auto_update = b.allow_auto_update.or(a.allow_auto_update);
|
result.allow_auto_update = b_ref.allow_auto_update.or(result.allow_auto_update);
|
||||||
a.update_interval = b.update_interval.or(a.update_interval);
|
result.update_interval = b_ref.update_interval.or(result.update_interval);
|
||||||
a.merge = b.merge.or(a.merge);
|
result.merge = b_ref.merge.clone().or(result.merge);
|
||||||
a.script = b.script.or(a.script);
|
result.script = b_ref.script.clone().or(result.script);
|
||||||
a.rules = b.rules.or(a.rules);
|
result.rules = b_ref.rules.clone().or(result.rules);
|
||||||
a.proxies = b.proxies.or(a.proxies);
|
result.proxies = b_ref.proxies.clone().or(result.proxies);
|
||||||
a.groups = b.groups.or(a.groups);
|
result.groups = b_ref.groups.clone().or(result.groups);
|
||||||
a.timeout_seconds = b.timeout_seconds.or(a.timeout_seconds);
|
result.timeout_seconds = b_ref.timeout_seconds.or(result.timeout_seconds);
|
||||||
Some(a)
|
Some(result)
|
||||||
}
|
}
|
||||||
t => t.0.or(t.1),
|
(Some(a_ref), None) => Some(a_ref.clone()),
|
||||||
|
(None, Some(b_ref)) => Some(b_ref.clone()),
|
||||||
|
(None, None) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,13 +152,14 @@ impl PrfOption {
|
|||||||
impl PrfItem {
|
impl PrfItem {
|
||||||
/// From partial item
|
/// From partial item
|
||||||
/// must contain `itype`
|
/// must contain `itype`
|
||||||
pub async fn from(item: PrfItem, file_data: Option<String>) -> Result<PrfItem> {
|
pub async fn from(item: &PrfItem, file_data: Option<String>) -> Result<PrfItem> {
|
||||||
if item.itype.is_none() {
|
if item.itype.is_none() {
|
||||||
bail!("type should not be null");
|
bail!("type should not be null");
|
||||||
}
|
}
|
||||||
|
|
||||||
let itype = item
|
let itype = item
|
||||||
.itype
|
.itype
|
||||||
|
.as_ref()
|
||||||
.ok_or_else(|| anyhow::anyhow!("type should not be null"))?;
|
.ok_or_else(|| anyhow::anyhow!("type should not be null"))?;
|
||||||
match itype.as_str() {
|
match itype.as_str() {
|
||||||
"remote" => {
|
"remote" => {
|
||||||
@@ -160,14 +167,16 @@ impl PrfItem {
|
|||||||
.url
|
.url
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| anyhow::anyhow!("url should not be null"))?;
|
.ok_or_else(|| anyhow::anyhow!("url should not be null"))?;
|
||||||
let name = item.name;
|
let name = item.name.as_ref();
|
||||||
let desc = item.desc;
|
let desc = item.desc.as_ref();
|
||||||
PrfItem::from_url(url, name, desc, item.option).await
|
let option = item.option.as_ref();
|
||||||
|
PrfItem::from_url(url, name, desc, option).await
|
||||||
}
|
}
|
||||||
"local" => {
|
"local" => {
|
||||||
let name = item.name.unwrap_or_else(|| "Local File".into());
|
let name = item.name.clone().unwrap_or_else(|| "Local File".into());
|
||||||
let desc = item.desc.unwrap_or_else(|| "".into());
|
let desc = item.desc.clone().unwrap_or_else(|| "".into());
|
||||||
PrfItem::from_local(name, desc, file_data, item.option).await
|
let option = item.option.as_ref();
|
||||||
|
PrfItem::from_local(name, desc, file_data, option).await
|
||||||
}
|
}
|
||||||
typ => bail!("invalid profile item type \"{typ}\""),
|
typ => bail!("invalid profile item type \"{typ}\""),
|
||||||
}
|
}
|
||||||
@@ -179,7 +188,7 @@ impl PrfItem {
|
|||||||
name: String,
|
name: String,
|
||||||
desc: String,
|
desc: String,
|
||||||
file_data: Option<String>,
|
file_data: Option<String>,
|
||||||
option: Option<PrfOption>,
|
option: Option<&PrfOption>,
|
||||||
) -> Result<PrfItem> {
|
) -> Result<PrfItem> {
|
||||||
let uid = help::get_uid("L").into();
|
let uid = help::get_uid("L").into();
|
||||||
let file = format!("{uid}.yaml").into();
|
let file = format!("{uid}.yaml").into();
|
||||||
@@ -192,29 +201,29 @@ impl PrfItem {
|
|||||||
let mut groups = opt_ref.and_then(|o| o.groups.clone());
|
let mut groups = opt_ref.and_then(|o| o.groups.clone());
|
||||||
|
|
||||||
if merge.is_none() {
|
if merge.is_none() {
|
||||||
let merge_item = PrfItem::from_merge(None)?;
|
let merge_item = &mut PrfItem::from_merge(None)?;
|
||||||
crate::config::profiles::profiles_append_item_safe(merge_item.clone()).await?;
|
profiles::profiles_append_item_safe(merge_item).await?;
|
||||||
merge = merge_item.uid;
|
merge = merge_item.uid.clone();
|
||||||
}
|
}
|
||||||
if script.is_none() {
|
if script.is_none() {
|
||||||
let script_item = PrfItem::from_script(None)?;
|
let script_item = &mut PrfItem::from_script(None)?;
|
||||||
crate::config::profiles::profiles_append_item_safe(script_item.clone()).await?;
|
profiles::profiles_append_item_safe(script_item).await?;
|
||||||
script = script_item.uid;
|
script = script_item.uid.clone();
|
||||||
}
|
}
|
||||||
if rules.is_none() {
|
if rules.is_none() {
|
||||||
let rules_item = PrfItem::from_rules()?;
|
let rules_item = &mut PrfItem::from_rules()?;
|
||||||
crate::config::profiles::profiles_append_item_safe(rules_item.clone()).await?;
|
profiles::profiles_append_item_safe(rules_item).await?;
|
||||||
rules = rules_item.uid;
|
rules = rules_item.uid.clone();
|
||||||
}
|
}
|
||||||
if proxies.is_none() {
|
if proxies.is_none() {
|
||||||
let proxies_item = PrfItem::from_proxies()?;
|
let proxies_item = &mut PrfItem::from_proxies()?;
|
||||||
crate::config::profiles::profiles_append_item_safe(proxies_item.clone()).await?;
|
profiles::profiles_append_item_safe(proxies_item).await?;
|
||||||
proxies = proxies_item.uid;
|
proxies = proxies_item.uid.clone();
|
||||||
}
|
}
|
||||||
if groups.is_none() {
|
if groups.is_none() {
|
||||||
let groups_item = PrfItem::from_groups()?;
|
let groups_item = &mut PrfItem::from_groups()?;
|
||||||
crate::config::profiles::profiles_append_item_safe(groups_item.clone()).await?;
|
profiles::profiles_append_item_safe(groups_item).await?;
|
||||||
groups = groups_item.uid;
|
groups = groups_item.uid.clone();
|
||||||
}
|
}
|
||||||
Ok(PrfItem {
|
Ok(PrfItem {
|
||||||
uid: Some(uid),
|
uid: Some(uid),
|
||||||
@@ -244,24 +253,23 @@ impl PrfItem {
|
|||||||
/// create a new item from url
|
/// create a new item from url
|
||||||
pub async fn from_url(
|
pub async fn from_url(
|
||||||
url: &str,
|
url: &str,
|
||||||
name: Option<String>,
|
name: Option<&String>,
|
||||||
desc: Option<String>,
|
desc: Option<&String>,
|
||||||
option: Option<PrfOption>,
|
option: Option<&PrfOption>,
|
||||||
) -> Result<PrfItem> {
|
) -> Result<PrfItem> {
|
||||||
let opt_ref = option.as_ref();
|
let with_proxy = option.is_some_and(|o| o.with_proxy.unwrap_or(false));
|
||||||
let with_proxy = opt_ref.is_some_and(|o| o.with_proxy.unwrap_or(false));
|
let self_proxy = option.is_some_and(|o| o.self_proxy.unwrap_or(false));
|
||||||
let self_proxy = opt_ref.is_some_and(|o| o.self_proxy.unwrap_or(false));
|
|
||||||
let accept_invalid_certs =
|
let accept_invalid_certs =
|
||||||
opt_ref.is_some_and(|o| o.danger_accept_invalid_certs.unwrap_or(false));
|
option.is_some_and(|o| o.danger_accept_invalid_certs.unwrap_or(false));
|
||||||
let allow_auto_update = opt_ref.map(|o| o.allow_auto_update.unwrap_or(true));
|
let allow_auto_update = option.map(|o| o.allow_auto_update.unwrap_or(true));
|
||||||
let user_agent = opt_ref.and_then(|o| o.user_agent.clone());
|
let user_agent = option.and_then(|o| o.user_agent.clone());
|
||||||
let update_interval = opt_ref.and_then(|o| o.update_interval);
|
let update_interval = option.and_then(|o| o.update_interval);
|
||||||
let timeout = opt_ref.and_then(|o| o.timeout_seconds).unwrap_or(20);
|
let timeout = option.and_then(|o| o.timeout_seconds).unwrap_or(20);
|
||||||
let mut merge = opt_ref.and_then(|o| o.merge.clone());
|
let mut merge = option.and_then(|o| o.merge.clone());
|
||||||
let mut script = opt_ref.and_then(|o| o.script.clone());
|
let mut script = option.and_then(|o| o.script.clone());
|
||||||
let mut rules = opt_ref.and_then(|o| o.rules.clone());
|
let mut rules = option.and_then(|o| o.rules.clone());
|
||||||
let mut proxies = opt_ref.and_then(|o| o.proxies.clone());
|
let mut proxies = option.and_then(|o| o.proxies.clone());
|
||||||
let mut groups = opt_ref.and_then(|o| o.groups.clone());
|
let mut groups = option.and_then(|o| o.groups.clone());
|
||||||
|
|
||||||
// 选择代理类型
|
// 选择代理类型
|
||||||
let proxy_type = if self_proxy {
|
let proxy_type = if self_proxy {
|
||||||
@@ -366,7 +374,11 @@ impl PrfItem {
|
|||||||
|
|
||||||
let uid = help::get_uid("R").into();
|
let uid = help::get_uid("R").into();
|
||||||
let file = format!("{uid}.yaml").into();
|
let file = format!("{uid}.yaml").into();
|
||||||
let name = name.unwrap_or_else(|| filename.unwrap_or_else(|| "Remote File".into()).into());
|
let name = name.map(|s| s.to_owned()).unwrap_or_else(|| {
|
||||||
|
filename
|
||||||
|
.map(|s| s.into())
|
||||||
|
.unwrap_or_else(|| "Remote File".into())
|
||||||
|
});
|
||||||
let data = resp.text_with_charset()?;
|
let data = resp.text_with_charset()?;
|
||||||
|
|
||||||
// process the charset "UTF-8 with BOM"
|
// process the charset "UTF-8 with BOM"
|
||||||
@@ -381,36 +393,36 @@ impl PrfItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if merge.is_none() {
|
if merge.is_none() {
|
||||||
let merge_item = PrfItem::from_merge(None)?;
|
let merge_item = &mut PrfItem::from_merge(None)?;
|
||||||
crate::config::profiles::profiles_append_item_safe(merge_item.clone()).await?;
|
profiles::profiles_append_item_safe(merge_item).await?;
|
||||||
merge = merge_item.uid;
|
merge = merge_item.uid.clone();
|
||||||
}
|
}
|
||||||
if script.is_none() {
|
if script.is_none() {
|
||||||
let script_item = PrfItem::from_script(None)?;
|
let script_item = &mut PrfItem::from_script(None)?;
|
||||||
crate::config::profiles::profiles_append_item_safe(script_item.clone()).await?;
|
profiles::profiles_append_item_safe(script_item).await?;
|
||||||
script = script_item.uid;
|
script = script_item.uid.clone();
|
||||||
}
|
}
|
||||||
if rules.is_none() {
|
if rules.is_none() {
|
||||||
let rules_item = PrfItem::from_rules()?;
|
let rules_item = &mut PrfItem::from_rules()?;
|
||||||
crate::config::profiles::profiles_append_item_safe(rules_item.clone()).await?;
|
profiles::profiles_append_item_safe(rules_item).await?;
|
||||||
rules = rules_item.uid;
|
rules = rules_item.uid.clone();
|
||||||
}
|
}
|
||||||
if proxies.is_none() {
|
if proxies.is_none() {
|
||||||
let proxies_item = PrfItem::from_proxies()?;
|
let proxies_item = &mut PrfItem::from_proxies()?;
|
||||||
crate::config::profiles::profiles_append_item_safe(proxies_item.clone()).await?;
|
profiles::profiles_append_item_safe(proxies_item).await?;
|
||||||
proxies = proxies_item.uid;
|
proxies = proxies_item.uid.clone();
|
||||||
}
|
}
|
||||||
if groups.is_none() {
|
if groups.is_none() {
|
||||||
let groups_item = PrfItem::from_groups()?;
|
let groups_item = &mut PrfItem::from_groups()?;
|
||||||
crate::config::profiles::profiles_append_item_safe(groups_item.clone()).await?;
|
profiles::profiles_append_item_safe(groups_item).await?;
|
||||||
groups = groups_item.uid;
|
groups = groups_item.uid.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(PrfItem {
|
Ok(PrfItem {
|
||||||
uid: Some(uid),
|
uid: Some(uid),
|
||||||
itype: Some("remote".into()),
|
itype: Some("remote".into()),
|
||||||
name: Some(name),
|
name: Some(name),
|
||||||
desc,
|
desc: desc.cloned(),
|
||||||
file: Some(file),
|
file: Some(file),
|
||||||
url: Some(url.into()),
|
url: Some(url.into()),
|
||||||
selected: None,
|
selected: None,
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ pub struct CleanupResult {
|
|||||||
macro_rules! patch {
|
macro_rules! patch {
|
||||||
($lv: expr, $rv: expr, $key: tt) => {
|
($lv: expr, $rv: expr, $key: tt) => {
|
||||||
if ($rv.$key).is_some() {
|
if ($rv.$key).is_some() {
|
||||||
$lv.$key = $rv.$key;
|
$lv.$key = $rv.$key.clone();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -122,28 +122,30 @@ impl IProfiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// find the item by the uid
|
/// find the item by the uid
|
||||||
pub fn get_item(&self, uid: &String) -> Result<&PrfItem> {
|
pub fn get_item(&self, uid: impl AsRef<str>) -> Result<&PrfItem> {
|
||||||
if let Some(items) = self.items.as_ref() {
|
let uid_str = uid.as_ref();
|
||||||
let some_uid = Some(uid.clone());
|
|
||||||
|
|
||||||
|
if let Some(items) = self.items.as_ref() {
|
||||||
for each in items.iter() {
|
for each in items.iter() {
|
||||||
if each.uid == some_uid {
|
if let Some(uid_val) = &each.uid
|
||||||
|
&& uid_val.as_str() == uid_str
|
||||||
|
{
|
||||||
return Ok(each);
|
return Ok(each);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bail!("failed to get the profile item \"uid:{uid}\"");
|
bail!("failed to get the profile item \"uid:{}\"", uid_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// append new item
|
/// append new item
|
||||||
/// if the file_data is some
|
/// if the file_data is some
|
||||||
/// then should save the data to file
|
/// then should save the data to file
|
||||||
pub async fn append_item(&mut self, mut item: PrfItem) -> Result<()> {
|
pub async fn append_item(&mut self, item: &mut PrfItem) -> Result<()> {
|
||||||
if item.uid.is_none() {
|
let uid = &item.uid;
|
||||||
|
if uid.is_none() {
|
||||||
bail!("the uid should not be null");
|
bail!("the uid should not be null");
|
||||||
}
|
}
|
||||||
let uid = item.uid.clone();
|
|
||||||
|
|
||||||
// save the file data
|
// save the file data
|
||||||
// move the field value after save
|
// move the field value after save
|
||||||
@@ -165,7 +167,7 @@ impl IProfiles {
|
|||||||
if self.current.is_none()
|
if self.current.is_none()
|
||||||
&& (item.itype == Some("remote".into()) || item.itype == Some("local".into()))
|
&& (item.itype == Some("remote".into()) || item.itype == Some("local".into()))
|
||||||
{
|
{
|
||||||
self.current = uid;
|
self.current = uid.to_owned();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.items.is_none() {
|
if self.items.is_none() {
|
||||||
@@ -173,24 +175,23 @@ impl IProfiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(items) = self.items.as_mut() {
|
if let Some(items) = self.items.as_mut() {
|
||||||
items.push(item)
|
items.push(item.to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
// self.save_file().await
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// reorder items
|
/// reorder items
|
||||||
pub async fn reorder(&mut self, active_id: String, over_id: String) -> Result<()> {
|
pub async fn reorder(&mut self, active_id: &String, over_id: &String) -> Result<()> {
|
||||||
let mut items = self.items.take().unwrap_or_default();
|
let mut items = self.items.take().unwrap_or_default();
|
||||||
let mut old_index = None;
|
let mut old_index = None;
|
||||||
let mut new_index = None;
|
let mut new_index = None;
|
||||||
|
|
||||||
for (i, _) in items.iter().enumerate() {
|
for (i, _) in items.iter().enumerate() {
|
||||||
if items[i].uid == Some(active_id.clone()) {
|
if items[i].uid.as_ref() == Some(active_id) {
|
||||||
old_index = Some(i);
|
old_index = Some(i);
|
||||||
}
|
}
|
||||||
if items[i].uid == Some(over_id.clone()) {
|
if items[i].uid.as_ref() == Some(over_id) {
|
||||||
new_index = Some(i);
|
new_index = Some(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,11 +207,11 @@ impl IProfiles {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// update the item value
|
/// update the item value
|
||||||
pub async fn patch_item(&mut self, uid: String, item: PrfItem) -> Result<()> {
|
pub async fn patch_item(&mut self, uid: &String, item: &PrfItem) -> Result<()> {
|
||||||
let mut items = self.items.take().unwrap_or_default();
|
let mut items = self.items.take().unwrap_or_default();
|
||||||
|
|
||||||
for each in items.iter_mut() {
|
for each in items.iter_mut() {
|
||||||
if each.uid == Some(uid.clone()) {
|
if each.uid.as_ref() == Some(uid) {
|
||||||
patch!(each, item, itype);
|
patch!(each, item, itype);
|
||||||
patch!(each, item, name);
|
patch!(each, item, name);
|
||||||
patch!(each, item, desc);
|
patch!(each, item, desc);
|
||||||
@@ -232,13 +233,13 @@ impl IProfiles {
|
|||||||
|
|
||||||
/// be used to update the remote item
|
/// be used to update the remote item
|
||||||
/// only patch `updated` `extra` `file_data`
|
/// only patch `updated` `extra` `file_data`
|
||||||
pub async fn update_item(&mut self, uid: String, mut item: PrfItem) -> Result<()> {
|
pub async fn update_item(&mut self, uid: &String, item: &mut PrfItem) -> Result<()> {
|
||||||
if self.items.is_none() {
|
if self.items.is_none() {
|
||||||
self.items = Some(vec![]);
|
self.items = Some(vec![]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the item
|
// find the item
|
||||||
let _ = self.get_item(&uid)?;
|
let _ = self.get_item(uid)?;
|
||||||
|
|
||||||
if let Some(items) = self.items.as_mut() {
|
if let Some(items) = self.items.as_mut() {
|
||||||
let some_uid = Some(uid.clone());
|
let some_uid = Some(uid.clone());
|
||||||
@@ -247,8 +248,8 @@ impl IProfiles {
|
|||||||
if each.uid == some_uid {
|
if each.uid == some_uid {
|
||||||
each.extra = item.extra;
|
each.extra = item.extra;
|
||||||
each.updated = item.updated;
|
each.updated = item.updated;
|
||||||
each.home = item.home;
|
each.home = item.home.to_owned();
|
||||||
each.option = PrfOption::merge(each.option.clone(), item.option);
|
each.option = PrfOption::merge(each.option.as_ref(), item.option.as_ref());
|
||||||
// save the file data
|
// save the file data
|
||||||
// move the field value after save
|
// move the field value after save
|
||||||
if let Some(file_data) = item.file_data.take() {
|
if let Some(file_data) = item.file_data.take() {
|
||||||
@@ -279,10 +280,10 @@ impl IProfiles {
|
|||||||
|
|
||||||
/// delete item
|
/// delete item
|
||||||
/// if delete the current then return true
|
/// if delete the current then return true
|
||||||
pub async fn delete_item(&mut self, uid: String) -> Result<bool> {
|
pub async fn delete_item(&mut self, uid: &String) -> Result<bool> {
|
||||||
let current = self.current.as_ref().unwrap_or(&uid);
|
let current = self.current.as_ref().unwrap_or(uid);
|
||||||
let current = current.clone();
|
let current = current.clone();
|
||||||
let item = self.get_item(&uid)?;
|
let item = self.get_item(uid)?;
|
||||||
let merge_uid = item.option.as_ref().and_then(|e| e.merge.clone());
|
let merge_uid = item.option.as_ref().and_then(|e| e.merge.clone());
|
||||||
let script_uid = item.option.as_ref().and_then(|e| e.script.clone());
|
let script_uid = item.option.as_ref().and_then(|e| e.script.clone());
|
||||||
let rules_uid = item.option.as_ref().and_then(|e| e.rules.clone());
|
let rules_uid = item.option.as_ref().and_then(|e| e.rules.clone());
|
||||||
@@ -330,7 +331,7 @@ impl IProfiles {
|
|||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
// delete the original uid
|
// delete the original uid
|
||||||
if current == uid {
|
if current == *uid {
|
||||||
self.current = None;
|
self.current = None;
|
||||||
for item in items.iter() {
|
for item in items.iter() {
|
||||||
if item.itype == Some("remote".into()) || item.itype == Some("local".into()) {
|
if item.itype == Some("remote".into()) || item.itype == Some("local".into()) {
|
||||||
@@ -342,7 +343,7 @@ impl IProfiles {
|
|||||||
|
|
||||||
self.items = Some(items);
|
self.items = Some(items);
|
||||||
self.save_file().await?;
|
self.save_file().await?;
|
||||||
Ok(current == uid)
|
Ok(current == *uid)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 获取current指向的订阅内容
|
/// 获取current指向的订阅内容
|
||||||
@@ -626,14 +627,14 @@ impl IProfiles {
|
|||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
|
|
||||||
pub async fn profiles_append_item_with_filedata_safe(
|
pub async fn profiles_append_item_with_filedata_safe(
|
||||||
item: PrfItem,
|
item: &PrfItem,
|
||||||
file_data: Option<String>,
|
file_data: Option<String>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let item = PrfItem::from(item, file_data).await?;
|
let item = &mut PrfItem::from(item, file_data).await?;
|
||||||
profiles_append_item_safe(item).await
|
profiles_append_item_safe(item).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn profiles_append_item_safe(item: PrfItem) -> Result<()> {
|
pub async fn profiles_append_item_safe(item: &mut PrfItem) -> Result<()> {
|
||||||
Config::profiles()
|
Config::profiles()
|
||||||
.await
|
.await
|
||||||
.with_data_modify(|mut profiles| async move {
|
.with_data_modify(|mut profiles| async move {
|
||||||
@@ -643,7 +644,7 @@ pub async fn profiles_append_item_safe(item: PrfItem) -> Result<()> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn profiles_patch_item_safe(index: String, item: PrfItem) -> Result<()> {
|
pub async fn profiles_patch_item_safe(index: &String, item: &PrfItem) -> Result<()> {
|
||||||
Config::profiles()
|
Config::profiles()
|
||||||
.await
|
.await
|
||||||
.with_data_modify(|mut profiles| async move {
|
.with_data_modify(|mut profiles| async move {
|
||||||
@@ -653,7 +654,7 @@ pub async fn profiles_patch_item_safe(index: String, item: PrfItem) -> Result<()
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn profiles_delete_item_safe(index: String) -> Result<bool> {
|
pub async fn profiles_delete_item_safe(index: &String) -> Result<bool> {
|
||||||
Config::profiles()
|
Config::profiles()
|
||||||
.await
|
.await
|
||||||
.with_data_modify(|mut profiles| async move {
|
.with_data_modify(|mut profiles| async move {
|
||||||
@@ -663,7 +664,7 @@ pub async fn profiles_delete_item_safe(index: String) -> Result<bool> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn profiles_reorder_safe(active_id: String, over_id: String) -> Result<()> {
|
pub async fn profiles_reorder_safe(active_id: &String, over_id: &String) -> Result<()> {
|
||||||
Config::profiles()
|
Config::profiles()
|
||||||
.await
|
.await
|
||||||
.with_data_modify(|mut profiles| async move {
|
.with_data_modify(|mut profiles| async move {
|
||||||
@@ -683,7 +684,7 @@ pub async fn profiles_save_file_safe() -> Result<()> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn profiles_draft_update_item_safe(index: String, item: PrfItem) -> Result<()> {
|
pub async fn profiles_draft_update_item_safe(index: &String, item: &mut PrfItem) -> Result<()> {
|
||||||
Config::profiles()
|
Config::profiles()
|
||||||
.await
|
.await
|
||||||
.with_data_modify(|mut profiles| async move {
|
.with_data_modify(|mut profiles| async move {
|
||||||
|
|||||||
@@ -437,11 +437,11 @@ impl IVerge {
|
|||||||
/// patch verge config
|
/// patch verge config
|
||||||
/// only save to file
|
/// only save to file
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
pub fn patch_config(&mut self, patch: IVerge) {
|
pub fn patch_config(&mut self, patch: &IVerge) {
|
||||||
macro_rules! patch {
|
macro_rules! patch {
|
||||||
($key: tt) => {
|
($key: tt) => {
|
||||||
if patch.$key.is_some() {
|
if patch.$key.is_some() {
|
||||||
self.$key = patch.$key;
|
self.$key = patch.$key.clone();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -696,3 +696,9 @@ impl From<IVerge> for IVergeResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Box<IVerge>> for IVergeResponse {
|
||||||
|
fn from(verge: Box<IVerge>) -> Self {
|
||||||
|
IVergeResponse::from(*verge)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::{CoreManager, RunningMode};
|
use super::{CoreManager, RunningMode};
|
||||||
|
use crate::config::{Config, ConfigType, IVerge};
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
logger::CLASH_LOGGER,
|
logger::CLASH_LOGGER,
|
||||||
@@ -41,18 +42,12 @@ impl CoreManager {
|
|||||||
self.start_core().await
|
self.start_core().await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn change_core(&self, clash_core: Option<String>) -> Result<(), String> {
|
pub async fn change_core(&self, clash_core: &String) -> Result<(), String> {
|
||||||
use crate::config::{Config, ConfigType, IVerge};
|
if !IVerge::VALID_CLASH_CORES.contains(&clash_core.as_str()) {
|
||||||
|
return Err(format!("Invalid clash core: {}", clash_core).into());
|
||||||
let core = clash_core
|
|
||||||
.as_ref()
|
|
||||||
.ok_or_else(|| "Clash core cannot be None".to_string())?;
|
|
||||||
|
|
||||||
if !IVerge::VALID_CLASH_CORES.contains(&core.as_str()) {
|
|
||||||
return Err(format!("Invalid clash core: {}", core).into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::verge().await.draft_mut().clash_core = clash_core;
|
Config::verge().await.draft_mut().clash_core = clash_core.to_owned().into();
|
||||||
Config::verge().await.apply();
|
Config::verge().await.apply();
|
||||||
|
|
||||||
let verge_data = Config::verge().await.latest_ref().clone();
|
let verge_data = Config::verge().await.latest_ref().clone();
|
||||||
|
|||||||
@@ -390,7 +390,7 @@ impl Timer {
|
|||||||
.spawn_async_routine(move || {
|
.spawn_async_routine(move || {
|
||||||
let uid = uid.clone();
|
let uid = uid.clone();
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
Self::async_task(uid).await;
|
Self::async_task(&uid).await;
|
||||||
}) as Pin<Box<dyn std::future::Future<Output = ()> + Send>>
|
}) as Pin<Box<dyn std::future::Future<Output = ()> + Send>>
|
||||||
})
|
})
|
||||||
.context("failed to create timer task")?;
|
.context("failed to create timer task")?;
|
||||||
@@ -476,14 +476,14 @@ impl Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Async task with better error handling and logging
|
/// Async task with better error handling and logging
|
||||||
async fn async_task(uid: String) {
|
async fn async_task(uid: &String) {
|
||||||
let task_start = std::time::Instant::now();
|
let task_start = std::time::Instant::now();
|
||||||
logging!(info, Type::Timer, "Running timer task for profile: {}", uid);
|
logging!(info, Type::Timer, "Running timer task for profile: {}", uid);
|
||||||
|
|
||||||
match tokio::time::timeout(std::time::Duration::from_secs(40), async {
|
match tokio::time::timeout(std::time::Duration::from_secs(40), async {
|
||||||
Self::emit_update_event(&uid, true);
|
Self::emit_update_event(uid, true);
|
||||||
|
|
||||||
let is_current = Config::profiles().await.latest_ref().current.as_ref() == Some(&uid);
|
let is_current = Config::profiles().await.latest_ref().current.as_ref() == Some(uid);
|
||||||
logging!(
|
logging!(
|
||||||
info,
|
info,
|
||||||
Type::Timer,
|
Type::Timer,
|
||||||
@@ -492,7 +492,7 @@ impl Timer {
|
|||||||
is_current
|
is_current
|
||||||
);
|
);
|
||||||
|
|
||||||
feat::update_profile(uid.clone(), None, Some(is_current), None).await
|
feat::update_profile(uid, None, is_current, false).await
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
@@ -517,7 +517,7 @@ impl Timer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Emit completed event
|
// Emit completed event
|
||||||
Self::emit_update_event(&uid, false);
|
Self::emit_update_event(uid, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ async fn collect_profile_items() -> ProfileItems {
|
|||||||
let item = {
|
let item = {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
profiles.get_item(&merge_uid).ok().cloned()
|
profiles.get_item(merge_uid).ok().cloned()
|
||||||
};
|
};
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
<Option<ChainItem>>::from_async(&item).await
|
<Option<ChainItem>>::from_async(&item).await
|
||||||
@@ -155,7 +155,7 @@ async fn collect_profile_items() -> ProfileItems {
|
|||||||
let item = {
|
let item = {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
profiles.get_item(&script_uid).ok().cloned()
|
profiles.get_item(script_uid).ok().cloned()
|
||||||
};
|
};
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
<Option<ChainItem>>::from_async(&item).await
|
<Option<ChainItem>>::from_async(&item).await
|
||||||
@@ -172,7 +172,7 @@ async fn collect_profile_items() -> ProfileItems {
|
|||||||
let item = {
|
let item = {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
profiles.get_item(&rules_uid).ok().cloned()
|
profiles.get_item(rules_uid).ok().cloned()
|
||||||
};
|
};
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
<Option<ChainItem>>::from_async(&item).await
|
<Option<ChainItem>>::from_async(&item).await
|
||||||
@@ -189,7 +189,7 @@ async fn collect_profile_items() -> ProfileItems {
|
|||||||
let item = {
|
let item = {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
profiles.get_item(&proxies_uid).ok().cloned()
|
profiles.get_item(proxies_uid).ok().cloned()
|
||||||
};
|
};
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
<Option<ChainItem>>::from_async(&item).await
|
<Option<ChainItem>>::from_async(&item).await
|
||||||
@@ -206,7 +206,7 @@ async fn collect_profile_items() -> ProfileItems {
|
|||||||
let item = {
|
let item = {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
profiles.get_item(&groups_uid).ok().cloned()
|
profiles.get_item(groups_uid).ok().cloned()
|
||||||
};
|
};
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
<Option<ChainItem>>::from_async(&item).await
|
<Option<ChainItem>>::from_async(&item).await
|
||||||
@@ -223,7 +223,7 @@ async fn collect_profile_items() -> ProfileItems {
|
|||||||
let item = {
|
let item = {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
profiles.get_item(&"Merge".into()).ok().cloned()
|
profiles.get_item("Merge").ok().cloned()
|
||||||
};
|
};
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
<Option<ChainItem>>::from_async(&item).await
|
<Option<ChainItem>>::from_async(&item).await
|
||||||
@@ -240,7 +240,7 @@ async fn collect_profile_items() -> ProfileItems {
|
|||||||
let item = {
|
let item = {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
profiles.get_item(&"Script".into()).ok().cloned()
|
profiles.get_item("Script").ok().cloned()
|
||||||
};
|
};
|
||||||
if let Some(item) = item {
|
if let Some(item) = item {
|
||||||
<Option<ChainItem>>::from_async(&item).await
|
<Option<ChainItem>>::from_async(&item).await
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ pub async fn restore_webdav_backup(filename: String) -> Result<()> {
|
|||||||
logging_error!(
|
logging_error!(
|
||||||
Type::Backup,
|
Type::Backup,
|
||||||
super::patch_verge(
|
super::patch_verge(
|
||||||
IVerge {
|
&IVerge {
|
||||||
webdav_url,
|
webdav_url,
|
||||||
webdav_username,
|
webdav_username,
|
||||||
webdav_password,
|
webdav_password,
|
||||||
@@ -253,7 +253,7 @@ pub async fn restore_local_backup(filename: String) -> Result<()> {
|
|||||||
logging_error!(
|
logging_error!(
|
||||||
Type::Backup,
|
Type::Backup,
|
||||||
super::patch_verge(
|
super::patch_verge(
|
||||||
IVerge {
|
&IVerge {
|
||||||
webdav_url,
|
webdav_url,
|
||||||
webdav_username,
|
webdav_username,
|
||||||
webdav_password,
|
webdav_password,
|
||||||
|
|||||||
@@ -226,15 +226,12 @@ async fn process_terminated_flags(update_flags: i32, patch: &IVerge) -> Result<(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn patch_verge(patch: IVerge, not_save_file: bool) -> Result<()> {
|
pub async fn patch_verge(patch: &IVerge, not_save_file: bool) -> Result<()> {
|
||||||
Config::verge()
|
Config::verge().await.draft_mut().patch_config(patch);
|
||||||
.await
|
|
||||||
.draft_mut()
|
|
||||||
.patch_config(patch.clone());
|
|
||||||
|
|
||||||
let update_flags = determine_update_flags(&patch);
|
let update_flags = determine_update_flags(patch);
|
||||||
let process_flag_result: std::result::Result<(), anyhow::Error> = {
|
let process_flag_result: std::result::Result<(), anyhow::Error> = {
|
||||||
process_terminated_flags(update_flags, &patch).await?;
|
process_terminated_flags(update_flags, patch).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -245,7 +242,7 @@ pub async fn patch_verge(patch: IVerge, not_save_file: bool) -> Result<()> {
|
|||||||
Config::verge().await.apply();
|
Config::verge().await.apply();
|
||||||
if !not_save_file {
|
if !not_save_file {
|
||||||
// 分离数据获取和异步调用
|
// 分离数据获取和异步调用
|
||||||
let verge_data = Config::verge().await.data_mut().clone();
|
let verge_data = Config::verge().await.data_ref().clone();
|
||||||
verge_data.save_file().await?;
|
verge_data.save_file().await?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ pub async fn toggle_proxy_profile(profile_index: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn should_update_profile(
|
async fn should_update_profile(
|
||||||
uid: String,
|
uid: &String,
|
||||||
ignore_auto_update: bool,
|
ignore_auto_update: bool,
|
||||||
) -> Result<Option<(String, Option<PrfOption>)>> {
|
) -> Result<Option<(String, Option<PrfOption>)>> {
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
let profiles = profiles.latest_ref();
|
let profiles = profiles.latest_ref();
|
||||||
let item = profiles.get_item(&uid)?;
|
let item = profiles.get_item(uid)?;
|
||||||
let is_remote = item.itype.as_ref().is_some_and(|s| s == "remote");
|
let is_remote = item.itype.as_ref().is_some_and(|s| s == "remote");
|
||||||
|
|
||||||
if !is_remote {
|
if !is_remote {
|
||||||
@@ -63,19 +63,19 @@ async fn should_update_profile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn perform_profile_update(
|
async fn perform_profile_update(
|
||||||
uid: String,
|
uid: &String,
|
||||||
url: String,
|
url: &String,
|
||||||
opt: Option<PrfOption>,
|
opt: Option<&PrfOption>,
|
||||||
option: Option<PrfOption>,
|
option: Option<&PrfOption>,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
log::info!(target: "app", "[订阅更新] 开始下载新的订阅内容");
|
log::info!(target: "app", "[订阅更新] 开始下载新的订阅内容");
|
||||||
let merged_opt = PrfOption::merge(opt.clone(), option.clone());
|
let merged_opt = PrfOption::merge(opt, option);
|
||||||
|
|
||||||
match PrfItem::from_url(&url, None, None, merged_opt.clone()).await {
|
match PrfItem::from_url(url, None, None, merged_opt.as_ref()).await {
|
||||||
Ok(item) => {
|
Ok(mut item) => {
|
||||||
log::info!(target: "app", "[订阅更新] 更新订阅配置成功");
|
log::info!(target: "app", "[订阅更新] 更新订阅配置成功");
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
profiles_draft_update_item_safe(uid.clone(), item).await?;
|
profiles_draft_update_item_safe(uid, &mut item).await?;
|
||||||
let is_current = Some(uid.clone()) == profiles.latest_ref().get_current();
|
let is_current = Some(uid.clone()) == profiles.latest_ref().get_current();
|
||||||
log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {is_current}");
|
log::info!(target: "app", "[订阅更新] 是否为当前使用的订阅: {is_current}");
|
||||||
Ok(is_current)
|
Ok(is_current)
|
||||||
@@ -91,7 +91,7 @@ async fn perform_profile_update(
|
|||||||
fallback_opt.with_proxy = Some(false);
|
fallback_opt.with_proxy = Some(false);
|
||||||
fallback_opt.self_proxy = Some(true);
|
fallback_opt.self_proxy = Some(true);
|
||||||
|
|
||||||
match PrfItem::from_url(&url, None, None, Some(fallback_opt)).await {
|
match PrfItem::from_url(url, None, None, Some(&fallback_opt)).await {
|
||||||
Ok(mut item) => {
|
Ok(mut item) => {
|
||||||
log::info!(target: "app", "[订阅更新] 使用Clash代理更新成功");
|
log::info!(target: "app", "[订阅更新] 使用Clash代理更新成功");
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ async fn perform_profile_update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let profiles = Config::profiles().await;
|
let profiles = Config::profiles().await;
|
||||||
profiles_draft_update_item_safe(uid.clone(), item.clone()).await?;
|
profiles_draft_update_item_safe(uid, &mut item).await?;
|
||||||
|
|
||||||
let profile_name = item.name.clone().unwrap_or_else(|| uid.clone());
|
let profile_name = item.name.clone().unwrap_or_else(|| uid.clone());
|
||||||
handle::Handle::notice_message("update_with_clash_proxy", profile_name);
|
handle::Handle::notice_message("update_with_clash_proxy", profile_name);
|
||||||
@@ -124,20 +124,17 @@ async fn perform_profile_update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_profile(
|
pub async fn update_profile(
|
||||||
uid: String,
|
uid: &String,
|
||||||
option: Option<PrfOption>,
|
option: Option<&PrfOption>,
|
||||||
auto_refresh: Option<bool>,
|
auto_refresh: bool,
|
||||||
ignore_auto_update: Option<bool>,
|
ignore_auto_update: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
logging!(info, Type::Config, "[订阅更新] 开始更新订阅 {}", uid);
|
logging!(info, Type::Config, "[订阅更新] 开始更新订阅 {}", uid);
|
||||||
let auto_refresh = auto_refresh.unwrap_or(true);
|
let url_opt = should_update_profile(uid, ignore_auto_update).await?;
|
||||||
let ignore_auto_update = ignore_auto_update.unwrap_or(false);
|
|
||||||
|
|
||||||
let url_opt = should_update_profile(uid.clone(), ignore_auto_update).await?;
|
|
||||||
|
|
||||||
let should_refresh = match url_opt {
|
let should_refresh = match url_opt {
|
||||||
Some((url, opt)) => {
|
Some((url, opt)) => {
|
||||||
perform_profile_update(uid.clone(), url, opt, option).await? && auto_refresh
|
perform_profile_update(uid, &url, opt.as_ref(), option).await? && auto_refresh
|
||||||
}
|
}
|
||||||
None => auto_refresh,
|
None => auto_refresh,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ pub async fn toggle_system_proxy() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let patch_result = super::patch_verge(
|
let patch_result = super::patch_verge(
|
||||||
IVerge {
|
&IVerge {
|
||||||
enable_system_proxy: Some(!enable),
|
enable_system_proxy: Some(!enable),
|
||||||
..IVerge::default()
|
..IVerge::default()
|
||||||
},
|
},
|
||||||
@@ -40,7 +40,7 @@ pub async fn toggle_tun_mode(not_save_file: Option<bool>) {
|
|||||||
let enable = enable.unwrap_or(false);
|
let enable = enable.unwrap_or(false);
|
||||||
|
|
||||||
match super::patch_verge(
|
match super::patch_verge(
|
||||||
IVerge {
|
&IVerge {
|
||||||
enable_tun_mode: Some(!enable),
|
enable_tun_mode: Some(!enable),
|
||||||
..IVerge::default()
|
..IVerge::default()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -93,14 +93,14 @@ mod app_init {
|
|||||||
}
|
}
|
||||||
|
|
||||||
app.deep_link().on_open_url(|event| {
|
app.deep_link().on_open_url(|event| {
|
||||||
let url = event.urls().first().map(|u| u.to_string());
|
let urls = event.urls();
|
||||||
if let Some(url) = url {
|
AsyncHandler::spawn(move || async move {
|
||||||
AsyncHandler::spawn(|| async {
|
if let Some(url) = urls.first()
|
||||||
if let Err(e) = resolve::resolve_scheme(url.into()).await {
|
&& let Err(e) = resolve::resolve_scheme(url.as_ref()).await
|
||||||
|
{
|
||||||
logging!(error, Type::Setup, "Failed to resolve scheme: {}", e);
|
logging!(error, Type::Setup, "Failed to resolve scheme: {}", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -117,7 +117,7 @@ mod app_init {
|
|||||||
{
|
{
|
||||||
auto_start_plugin_builder = auto_start_plugin_builder
|
auto_start_plugin_builder = auto_start_plugin_builder
|
||||||
.macos_launcher(MacosLauncher::LaunchAgent)
|
.macos_launcher(MacosLauncher::LaunchAgent)
|
||||||
.app_name(app.config().identifier.clone());
|
.app_name(&app.config().identifier);
|
||||||
}
|
}
|
||||||
app.handle().plugin(auto_start_plugin_builder.build())?;
|
app.handle().plugin(auto_start_plugin_builder.build())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -29,6 +29,11 @@ impl<T: Clone + ToOwned> From<T> for Draft<T> {
|
|||||||
/// - `apply`: Commits the draft data, replacing the committed data and returning the old committed value if a draft existed.
|
/// - `apply`: Commits the draft data, replacing the committed data and returning the old committed value if a draft existed.
|
||||||
/// - `discard`: Discards the draft data and returns it if it existed.
|
/// - `discard`: Discards the draft data and returns it if it existed.
|
||||||
impl<T: Clone + ToOwned> Draft<Box<T>> {
|
impl<T: Clone + ToOwned> Draft<Box<T>> {
|
||||||
|
/// 正式数据视图
|
||||||
|
pub fn data_ref(&self) -> MappedRwLockReadGuard<'_, Box<T>> {
|
||||||
|
RwLockReadGuard::map(self.inner.read(), |inner| &inner.0)
|
||||||
|
}
|
||||||
|
|
||||||
/// 可写正式数据
|
/// 可写正式数据
|
||||||
pub fn data_mut(&self) -> MappedRwLockWriteGuard<'_, Box<T>> {
|
pub fn data_mut(&self) -> MappedRwLockWriteGuard<'_, Box<T>> {
|
||||||
RwLockWriteGuard::map(self.inner.write(), |inner| &mut inner.0)
|
RwLockWriteGuard::map(self.inner.write(), |inner| &mut inner.0)
|
||||||
|
|||||||
@@ -429,26 +429,8 @@ pub async fn init_resources() -> Result<()> {
|
|||||||
let src_path = res_dir.join(file);
|
let src_path = res_dir.join(file);
|
||||||
let dest_path = app_dir.join(file);
|
let dest_path = app_dir.join(file);
|
||||||
|
|
||||||
let handle_copy = |src: PathBuf, dest: PathBuf, file: String| async move {
|
|
||||||
match fs::copy(&src, &dest).await {
|
|
||||||
Ok(_) => {
|
|
||||||
logging!(debug, Type::Setup, "resources copied '{}'", file);
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
logging!(
|
|
||||||
error,
|
|
||||||
Type::Setup,
|
|
||||||
"failed to copy resources '{}' to '{:?}', {}",
|
|
||||||
file,
|
|
||||||
dest,
|
|
||||||
err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
if src_path.exists() && !dest_path.exists() {
|
if src_path.exists() && !dest_path.exists() {
|
||||||
handle_copy(src_path.clone(), dest_path.clone(), (*file).into()).await;
|
handle_copy(&src_path, &dest_path, file).await;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,12 +440,12 @@ pub async fn init_resources() -> Result<()> {
|
|||||||
match (src_modified, dest_modified) {
|
match (src_modified, dest_modified) {
|
||||||
(Ok(src_modified), Ok(dest_modified)) => {
|
(Ok(src_modified), Ok(dest_modified)) => {
|
||||||
if src_modified > dest_modified {
|
if src_modified > dest_modified {
|
||||||
handle_copy(src_path.clone(), dest_path.clone(), (*file).into()).await;
|
handle_copy(&src_path, &dest_path, file).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
logging!(debug, Type::Setup, "failed to get modified '{}'", file);
|
logging!(debug, Type::Setup, "failed to get modified '{}'", file);
|
||||||
handle_copy(src_path.clone(), dest_path.clone(), (*file).into()).await;
|
handle_copy(&src_path, &dest_path, file).await;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -563,3 +545,21 @@ pub async fn startup_script() -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn handle_copy(src: &PathBuf, dest: &PathBuf, file: &str) {
|
||||||
|
match fs::copy(src, dest).await {
|
||||||
|
Ok(_) => {
|
||||||
|
logging!(debug, Type::Setup, "resources copied '{}'", file);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
logging!(
|
||||||
|
error,
|
||||||
|
Type::Setup,
|
||||||
|
"failed to copy resources '{}' to '{:?}', {}",
|
||||||
|
file,
|
||||||
|
dest,
|
||||||
|
err
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use smartstring::alias::String;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
@@ -99,7 +98,7 @@ pub(super) async fn resolve_setup_logger() {
|
|||||||
logging_error!(Type::Setup, init::init_logger().await);
|
logging_error!(Type::Setup, init::init_logger().await);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn resolve_scheme(param: String) -> Result<()> {
|
pub async fn resolve_scheme(param: &str) -> Result<()> {
|
||||||
logging_error!(Type::Setup, scheme::resolve_scheme(param).await);
|
logging_error!(Type::Setup, scheme::resolve_scheme(param).await);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,9 +3,14 @@ use percent_encoding::percent_decode_str;
|
|||||||
use smartstring::alias::String;
|
use smartstring::alias::String;
|
||||||
use tauri::Url;
|
use tauri::Url;
|
||||||
|
|
||||||
use crate::{config::PrfItem, core::handle, logging, logging_error, utils::logging::Type};
|
use crate::{
|
||||||
|
config::{PrfItem, profiles},
|
||||||
|
core::handle,
|
||||||
|
logging, logging_error,
|
||||||
|
utils::logging::Type,
|
||||||
|
};
|
||||||
|
|
||||||
pub(super) async fn resolve_scheme(param: String) -> Result<()> {
|
pub(super) async fn resolve_scheme(param: &str) -> Result<()> {
|
||||||
log::info!(target:"app", "received deep link: {param}");
|
log::info!(target:"app", "received deep link: {param}");
|
||||||
|
|
||||||
let param_str = if param.starts_with("[") && param.len() > 4 {
|
let param_str = if param.starts_with("[") && param.len() > 4 {
|
||||||
@@ -13,7 +18,7 @@ pub(super) async fn resolve_scheme(param: String) -> Result<()> {
|
|||||||
.get(2..param.len() - 2)
|
.get(2..param.len() - 2)
|
||||||
.ok_or_else(|| anyhow::anyhow!("Invalid string slice boundaries"))?
|
.ok_or_else(|| anyhow::anyhow!("Invalid string slice boundaries"))?
|
||||||
} else {
|
} else {
|
||||||
param.as_str()
|
param
|
||||||
};
|
};
|
||||||
|
|
||||||
// 解析 URL
|
// 解析 URL
|
||||||
@@ -25,10 +30,11 @@ pub(super) async fn resolve_scheme(param: String) -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if link_parsed.scheme() == "clash" || link_parsed.scheme() == "clash-verge" {
|
if link_parsed.scheme() == "clash" || link_parsed.scheme() == "clash-verge" {
|
||||||
let name = link_parsed
|
let name_owned: Option<String> = link_parsed
|
||||||
.query_pairs()
|
.query_pairs()
|
||||||
.find(|(key, _)| key == "name")
|
.find(|(key, _)| key == "name")
|
||||||
.map(|(_, value)| value.into());
|
.map(|(_, value)| value.into_owned().into());
|
||||||
|
let name = name_owned.as_ref();
|
||||||
|
|
||||||
let url_param = if let Some(query) = link_parsed.query() {
|
let url_param = if let Some(query) = link_parsed.query() {
|
||||||
let prefix = "url=";
|
let prefix = "url=";
|
||||||
@@ -43,10 +49,10 @@ pub(super) async fn resolve_scheme(param: String) -> Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match url_param {
|
match url_param {
|
||||||
Some(url) => {
|
Some(ref url) => {
|
||||||
log::info!(target:"app", "decoded subscription url: {url}");
|
log::info!(target:"app", "decoded subscription url: {url}");
|
||||||
match PrfItem::from_url(url.as_ref(), name, None, None).await {
|
match PrfItem::from_url(url, name, None, None).await {
|
||||||
Ok(item) => {
|
Ok(mut item) => {
|
||||||
let uid = match item.uid.clone() {
|
let uid = match item.uid.clone() {
|
||||||
Some(uid) => uid,
|
Some(uid) => uid,
|
||||||
None => {
|
None => {
|
||||||
@@ -58,7 +64,7 @@ pub(super) async fn resolve_scheme(param: String) -> Result<()> {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let result = crate::config::profiles::profiles_append_item_safe(item).await;
|
let result = profiles::profiles_append_item_safe(&mut item).await;
|
||||||
logging_error!(
|
logging_error!(
|
||||||
Type::Config,
|
Type::Config,
|
||||||
"failed to import subscription url: {:?}",
|
"failed to import subscription url: {:?}",
|
||||||
|
|||||||
@@ -21,16 +21,14 @@ const MINIMAL_HEIGHT: f64 = 520.0;
|
|||||||
pub async fn build_new_window() -> Result<WebviewWindow, String> {
|
pub async fn build_new_window() -> Result<WebviewWindow, String> {
|
||||||
let app_handle = handle::Handle::app_handle();
|
let app_handle = handle::Handle::app_handle();
|
||||||
|
|
||||||
let start_page = Config::verge()
|
let config = Config::verge().await;
|
||||||
.await
|
let latest = config.latest_ref();
|
||||||
.latest_ref()
|
let start_page = latest.start_page.as_deref().unwrap_or("/");
|
||||||
.start_page
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| "/".into());
|
|
||||||
match tauri::WebviewWindowBuilder::new(
|
match tauri::WebviewWindowBuilder::new(
|
||||||
app_handle,
|
app_handle,
|
||||||
"main", /* the unique window label */
|
"main", /* the unique window label */
|
||||||
tauri::WebviewUrl::App(start_page.as_str().into()),
|
tauri::WebviewUrl::App(start_page.into()),
|
||||||
)
|
)
|
||||||
.title("Clash Verge")
|
.title("Clash Verge")
|
||||||
.center()
|
.center()
|
||||||
|
|||||||
@@ -107,9 +107,8 @@ pub fn embed_server() {
|
|||||||
let scheme = warp::path!("commands" / "scheme")
|
let scheme = warp::path!("commands" / "scheme")
|
||||||
.and(warp::query::<QueryParam>())
|
.and(warp::query::<QueryParam>())
|
||||||
.map(|query: QueryParam| {
|
.map(|query: QueryParam| {
|
||||||
let param = query.param.clone();
|
|
||||||
tokio::task::spawn_local(async move {
|
tokio::task::spawn_local(async move {
|
||||||
logging_error!(Type::Setup, resolve::resolve_scheme(param).await);
|
logging_error!(Type::Setup, resolve::resolve_scheme(&query.param).await);
|
||||||
});
|
});
|
||||||
warp::reply::with_status::<std::string::String>(
|
warp::reply::with_status::<std::string::String>(
|
||||||
"ok".to_string(),
|
"ok".to_string(),
|
||||||
|
|||||||
Reference in New Issue
Block a user