diff --git a/.github/workflows/validate-form.yml b/.github/workflows/validate-form.yml index b30759fa..2d48f16a 100644 --- a/.github/workflows/validate-form.yml +++ b/.github/workflows/validate-form.yml @@ -15,9 +15,9 @@ jobs: - uses: actions/checkout@v5 - name: Setup Node.js - uses: actions/setup-node@v5 + uses: actions/setup-node@v6 with: - node-js: 20 + node-version: 20 - name: Install Dependencies run: | diff --git a/Cargo.lock b/Cargo.lock index 2ef35382..b5e6df7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -319,11 +319,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.4" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -527,9 +527,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.49" +version = "4.5.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4512b90fa68d3a9932cea5184017c5d200f5921df706d45e853537dea51508f" +checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623" dependencies = [ "clap_builder", "clap_derive", @@ -537,9 +537,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.49" +version = "4.5.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0025e98baa12e766c67ba13ff4695a887a1eba19569aad00a472546795bd6730" +checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0" dependencies = [ "anstream", "anstyle", @@ -740,7 +740,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "crossterm_winapi", "mio", "parking_lot", @@ -756,7 +756,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "crossterm_winapi", "derive_more", "document-features", @@ -1680,9 +1680,12 @@ dependencies = [ [[package]] name = "indoc" -version = "2.0.6" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] [[package]] name = "inotify" @@ -1690,7 +1693,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "inotify-sys", "libc", ] @@ -1768,9 +1771,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -1941,7 +1944,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", ] @@ -2016,9 +2019,9 @@ dependencies = [ [[package]] name = "luajit-src" -version = "210.6.1+f9140a6" +version = "210.6.2+25a61a1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "813bd31f2759443affa687c0d9c5eb5cf6cb0e898810ab197408431d746054bf" +checksum = "89b3e51e810ed7940b3d057d4cb63ef5faa8261fc8f46fb1905947a22f1c89ec" dependencies = [ "cc", "which", @@ -2162,7 +2165,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "cfg-if", "cfg_aliases", "libc", @@ -2190,7 +2193,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "fsevent-sys", "inotify", "kqueue", @@ -2352,7 +2355,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "objc2", ] @@ -2373,9 +2376,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "onig" @@ -2383,7 +2386,7 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "libc", "once_cell", "onig_sys", @@ -2670,7 +2673,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "crc32fast", "fdeflate", "flate2", @@ -2908,7 +2911,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "cassowary", "compact_str", "crossterm 0.28.1", @@ -2988,7 +2991,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", ] [[package]] @@ -3090,7 +3093,7 @@ checksum = "23ca8e9091b72afdc9979bddcd1988ad898fa7bc0b85c8da8c154c29d44319eb" dependencies = [ "aes", "base64ct", - "bitflags 2.9.4", + "bitflags 2.10.0", "block-padding", "byteorder", "bytes", @@ -3197,7 +3200,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -3210,7 +3213,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.11.0", @@ -3978,9 +3981,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "unicode-ident" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" [[package]] name = "unicode-segmentation" @@ -4243,11 +4246,10 @@ checksum = "a751b3277700db47d3e574514de2eced5e54dc8a5436a3bf7a0b248b2cee16f3" [[package]] name = "which" -version = "7.0.3" +version = "8.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d643ce3fd3e5b54854602a080f34fb10ab75e0b813ee32d00ca2b44fa74762" +checksum = "d3fabb953106c3c8eea8306e4393700d7657561cb43122571b172bbfb7c7ba1d" dependencies = [ - "either", "env_home", "rustix 1.1.2", "winsafe", @@ -4798,7 +4800,7 @@ name = "yazi-config" version = "25.9.15" dependencies = [ "anyhow", - "bitflags 2.9.4", + "bitflags 2.10.0", "crossterm 0.29.0", "dirs", "globset", @@ -4930,7 +4932,7 @@ version = "25.9.15" dependencies = [ "anyhow", "arc-swap", - "bitflags 2.9.4", + "bitflags 2.10.0", "core-foundation-sys", "dirs", "foldhash 0.2.0", @@ -4966,7 +4968,7 @@ name = "yazi-parser" version = "25.9.15" dependencies = [ "anyhow", - "bitflags 2.9.4", + "bitflags 2.10.0", "crossterm 0.29.0", "hashbrown 0.16.0", "mlua", @@ -5072,7 +5074,7 @@ dependencies = [ name = "yazi-sftp" version = "0.1.0" dependencies = [ - "bitflags 2.9.4", + "bitflags 2.10.0", "parking_lot", "russh", "serde", diff --git a/Cargo.toml b/Cargo.toml index 66cda694..041ccb33 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,8 @@ lto = false ansi-to-tui = "7.0.0" anyhow = "1.0.100" base64 = "0.22.1" -bitflags = { version = "2.9.4", features = [ "serde" ] } -clap = { version = "4.5.49", features = [ "derive" ] } +bitflags = { version = "2.10.0", features = [ "serde" ] } +clap = { version = "4.5.50", features = [ "derive" ] } core-foundation-sys = "0.8.7" crossterm = { version = "0.29.0", features = [ "event-stream" ] } dirs = "6.0.0" diff --git a/yazi-actor/src/context.rs b/yazi-actor/src/context.rs index fdae7b95..9361ae92 100644 --- a/yazi-actor/src/context.rs +++ b/yazi-actor/src/context.rs @@ -6,10 +6,12 @@ use yazi_fs::File; use yazi_shared::{Id, Source, event::Cmd, url::UrlBuf}; pub struct Ctx<'a> { - pub core: &'a mut Core, - pub tab: usize, - pub level: usize, - pub source: Source, + pub core: &'a mut Core, + pub tab: usize, + pub level: usize, + pub source: Source, + #[cfg(debug_assertions)] + pub backtrace: Vec<&'static str>, } impl Deref for Ctx<'_> { @@ -36,19 +38,40 @@ impl<'a> Ctx<'a> { core.mgr.tabs.cursor }; - Ok(Self { core, tab, level: 0, source: cmd.source }) + Ok(Self { + core, + tab, + level: 0, + source: cmd.source, + #[cfg(debug_assertions)] + backtrace: vec![], + }) } #[inline] pub fn renew<'b>(cx: &'a mut Ctx<'b>) -> Self { let tab = cx.core.mgr.tabs.cursor; - Self { core: cx.core, tab, level: cx.level, source: cx.source } + Self { + core: cx.core, + tab, + level: cx.level, + source: cx.source, + #[cfg(debug_assertions)] + backtrace: vec![], + } } #[inline] pub fn active(core: &'a mut Core) -> Self { let tab = core.mgr.tabs.cursor; - Self { core, tab, level: 0, source: Source::Unknown } + Self { + core, + tab, + level: 0, + source: Source::Unknown, + #[cfg(debug_assertions)] + backtrace: vec![], + } } } diff --git a/yazi-actor/src/mgr/peek.rs b/yazi-actor/src/mgr/peek.rs index 3940cd82..3044c269 100644 --- a/yazi-actor/src/mgr/peek.rs +++ b/yazi-actor/src/mgr/peek.rs @@ -30,6 +30,9 @@ impl Actor for Peek { if !cx.tab().preview.same_file(&hovered, &mime) { cx.tab_mut().preview.reset(); } + if !cx.tab().preview.same_folder(&hovered.url) { + cx.tab_mut().preview.folder_lock = None; + } if matches!(opt.only_if, Some(u) if u != hovered.url) { succ!(); @@ -45,7 +48,7 @@ impl Actor for Peek { } if hovered.is_dir() { - cx.tab_mut().preview.go_folder(hovered, folder.map(|(_, cha)| cha), opt.force); + cx.tab_mut().preview.go_folder(hovered, folder.map(|(_, cha)| cha), mime, opt.force); } else { cx.tab_mut().preview.go(hovered, mime, opt.force); } diff --git a/yazi-core/src/tab/preview.rs b/yazi-core/src/tab/preview.rs index 7d48d9f5..3cfd7ec5 100644 --- a/yazi-core/src/tab/preview.rs +++ b/yazi-core/src/tab/preview.rs @@ -9,7 +9,7 @@ use yazi_fs::{File, Files, FilesOp, cha::Cha}; use yazi_macro::render; use yazi_parser::mgr::PreviewLock; use yazi_plugin::{external::Highlighter, isolate}; -use yazi_shared::{pool::{InternStr, Symbol}, url::UrlBuf}; +use yazi_shared::{pool::Symbol, url::UrlBuf}; use yazi_vfs::{VfsFiles, VfsFilesOp}; #[derive(Default)] @@ -17,8 +17,9 @@ pub struct Preview { pub lock: Option, pub skip: usize, - previewer_ct: Option, - folder_loader: Option>, + previewer_ct: Option, + pub folder_lock: Option, + folder_loader: Option>, } impl Preview { @@ -37,19 +38,17 @@ impl Preview { self.previewer_ct = isolate::peek(&previewer.run, file, mime, self.skip); } - pub fn go_folder(&mut self, file: File, dir: Option, force: bool) { - const MIME: &str = "folder/lock"; - - let same = self.same_file(&file, MIME); - let (wd, cha, internal) = (file.url_owned(), file.cha, file.url.is_internal()); - - self.go(file, MIME.intern(), force); - if same || !internal { - return; + pub fn go_folder(&mut self, file: File, dir: Option, mime: Symbol, force: bool) { + if !file.url.is_internal() { + return self.go(file, mime, force); + } else if self.folder_lock.as_ref() == Some(&file.url) { + return self.go(file, mime, force); } - self.lock = - Some(PreviewLock { url: wd.clone(), cha, mime: MIME.to_owned(), ..Default::default() }); + let wd = file.url_owned(); + self.go(file, mime, force); + + self.folder_lock = Some(wd.clone()); self.folder_loader.take().map(|h| h.abort()); self.folder_loader = Some(tokio::spawn(async move { let Some(new) = Files::assert_stale(&wd, dir.unwrap_or_default()).await else { return }; @@ -97,4 +96,6 @@ impl Preview { pub fn same_lock(&self, file: &File, mime: &str) -> bool { self.same_file(file, mime) && matches!(&self.lock, Some(l) if l.skip == self.skip) } + + pub fn same_folder(&self, url: &UrlBuf) -> bool { self.folder_lock.as_ref() == Some(url) } } diff --git a/yazi-macro/src/actor.rs b/yazi-macro/src/actor.rs index f6ddfeae..ca9999c1 100644 --- a/yazi-macro/src/actor.rs +++ b/yazi-macro/src/actor.rs @@ -9,11 +9,18 @@ macro_rules! act { }; (@impl $layer:ident : $name:ident, $cx:ident, $opt:ident) => {{ $cx.level += 1; + #[cfg(debug_assertions)] + $cx.backtrace.push(concat!(stringify!($layer), ":", stringify!($name))); + let result = match act!(@pre $layer:$name, $cx, $opt) { Ok(opt) => ::act($cx, opt), Err(e) => Err(e), }; + $cx.level -= 1; + #[cfg(debug_assertions)] + $cx.backtrace.pop(); + result }}; diff --git a/yazi-shared/src/pool/symbol.rs b/yazi-shared/src/pool/symbol.rs index ef5386f0..917099d9 100644 --- a/yazi-shared/src/pool/symbol.rs +++ b/yazi-shared/src/pool/symbol.rs @@ -109,6 +109,13 @@ impl PartialOrd for Symbol { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } +// --- Display +impl std::fmt::Display for Symbol { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.as_ref()) + } +} + // --- Debug impl std::fmt::Debug for Symbol<[u8]> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {