From a64e8a8b59ce066f39ced549b9e030430779d104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Wed, 11 Dec 2024 21:21:41 +0800 Subject: [PATCH] fix: offset cursor shift when deleting multiple files in bulk (#2030) --- yazi-core/src/tab/folder.rs | 5 ++- yazi-fs/src/files.rs | 62 ++++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/yazi-core/src/tab/folder.rs b/yazi-core/src/tab/folder.rs index 70bfd36e..9c87edf3 100644 --- a/yazi-core/src/tab/folder.rs +++ b/yazi-core/src/tab/folder.rs @@ -51,7 +51,10 @@ impl Folder { FilesOp::IOErr(..) => self.files.update_ioerr(), FilesOp::Creating(_, files) => self.files.update_creating(files), - FilesOp::Deleting(_, urns) => self.files.update_deleting(urns), + FilesOp::Deleting(_, urns) => { + let deleted = self.files.update_deleting(urns); + self.cursor -= deleted.into_iter().filter(|&i| i < self.cursor).count(); + } FilesOp::Updating(_, files) => _ = self.files.update_updating(files), FilesOp::Upserting(_, files) => self.files.update_upserting(files), } diff --git a/yazi-fs/src/files.rs b/yazi-fs/src/files.rs index 75196e3f..a9b7ae9c 100644 --- a/yazi-fs/src/files.rs +++ b/yazi-fs/src/files.rs @@ -1,4 +1,4 @@ -use std::{collections::{HashMap, HashSet}, mem, ops::Deref}; +use std::{collections::{HashMap, HashSet}, mem, ops::{Deref, Not}}; use tokio::{fs::{self, DirEntry}, select, sync::mpsc::{self, UnboundedReceiver}}; use yazi_shared::{Id, url::{Url, Urn, UrnBuf}}; @@ -182,19 +182,9 @@ impl Files { } #[cfg(unix)] - pub fn update_deleting(&mut self, urns: HashSet) { + pub fn update_deleting(&mut self, urns: HashSet) -> Vec { if urns.is_empty() { - return; - } - - macro_rules! go { - ($dist:expr, $src:expr, $inc:literal) => { - let len = $dist.len(); - $dist.retain(|f| !$src.remove(f.urn())); - if $dist.len() != len { - self.revision += $inc; - } - }; + return vec![]; } let (mut hidden, mut items) = if let Some(filter) = &self.filter { @@ -208,32 +198,46 @@ impl Files { urns.into_iter().partition(|u| u.as_urn().is_hidden()) }; + let mut deleted = Vec::with_capacity(items.len()); if !items.is_empty() { - go!(self.items, items, 1); + let mut i = 0; + self.items.retain(|f| { + let b = items.remove(f.urn()); + if b { + deleted.push(i); + } + i += 1; + !b + }); } if !hidden.is_empty() { - go!(self.hidden, hidden, 0); + self.hidden.retain(|f| !hidden.remove(f.urn())); } + + self.revision += deleted.is_empty().not() as u64; + deleted } #[cfg(windows)] - pub fn update_deleting(&mut self, mut urns: HashSet) { - macro_rules! go { - ($dist:expr, $src:expr, $inc:literal) => { - let len = $dist.len(); - $dist.retain(|f| !$src.remove(f.urn())); - if $dist.len() != len { - self.revision += $inc; + pub fn update_deleting(&mut self, mut urns: HashSet) -> Vec { + let mut deleted = Vec::with_capacity(urns.len()); + if !urns.is_empty() { + let mut i = 0; + self.items.retain(|f| { + let b = urns.remove(f.urn()); + if b { + deleted.push(i) } - }; + i += 1; + !b + }); + } + if !urns.is_empty() { + self.hidden.retain(|f| !urns.remove(f.urn())); } - if !urns.is_empty() { - go!(self.items, urns, 1); - } - if !urns.is_empty() { - go!(self.hidden, urns, 0); - } + self.revision += deleted.is_empty().not() as u64; + deleted } pub fn update_updating(