mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-28 00:42:08 +08:00
feat: allow manually unfixing proxy nodes (#7756)
* feat(proxy): add ability to clear persisted node selection for groups * feat(hooks): make proxy selection operations asynchronous * chore: update tauri-plugin-mihomo deps * refactor: rename clear_selected_node to forget_selected_node * refactor(hooks): rename isFixed to isFixedProxy in useProxySelection * docs: update changelog with manual node cancellation support * chore(layout): remove dev-only mihomo websocket debugging interval
This commit is contained in:
@@ -32,6 +32,14 @@ pub async fn record_selected_node(group_name: String, node: String) -> CmdResult
|
||||
.stringify_err()
|
||||
}
|
||||
|
||||
/// Forget the persisted node selection for a proxy group in the current profile.
|
||||
#[tauri::command]
|
||||
pub async fn forget_selected_node(group_name: String) -> CmdResult<()> {
|
||||
crate::config::profiles::forget_selected_node(&group_name)
|
||||
.await
|
||||
.stringify_err()
|
||||
}
|
||||
|
||||
static TRAY_SYNC_RUNNING: AtomicBool = AtomicBool::new(false);
|
||||
static TRAY_SYNC_PENDING: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
|
||||
@@ -977,6 +977,45 @@ pub async fn record_selected_node(group_name: &str, node: &str) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_selected_node(selected: &mut Vec<PrfSelected>, group_name: &str) -> bool {
|
||||
let original_len = selected.len();
|
||||
selected.retain(|entry| entry.name.as_deref() != Some(group_name));
|
||||
selected.len() != original_len
|
||||
}
|
||||
|
||||
pub async fn forget_selected_node(group_name: &str) -> Result<()> {
|
||||
let cleared = Config::profiles()
|
||||
.await
|
||||
.with_data_modify(move |mut profiles| async move {
|
||||
let Some(current) = profiles.current.clone() else {
|
||||
return Ok((profiles, false));
|
||||
};
|
||||
let Some(item) = profiles
|
||||
.items
|
||||
.as_mut()
|
||||
.and_then(|items| items.iter_mut().find(|item| item.uid.as_ref() == Some(¤t)))
|
||||
else {
|
||||
return Ok((profiles, false));
|
||||
};
|
||||
|
||||
let mut selected = item.selected.clone().unwrap_or_default();
|
||||
if !remove_selected_node(&mut selected, group_name) {
|
||||
return Ok((profiles, false));
|
||||
}
|
||||
|
||||
item.selected = (!selected.is_empty()).then_some(selected);
|
||||
profiles.save_file().await?;
|
||||
Ok((profiles, true))
|
||||
})
|
||||
.await?;
|
||||
|
||||
if cleared {
|
||||
supersede_selected_activation();
|
||||
handle::Handle::refresh_profiles();
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn persist_reconciled_selected(
|
||||
profile_uid: &String,
|
||||
original_selected: &[PrfSelected],
|
||||
@@ -1395,6 +1434,22 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removes_only_the_requested_group_selection() {
|
||||
let mut selections = vec![selected("Proxy", "Node A"), selected("Fallback", "Node B")];
|
||||
|
||||
assert!(remove_selected_node(&mut selections, "Proxy"));
|
||||
assert_eq!(selections, vec![selected("Fallback", "Node B")]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn removing_a_missing_group_is_idempotent() {
|
||||
let mut selections = vec![selected("Proxy", "Node A")];
|
||||
|
||||
assert!(!remove_selected_node(&mut selections, "Missing"));
|
||||
assert_eq!(selections, vec![selected("Proxy", "Node A")]);
|
||||
}
|
||||
|
||||
fn proxies(groups: Vec<(&str, &[&str], Option<&str>)>) -> Proxies {
|
||||
Proxies {
|
||||
proxies: groups
|
||||
|
||||
@@ -165,6 +165,7 @@ mod app_init {
|
||||
cmd::copy_clash_env,
|
||||
cmd::sync_tray_proxy_selection,
|
||||
cmd::record_selected_node,
|
||||
cmd::forget_selected_node,
|
||||
cmd::save_dns_config,
|
||||
cmd::apply_dns_config,
|
||||
cmd::check_dns_config_exists,
|
||||
|
||||
Reference in New Issue
Block a user