mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-23 07:41:03 +00:00
fix: missing a repeek on unyanking files in the hovered folder (#1988)
This commit is contained in:
parent
2771aef677
commit
c7d9265d25
28 changed files with 71 additions and 64 deletions
4
.github/DISCUSSION_TEMPLATE/1-q-a.yml
vendored
4
.github/DISCUSSION_TEMPLATE/1-q-a.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
4
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
4
.github/ISSUE_TEMPLATE/feature.yml
vendored
4
.github/ISSUE_TEMPLATE/feature.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
// }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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<PathBuf, String>);
|
||||
|
||||
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<String> { self.get(url).map(|s| s.to_owned()) }
|
||||
pub fn by_url_owned(&self, url: &Url) -> Option<Cow<'static, str>> {
|
||||
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<Cow<'static, str>> {
|
||||
if file.is_dir() { Some(Cow::Borrowed(MIME_DIR)) } else { self.by_url_owned(&file.url) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains(&self, url: &Url) -> bool {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -20,9 +20,7 @@ impl Deref for Yanked {
|
|||
}
|
||||
|
||||
impl Yanked {
|
||||
pub fn new(cut: bool, urls: HashSet<Url>) -> Self {
|
||||
Self { cut, urls, version: 0, ..Default::default() }
|
||||
}
|
||||
pub fn new(cut: bool, urls: HashSet<Url>) -> 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() {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<str>)>) {
|
||||
let mut openers = HashMap::new();
|
||||
for (url, mime) in targets {
|
||||
if let Some(opener) = OPEN.openers(&url, mime).and_then(|o| o.first().copied()) {
|
||||
|
|
|
|||
|
|
@ -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::<AnyUserData>("cx")?
|
||||
.borrow_scoped(|cx: &Ctx| cx.manager.mimetype.get_owned(&me.url))
|
||||
lua.named_registry_value::<AnyUserData>("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::<AnyUserData>("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))
|
||||
})
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use ratatui::widgets::Borders;
|
|||
|
||||
use super::Area;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Bar {
|
||||
area: Area,
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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<Cell>,
|
||||
height: u16,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue