mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-30 10:42:09 +08:00
fix(profile): schedule imported profiles for auto-update
This commit is contained in:
@@ -16,8 +16,8 @@ use crate::{
|
||||
feat,
|
||||
utils::{dirs, help},
|
||||
};
|
||||
use clash_verge_draft::SharedDraft;
|
||||
use clash_verge_logging::{Type, logging};
|
||||
use clash_verge_draft::{Draft, SharedDraft};
|
||||
use clash_verge_logging::{Type, logging, logging_error};
|
||||
use scopeguard::defer;
|
||||
use smartstring::alias::String;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
@@ -83,21 +83,18 @@ pub async fn import_profile(url: std::string::String, option: Option<PrfOption>)
|
||||
}
|
||||
};
|
||||
|
||||
match profiles_append_item_safe(item).await {
|
||||
Ok(_) => match profiles_save_file_safe().await {
|
||||
Ok(_) => {
|
||||
logging!(info, Type::Cmd, "[导入订阅] 配置文件保存成功");
|
||||
}
|
||||
Err(e) => {
|
||||
logging!(error, Type::Cmd, "[导入订阅] 保存配置文件失败: {}", e);
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
logging!(error, Type::Cmd, "[导入订阅] 保存配置失败: {}", e);
|
||||
return Err(format!("导入订阅失败: {}", e).into());
|
||||
}
|
||||
if let Err(e) = profiles_append_item_safe(item).await {
|
||||
logging!(error, Type::Cmd, "[导入订阅] 保存配置失败: {}", e);
|
||||
return Err(format!("导入订阅失败: {}", e).into());
|
||||
}
|
||||
|
||||
if let Err(e) = profiles_save_file_safe().await {
|
||||
logging!(error, Type::Cmd, "[导入订阅] 保存配置文件失败: {}", e);
|
||||
return Err(format!("导入订阅失败: {}", e).into());
|
||||
}
|
||||
logging!(info, Type::Cmd, "[导入订阅] 配置文件保存成功");
|
||||
logging_error!(Type::Timer, Timer::global().refresh().await);
|
||||
|
||||
if let Some(uid) = &item.uid {
|
||||
logging!(info, Type::Cmd, "[导入订阅] 发送配置变更通知: {}", uid);
|
||||
handle::Handle::notify_profile_changed(uid);
|
||||
@@ -129,6 +126,7 @@ pub async fn create_profile(item: PrfItem, file_data: Option<String>) -> CmdResu
|
||||
match profiles_append_item_with_filedata_safe(&item, file_data).await {
|
||||
Ok(_) => {
|
||||
profiles_save_file_safe().await.stringify_err()?;
|
||||
logging_error!(Type::Timer, Timer::global().refresh().await);
|
||||
// 发送配置变更通知
|
||||
if let Some(uid) = &item.uid {
|
||||
logging!(info, Type::Cmd, "[创建订阅] 发送配置变更通知: {}", uid);
|
||||
@@ -211,8 +209,27 @@ async fn restore_previous_profile(prev_profile: &String) -> CmdResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn commit_current_profile(profiles: &Draft<IProfiles>, current: Option<String>) -> anyhow::Result<()> {
|
||||
profiles.discard();
|
||||
let Some(current) = current else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
profiles
|
||||
.with_data_modify(|mut committed| async move {
|
||||
committed.patch_config(&IProfiles {
|
||||
current: Some(current),
|
||||
items: None,
|
||||
});
|
||||
Ok((committed, ()))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn handle_success(current_value: Option<&String>) -> CmdResult<ValidationOutcome> {
|
||||
Config::profiles().await.apply();
|
||||
commit_current_profile(&Config::profiles().await, current_value.cloned())
|
||||
.await
|
||||
.stringify_err()?;
|
||||
// Runtime refresh and tray rebuilding happen after saved node selections are restored.
|
||||
profiles::activate_selected_nodes().stringify_err()?;
|
||||
|
||||
@@ -398,3 +415,44 @@ pub async fn get_next_update_time(uid: String) -> CmdResult<Option<i64>> {
|
||||
let next_time = timer.get_next_update_time(&uid).await;
|
||||
Ok(next_time)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::commit_current_profile;
|
||||
use crate::config::{IProfiles, PrfItem};
|
||||
use clash_verge_draft::Draft;
|
||||
|
||||
fn profile(uid: &str) -> PrfItem {
|
||||
PrfItem {
|
||||
uid: Some(uid.into()),
|
||||
..PrfItem::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn committing_profile_switch_preserves_profiles_added_after_draft_creation() -> anyhow::Result<()> {
|
||||
let profiles = Draft::new(IProfiles {
|
||||
current: Some("a".into()),
|
||||
items: Some(vec![profile("a"), profile("b")]),
|
||||
});
|
||||
profiles.edit_draft(|draft| {
|
||||
draft.patch_config(&IProfiles {
|
||||
current: Some("b".into()),
|
||||
items: None,
|
||||
});
|
||||
});
|
||||
profiles
|
||||
.with_data_modify(|mut committed| async move {
|
||||
committed.items.get_or_insert_with(Vec::new).push(profile("new"));
|
||||
Ok((committed, ()))
|
||||
})
|
||||
.await?;
|
||||
|
||||
commit_current_profile(&profiles, Some("b".into())).await?;
|
||||
|
||||
let committed = profiles.data_arc();
|
||||
assert_eq!(committed.current.as_deref(), Some("b"));
|
||||
assert!(committed.get_item("new").is_ok());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user