From c7d9265d25e51ab2ad7b4524b2be52e6b5bdf42a 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: Thu, 5 Dec 2024 08:45:18 +0800 Subject: [PATCH] fix: missing a repeek on unyanking files in the hovered folder (#1988) --- .github/DISCUSSION_TEMPLATE/1-q-a.yml | 4 +-- .github/ISSUE_TEMPLATE/bug.yml | 4 +-- .github/ISSUE_TEMPLATE/feature.yml | 4 +-- yazi-core/src/manager/commands/open.rs | 8 +++--- yazi-core/src/manager/commands/peek.rs | 4 +-- yazi-core/src/manager/commands/seek.rs | 8 ++---- yazi-core/src/manager/commands/spot.rs | 11 ++------ yazi-core/src/manager/commands/unyank.rs | 5 ++++ .../src/manager/commands/update_mimes.rs | 2 +- yazi-core/src/manager/mimetype.rs | 27 ++++++++++++++----- yazi-core/src/manager/watcher.rs | 4 +-- yazi-core/src/manager/yanked.rs | 11 +++++--- yazi-core/src/tasks/preload.rs | 5 ++-- yazi-core/src/tasks/process.rs | 2 +- yazi-fm/src/lives/file.rs | 11 +++----- yazi-plugin/src/elements/bar.rs | 2 +- yazi-plugin/src/elements/border.rs | 2 +- yazi-plugin/src/elements/cell.rs | 2 +- yazi-plugin/src/elements/clear.rs | 2 +- yazi-plugin/src/elements/gauge.rs | 2 +- yazi-plugin/src/elements/list.rs | 2 +- yazi-plugin/src/elements/rect.rs | 2 +- yazi-plugin/src/elements/renderable.rs | 2 +- yazi-plugin/src/elements/row.rs | 2 +- yazi-plugin/src/elements/table.rs | 2 +- yazi-plugin/src/elements/text.rs | 2 +- yazi-plugin/src/utils/preview.rs | 1 + yazi-proxy/src/options/open.rs | 2 +- 28 files changed, 71 insertions(+), 64 deletions(-) diff --git a/.github/DISCUSSION_TEMPLATE/1-q-a.yml b/.github/DISCUSSION_TEMPLATE/1-q-a.yml index 6d818615..c667e122 100644 --- a/.github/DISCUSSION_TEMPLATE/1-q-a.yml +++ b/.github/DISCUSSION_TEMPLATE/1-q-a.yml @@ -45,9 +45,9 @@ body: Add any other context about the problem here. You can attach screenshots by clicking this area to highlight it and then drag the files in. - type: checkboxes - id: validations + id: checklist attributes: - label: Validations + label: Checklist description: Before submitting the post, please make sure you have completed the following options: - label: I have searched the existing discussions/issues diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 6aeaede8..75b3e817 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -58,9 +58,9 @@ body: Add any other context about the problem here. You can attach screenshots by clicking this area to highlight it and then drag the files in. - type: checkboxes - id: validations + id: checklist attributes: - label: Validations + label: Checklist description: Before submitting the issue, please make sure you have completed the following options: - label: I tried the [latest nightly build](https://yazi-rs.github.io/docs/installation#official-binaries), and the issue is still reproducible diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index 478f0667..90e797aa 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -38,9 +38,9 @@ body: label: Additional context description: Add any other context or screenshots about the feature request here. - type: checkboxes - id: validations + id: checklist attributes: - label: Validations + label: Checklist description: Before submitting the issue, please make sure you have completed the following options: - label: I have searched the existing issues/discussions diff --git a/yazi-core/src/manager/commands/open.rs b/yazi-core/src/manager/commands/open.rs index 58c8ac56..baf0e499 100644 --- a/yazi-core/src/manager/commands/open.rs +++ b/yazi-core/src/manager/commands/open.rs @@ -43,9 +43,9 @@ impl Manager { let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]); for u in selected { if self.mimetype.contains(u) { - done.push((u.clone(), String::new())); + done.push((u.clone(), Cow::Borrowed(""))); } else if self.guess_folder(u) { - done.push((u.clone(), MIME_DIR.to_owned())); + done.push((u.clone(), Cow::Borrowed(MIME_DIR))); } else { todo.push(u.clone()); } @@ -64,7 +64,7 @@ impl Manager { } } - done.extend(files.iter().map(|f| (f.url_owned(), String::new()))); + done.extend(files.iter().map(|f| (f.url_owned(), Cow::Borrowed("")))); for (fetcher, files) in PLUGIN.mime_fetchers(files) { if let Err(e) = isolate::fetch(CmdCow::from(&fetcher.run), files).await { error!("Fetch mime failed on opening: {e}"); @@ -81,7 +81,7 @@ impl Manager { .targets .into_iter() .filter_map(|(u, m)| { - Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.get_owned(&u)).map(|m| (u, m)) + Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.by_url_owned(&u)).map(|m| (u, m)) }) .collect(); diff --git a/yazi-core/src/manager/commands/peek.rs b/yazi-core/src/manager/commands/peek.rs index c4d7502b..3dcaf333 100644 --- a/yazi-core/src/manager/commands/peek.rs +++ b/yazi-core/src/manager/commands/peek.rs @@ -35,7 +35,7 @@ impl Manager { return self.active_mut().preview.reset_image(); } - let mime = self.mimetype.get_owned(&hovered.url).unwrap_or_default(); + let mime = self.mimetype.by_file_owned(&hovered).unwrap_or_default(); let folder = self.active().hovered_folder().map(|f| (f.offset, f.cha)); if !self.active().preview.same_url(&hovered.url) { @@ -61,7 +61,7 @@ impl Manager { if hovered.is_dir() { self.active_mut().preview.go_folder(hovered, folder.map(|(_, cha)| cha), opt.force); } else { - self.active_mut().preview.go(hovered, mime.into(), opt.force); + self.active_mut().preview.go(hovered, mime, opt.force); } } } diff --git a/yazi-core/src/manager/commands/seek.rs b/yazi-core/src/manager/commands/seek.rs index 5bd1f4e5..e5f41248 100644 --- a/yazi-core/src/manager/commands/seek.rs +++ b/yazi-core/src/manager/commands/seek.rs @@ -1,6 +1,6 @@ use yazi_config::PLUGIN; use yazi_plugin::isolate; -use yazi_shared::{MIME_DIR, event::{CmdCow, Data}}; +use yazi_shared::event::{CmdCow, Data}; use crate::manager::Manager; @@ -20,11 +20,7 @@ impl Manager { return self.active_mut().preview.reset(); }; - let mime = if hovered.is_dir() { - MIME_DIR - } else if let Some(s) = self.mimetype.get(&hovered.url) { - s - } else { + let Some(mime) = self.mimetype.by_file(hovered) else { return self.active_mut().preview.reset(); }; diff --git a/yazi-core/src/manager/commands/spot.rs b/yazi-core/src/manager/commands/spot.rs index 4ed53ef1..2e2645cc 100644 --- a/yazi-core/src/manager/commands/spot.rs +++ b/yazi-core/src/manager/commands/spot.rs @@ -1,6 +1,4 @@ -use std::borrow::Cow; - -use yazi_shared::{MIME_DIR, event::{CmdCow, Data}}; +use yazi_shared::event::{CmdCow, Data}; use crate::manager::Manager; @@ -19,12 +17,7 @@ impl Manager { return; }; - let mime = if hovered.is_dir() { - Cow::Borrowed(MIME_DIR) - } else { - Cow::Owned(self.mimetype.get_owned(&hovered.url).unwrap_or_default()) - }; - + let mime = self.mimetype.by_file_owned(&hovered).unwrap_or_default(); // if !self.active().spot.same_file(&hovered, &mime) { // self.active_mut().spot.reset(); // } diff --git a/yazi-core/src/manager/commands/unyank.rs b/yazi-core/src/manager/commands/unyank.rs index 4956ae60..07333434 100644 --- a/yazi-core/src/manager/commands/unyank.rs +++ b/yazi-core/src/manager/commands/unyank.rs @@ -15,7 +15,12 @@ impl From<()> for Opt { impl Manager { #[yazi_codegen::command] pub fn unyank(&mut self, _: Opt) { + let repeek = self.hovered().is_some_and(|f| f.is_dir() && self.yanked.contains_in(&f.url)); self.yanked.clear(); + render!(self.yanked.catchup_revision(false)); + if repeek { + self.peek(true); + } } } diff --git a/yazi-core/src/manager/commands/update_mimes.rs b/yazi-core/src/manager/commands/update_mimes.rs index c411dcf8..dffb2e68 100644 --- a/yazi-core/src/manager/commands/update_mimes.rs +++ b/yazi-core/src/manager/commands/update_mimes.rs @@ -29,7 +29,7 @@ impl Manager { .updates .into_iter() .map(|(url, mime)| (Url::from(url.into_owned()), mime)) - .filter(|(url, mime)| self.mimetype.get(url) != Some(mime)) + .filter(|(url, mime)| self.mimetype.by_url(url) != Some(mime)) .fold(HashMap::new(), |mut map, (u, m)| { for u in linked.from_file(&u) { map.insert(u, m.clone()); diff --git a/yazi-core/src/manager/mimetype.rs b/yazi-core/src/manager/mimetype.rs index 1b339293..0b0d248b 100644 --- a/yazi-core/src/manager/mimetype.rs +++ b/yazi-core/src/manager/mimetype.rs @@ -1,24 +1,37 @@ -use std::{collections::HashMap, path::PathBuf}; +use std::{borrow::Cow, collections::HashMap, path::PathBuf}; -use yazi_shared::url::{Url, UrlScheme}; +use yazi_fs::File; +use yazi_shared::{MIME_DIR, url::{Url, UrlScheme}}; #[derive(Default)] pub struct Mimetype(HashMap); impl Mimetype { #[inline] - pub fn get(&self, url: &Url) -> Option<&str> { - let s = match url.scheme() { + pub fn by_url(&self, url: &Url) -> Option<&str> { + match url.scheme() { UrlScheme::Regular => self.0.get(url.as_path()), UrlScheme::Search => None, UrlScheme::SearchItem => self.0.get(url.as_path()), UrlScheme::Archive => None, - }; - s.map(|s| s.as_str()) + } + .map(|s| s.as_str()) } #[inline] - pub fn get_owned(&self, url: &Url) -> Option { self.get(url).map(|s| s.to_owned()) } + pub fn by_url_owned(&self, url: &Url) -> Option> { + self.by_url(url).map(|s| Cow::Owned(s.to_owned())) + } + + #[inline] + pub fn by_file(&self, file: &File) -> Option<&str> { + if file.is_dir() { Some(MIME_DIR) } else { self.by_url(&file.url) } + } + + #[inline] + pub fn by_file_owned(&self, file: &File) -> Option> { + if file.is_dir() { Some(Cow::Borrowed(MIME_DIR)) } else { self.by_url_owned(&file.url) } + } #[inline] pub fn contains(&self, url: &Url) -> bool { diff --git a/yazi-core/src/manager/watcher.rs b/yazi-core/src/manager/watcher.rs index 68697fcf..d73b6dfa 100644 --- a/yazi-core/src/manager/watcher.rs +++ b/yazi-core/src/manager/watcher.rs @@ -61,9 +61,7 @@ impl Watcher { let (mut parents, watched) = (HashSet::new(), WATCHED.read()); for u in urls { let Some(p) = u.parent_url() else { continue }; - if !watched.contains(&p) - && LINKED.read().from_dir(&p).find(|&u| watched.contains(u)).is_none() - { + if !watched.contains(&p) && !LINKED.read().from_dir(&p).any(|u| watched.contains(u)) { continue; } out_tx.send(u).ok(); diff --git a/yazi-core/src/manager/yanked.rs b/yazi-core/src/manager/yanked.rs index f87e62df..d2ae1745 100644 --- a/yazi-core/src/manager/yanked.rs +++ b/yazi-core/src/manager/yanked.rs @@ -20,9 +20,7 @@ impl Deref for Yanked { } impl Yanked { - pub fn new(cut: bool, urls: HashSet) -> Self { - Self { cut, urls, version: 0, ..Default::default() } - } + pub fn new(cut: bool, urls: HashSet) -> Self { Self { cut, urls, ..Default::default() } } pub fn remove(&mut self, url: &Url) { if self.urls.remove(url) { @@ -39,6 +37,13 @@ impl Yanked { self.revision += 1; } + pub fn contains_in(&self, dir: &Url) -> bool { + self.urls.iter().any(|u| { + let mut it = u.components(); + it.next_back().is_some() && it == dir.components() && u.parent_url().as_ref() == Some(dir) + }) + } + pub fn apply_op(&mut self, op: &FilesOp) { let (removal, addition) = op.diff_recoverable(|u| self.contains(u)); if !removal.is_empty() { diff --git a/yazi-core/src/tasks/preload.rs b/yazi-core/src/tasks/preload.rs index a40b05e5..58b76047 100644 --- a/yazi-core/src/tasks/preload.rs +++ b/yazi-core/src/tasks/preload.rs @@ -1,6 +1,5 @@ use yazi_config::{PLUGIN, plugin::MAX_PREWORKERS}; use yazi_fs::{File, Files, SortBy}; -use yazi_shared::MIME_DIR; use super::Tasks; use crate::manager::Mimetype; @@ -10,7 +9,7 @@ impl Tasks { let mut loaded = self.scheduler.prework.loaded.lock(); let mut tasks: [Vec<_>; MAX_PREWORKERS as usize] = Default::default(); for f in paged { - let mime = if f.is_dir() { MIME_DIR } else { mimetype.get(&f.url).unwrap_or_default() }; + let mime = mimetype.by_file(f).unwrap_or_default(); let factors = |s: &str| match s { "mime" => !mime.is_empty(), "dummy" => f.cha.is_dummy(), @@ -38,7 +37,7 @@ impl Tasks { pub fn preload_paged(&self, paged: &[File], mimetype: &Mimetype) { let mut loaded = self.scheduler.prework.loaded.lock(); for f in paged { - let mime = if f.is_dir() { MIME_DIR } else { mimetype.get(&f.url).unwrap_or_default() }; + let mime = mimetype.by_file(f).unwrap_or_default(); for p in PLUGIN.preloaders(&f.url, mime) { match loaded.get_mut(&f.url) { Some(n) if *n & (1 << p.idx) != 0 => continue, diff --git a/yazi-core/src/tasks/process.rs b/yazi-core/src/tasks/process.rs index 977db837..9e0d9190 100644 --- a/yazi-core/src/tasks/process.rs +++ b/yazi-core/src/tasks/process.rs @@ -6,7 +6,7 @@ use yazi_shared::url::Url; use super::Tasks; impl Tasks { - pub fn process_from_files(&self, hovered: Url, targets: Vec<(Url, String)>) { + pub fn process_from_files(&self, hovered: Url, targets: Vec<(Url, Cow)>) { let mut openers = HashMap::new(); for (url, mime) in targets { if let Some(opener) = OPEN.openers(&url, mime).and_then(|o| o.first().copied()) { diff --git a/yazi-fm/src/lives/file.rs b/yazi-fm/src/lives/file.rs index 32f8d2c4..0dcdef66 100644 --- a/yazi-fm/src/lives/file.rs +++ b/yazi-fm/src/lives/file.rs @@ -3,7 +3,6 @@ use std::ops::Deref; use mlua::{AnyUserData, IntoLua, UserData, UserDataFields, UserDataMethods}; use yazi_config::THEME; use yazi_plugin::{bindings::Range, elements::Style}; -use yazi_shared::MIME_DIR; use super::Lives; use crate::Ctx; @@ -55,9 +54,9 @@ impl UserData for File { Ok(if me.is_dir() { me.folder().files.sizes.get(me.urn()).copied() } else { Some(me.len) }) }); methods.add_method("mime", |lua, me, ()| { - lua - .named_registry_value::("cx")? - .borrow_scoped(|cx: &Ctx| cx.manager.mimetype.get_owned(&me.url)) + lua.named_registry_value::("cx")?.borrow_scoped(|cx: &Ctx| { + cx.manager.mimetype.by_url(&me.url).map(|s| lua.create_string(s)).transpose() + })? }); methods.add_method("prefix", |lua, me, ()| { if !me.folder().url.is_search() { @@ -70,9 +69,7 @@ impl UserData for File { }); methods.add_method("style", |lua, me, ()| { lua.named_registry_value::("cx")?.borrow_scoped(|cx: &Ctx| { - let mime = - if me.is_dir() { MIME_DIR } else { cx.manager.mimetype.get(&me.url).unwrap_or_default() }; - + let mime = cx.manager.mimetype.by_file(me).unwrap_or_default(); THEME.filetypes.iter().find(|&x| x.matches(me, mime)).map(|x| Style::from(x.style)) }) }); diff --git a/yazi-plugin/src/elements/bar.rs b/yazi-plugin/src/elements/bar.rs index 50f3a046..63e403ab 100644 --- a/yazi-plugin/src/elements/bar.rs +++ b/yazi-plugin/src/elements/bar.rs @@ -3,7 +3,7 @@ use ratatui::widgets::Borders; use super::Area; -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct Bar { area: Area, diff --git a/yazi-plugin/src/elements/border.rs b/yazi-plugin/src/elements/border.rs index 0eea9f33..b85897d8 100644 --- a/yazi-plugin/src/elements/border.rs +++ b/yazi-plugin/src/elements/border.rs @@ -12,7 +12,7 @@ const THICK: u8 = 3; const QUADRANT_INSIDE: u8 = 4; const QUADRANT_OUTSIDE: u8 = 5; -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct Border { pub(crate) area: Area, diff --git a/yazi-plugin/src/elements/cell.rs b/yazi-plugin/src/elements/cell.rs index 591b7633..2c13dc86 100644 --- a/yazi-plugin/src/elements/cell.rs +++ b/yazi-plugin/src/elements/cell.rs @@ -4,7 +4,7 @@ use super::Text; const EXPECTED: &str = "expected a table of strings, Texts, Lines or Spans"; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Cell { pub(super) text: ratatui::text::Text<'static>, } diff --git a/yazi-plugin/src/elements/clear.rs b/yazi-plugin/src/elements/clear.rs index 709ba812..7d01e6b2 100644 --- a/yazi-plugin/src/elements/clear.rs +++ b/yazi-plugin/src/elements/clear.rs @@ -7,7 +7,7 @@ use super::Area; pub static COLLISION: AtomicBool = AtomicBool::new(false); -#[derive(Clone, Copy, Default)] +#[derive(Clone, Copy, Debug, Default)] pub struct Clear { pub area: Area, } diff --git a/yazi-plugin/src/elements/gauge.rs b/yazi-plugin/src/elements/gauge.rs index a1d55795..5418fe0c 100644 --- a/yazi-plugin/src/elements/gauge.rs +++ b/yazi-plugin/src/elements/gauge.rs @@ -4,7 +4,7 @@ use ratatui::widgets::Widget; use super::{Area, Span}; use crate::elements::Style; -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct Gauge { area: Area, diff --git a/yazi-plugin/src/elements/list.rs b/yazi-plugin/src/elements/list.rs index 92ca0bd2..6aa228c5 100644 --- a/yazi-plugin/src/elements/list.rs +++ b/yazi-plugin/src/elements/list.rs @@ -6,7 +6,7 @@ use super::{Area, Text}; const EXPECTED: &str = "expected a table of strings, Texts, Lines or Spans"; // --- List -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct List { area: Area, diff --git a/yazi-plugin/src/elements/rect.rs b/yazi-plugin/src/elements/rect.rs index a94fe709..6978d8e6 100644 --- a/yazi-plugin/src/elements/rect.rs +++ b/yazi-plugin/src/elements/rect.rs @@ -4,7 +4,7 @@ use mlua::{FromLua, Lua, Table, UserData}; use super::Pad; -#[derive(Clone, Copy, Default, FromLua)] +#[derive(Clone, Copy, Debug, Default, FromLua)] pub struct Rect(pub(super) ratatui::layout::Rect); impl Deref for Rect { diff --git a/yazi-plugin/src/elements/renderable.rs b/yazi-plugin/src/elements/renderable.rs index ead60605..d4d7339e 100644 --- a/yazi-plugin/src/elements/renderable.rs +++ b/yazi-plugin/src/elements/renderable.rs @@ -2,7 +2,7 @@ use mlua::{AnyUserData, ExternalError}; use super::{Bar, Border, Clear, Gauge, List, Table, Text}; -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Renderable { Text(Text), List(List), diff --git a/yazi-plugin/src/elements/row.rs b/yazi-plugin/src/elements/row.rs index f9d23194..8a74b76d 100644 --- a/yazi-plugin/src/elements/row.rs +++ b/yazi-plugin/src/elements/row.rs @@ -2,7 +2,7 @@ use mlua::{AnyUserData, FromLua, Lua, Table, UserData}; use super::Cell; -#[derive(Clone, Default, FromLua)] +#[derive(Clone, Debug, Default, FromLua)] pub struct Row { pub(super) cells: Vec, height: u16, diff --git a/yazi-plugin/src/elements/table.rs b/yazi-plugin/src/elements/table.rs index 7a145b06..e55ec8b1 100644 --- a/yazi-plugin/src/elements/table.rs +++ b/yazi-plugin/src/elements/table.rs @@ -5,7 +5,7 @@ use super::{Area, Row}; use crate::elements::{Constraint, Style}; // --- Table -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct Table { pub(crate) area: Area, diff --git a/yazi-plugin/src/elements/text.rs b/yazi-plugin/src/elements/text.rs index a195062d..119bfa25 100644 --- a/yazi-plugin/src/elements/text.rs +++ b/yazi-plugin/src/elements/text.rs @@ -16,7 +16,7 @@ pub const WRAP_TRIM: u8 = 2; const EXPECTED: &str = "expected a string, Line, Span, or a table of them"; -#[derive(Clone, Default, FromLua)] +#[derive(Clone, Debug, Default, FromLua)] pub struct Text { pub area: Area, diff --git a/yazi-plugin/src/utils/preview.rs b/yazi-plugin/src/utils/preview.rs index 2802f47c..f1ae58c5 100644 --- a/yazi-plugin/src/utils/preview.rs +++ b/yazi-plugin/src/utils/preview.rs @@ -6,6 +6,7 @@ use yazi_shared::{Layer, errors::PeekError, event::Cmd}; use super::Utils; use crate::{elements::{Area, Rect, Renderable, Text, WRAP, WRAP_NO}, external::Highlighter, file::FileRef}; +#[derive(Debug)] pub struct PreviewLock { pub url: yazi_shared::url::Url, pub cha: yazi_fs::Cha, diff --git a/yazi-proxy/src/options/open.rs b/yazi-proxy/src/options/open.rs index 0882ff4b..71455633 100644 --- a/yazi-proxy/src/options/open.rs +++ b/yazi-proxy/src/options/open.rs @@ -7,7 +7,7 @@ use yazi_shared::{event::CmdCow, url::Url}; #[derive(Default)] pub struct OpenDoOpt { pub hovered: Url, - pub targets: Vec<(Url, String)>, + pub targets: Vec<(Url, Cow<'static, str>)>, pub interactive: bool, }