This commit is contained in:
sxyazi 2023-12-24 23:01:02 +08:00
parent e5ba8e7d27
commit 169543b799
No known key found for this signature in database
15 changed files with 80 additions and 54 deletions

View file

@ -160,8 +160,6 @@ impl Adaptor {
pub(super) fn start(self) { Ueberzug::start(self); } pub(super) fn start(self) { Ueberzug::start(self); }
pub async fn image_show(self, path: &Path, rect: Rect) -> Result<(u32, u32)> { pub async fn image_show(self, path: &Path, rect: Rect) -> Result<(u32, u32)> {
self.image_hide().ok();
let size = match self { let size = match self {
Self::Kitty => Kitty::image_show(path, rect).await, Self::Kitty => Kitty::image_show(path, rect).await,
Self::KittyOld => KittyOld::image_show(path, rect).await, Self::KittyOld => KittyOld::image_show(path, rect).await,

View file

@ -11,6 +11,7 @@ pub struct Files {
hidden: Vec<File>, hidden: Vec<File>,
items: Vec<File>, items: Vec<File>,
ticket: u64, ticket: u64,
version: u64,
pub(crate) revision: u64, pub(crate) revision: u64,
pub sizes: BTreeMap<Url, u64>, pub sizes: BTreeMap<Url, u64>,
@ -26,6 +27,7 @@ impl Default for Files {
items: Default::default(), items: Default::default(),
hidden: Default::default(), hidden: Default::default(),
ticket: Default::default(), ticket: Default::default(),
version: Default::default(),
revision: Default::default(), revision: Default::default(),
sizes: Default::default(), sizes: Default::default(),
@ -160,9 +162,9 @@ impl Files {
} }
self.ticket = ticket; self.ticket = ticket;
if !self.items.is_empty() || !self.hidden.is_empty() { self.hidden.clear();
if !self.items.is_empty() {
self.revision += 1; self.revision += 1;
self.hidden.clear();
self.items.clear(); self.items.clear();
} }
} }
@ -287,14 +289,24 @@ impl Files {
return; return;
} }
self.revision += 1;
if !hidden.is_empty() { if !hidden.is_empty() {
self.hidden.extend(hidden.into_values()); self.hidden.extend(hidden.into_values());
} }
if !items.is_empty() { if !items.is_empty() {
self.revision += 1;
self.items.extend(items.into_values()); self.items.extend(items.into_values());
} }
} }
pub fn catchup_revision(&mut self) -> bool {
if self.version == self.revision {
return false;
}
self.version = self.revision;
self.sorter.sort(&mut self.items, &self.sizes);
true
}
} }
impl Files { impl Files {
@ -355,33 +367,32 @@ impl Files {
#[inline] #[inline]
pub fn sorter(&self) -> &FilesSorter { &self.sorter } pub fn sorter(&self) -> &FilesSorter { &self.sorter }
pub fn set_sorter(&mut self, sorter: FilesSorter) -> bool { pub fn set_sorter(&mut self, sorter: FilesSorter) {
if self.sorter == sorter { if self.sorter != sorter {
return false; self.sorter = sorter;
self.revision += 1;
} }
self.sorter = sorter;
self.revision += 1;
self.sorter.sort(&mut self.items, &self.sizes)
} }
// --- Show hidden // --- Show hidden
pub fn set_show_hidden(&mut self, state: bool) -> bool { pub fn set_show_hidden(&mut self, state: bool) {
if state == self.show_hidden { if self.show_hidden == state {
return false; return;
} else if state && self.hidden.is_empty() {
return false;
} }
if state { self.show_hidden = state;
if self.show_hidden && self.hidden.is_empty() {
return;
} else if !self.show_hidden && self.items.is_empty() {
return;
}
self.revision += 1;
if self.show_hidden {
self.items.append(&mut self.hidden); self.items.append(&mut self.hidden);
self.sorter.sort(&mut self.items, &self.sizes);
} else { } else {
let items = mem::take(&mut self.items); let items = mem::take(&mut self.items);
(self.hidden, self.items) = items.into_iter().partition(|f| f.is_hidden()); (self.hidden, self.items) = items.into_iter().partition(|f| f.is_hidden());
} }
self.show_hidden = state;
self.revision += 1;
true
} }
} }

View file

@ -25,7 +25,6 @@ impl From<&Url> for Folder {
impl Folder { impl Folder {
pub fn update(&mut self, op: FilesOp) -> bool { pub fn update(&mut self, op: FilesOp) -> bool {
let revision = self.files.revision;
match op { match op {
FilesOp::Full(_, files) => self.files.update_full(files), FilesOp::Full(_, files) => self.files.update_full(files),
FilesOp::Part(_, files, ticket) => self.files.update_part(files, ticket), FilesOp::Part(_, files, ticket) => self.files.update_part(files, ticket),
@ -37,7 +36,7 @@ impl Folder {
FilesOp::Upserting(_, files) => self.files.update_upserting(files), FilesOp::Upserting(_, files) => self.files.update_upserting(files),
_ => unreachable!(), _ => unreachable!(),
} }
if revision == self.files.revision { if !self.files.catchup_revision() {
return false; return false;
} }

View file

@ -11,6 +11,9 @@ pub struct Opt {
impl From<&Exec> for Opt { impl From<&Exec> for Opt {
fn from(e: &Exec) -> Self { Self { url: e.args.first().map(Url::from) } } fn from(e: &Exec) -> Self { Self { url: e.args.first().map(Url::from) } }
} }
impl From<Option<Url>> for Opt {
fn from(url: Option<Url>) -> Self { Self { url } }
}
impl Manager { impl Manager {
#[inline] #[inline]
@ -27,7 +30,7 @@ impl Manager {
let mut b = self.current_mut().repos(opt.url); let mut b = self.current_mut().repos(opt.url);
// Re-peek // Re-peek
b |= self.peek(()); b |= self.peek(false);
// Refresh watcher // Refresh watcher
let mut to_watch = BTreeSet::new(); let mut to_watch = BTreeSet::new();

View file

@ -1,10 +1,11 @@
use yazi_shared::{event::Exec, fs::Url, MIME_DIR}; use yazi_shared::{emit, event::Exec, fs::Url, Layer, MIME_DIR};
use crate::manager::Manager; use crate::manager::Manager;
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct Opt { pub struct Opt {
skip: Option<usize>, skip: Option<usize>,
force: bool,
only_if: Option<Url>, only_if: Option<Url>,
upper_bound: bool, upper_bound: bool,
} }
@ -13,16 +14,22 @@ impl From<&Exec> for Opt {
fn from(e: &Exec) -> Self { fn from(e: &Exec) -> Self {
Self { Self {
skip: e.args.first().and_then(|s| s.parse().ok()), skip: e.args.first().and_then(|s| s.parse().ok()),
force: e.named.contains_key("force"),
only_if: e.named.get("only-if").map(Url::from), only_if: e.named.get("only-if").map(Url::from),
upper_bound: e.named.contains_key("upper-bound"), upper_bound: e.named.contains_key("upper-bound"),
} }
} }
} }
impl From<()> for Opt { impl From<bool> for Opt {
fn from(_: ()) -> Self { Default::default() } fn from(force: bool) -> Self { Self { force, ..Default::default() } }
} }
impl Manager { impl Manager {
#[inline]
pub fn _peek(force: bool) {
emit!(Call(Exec::call("peek", vec![]).with_bool("force", force).vec(), Layer::Manager));
}
pub fn peek(&mut self, opt: impl Into<Opt>) -> bool { pub fn peek(&mut self, opt: impl Into<Opt>) -> bool {
let Some(hovered) = self.hovered() else { let Some(hovered) = self.hovered() else {
return self.active_mut().preview.reset(); return self.active_mut().preview.reset();
@ -56,7 +63,11 @@ impl Manager {
} }
} }
self.active_mut().preview.go(hovered, mime); if opt.force {
self.active_mut().preview.force(hovered, mime);
} else {
self.active_mut().preview.go(hovered, mime);
}
false false
} }
} }

View file

@ -28,7 +28,6 @@ impl Manager {
self.watcher.trigger_dirs(&[self.cwd()]); self.watcher.trigger_dirs(&[self.cwd()]);
} }
Self::_hover(None); self.hover(None)
false
} }
} }

View file

@ -35,7 +35,7 @@ impl Manager {
b |= hovered.as_ref().is_some_and(|h| self.current_mut().hover(h)); b |= hovered.as_ref().is_some_and(|h| self.current_mut().hover(h));
if hovered.as_ref() != self.hovered().map(|h| &h.url) { if hovered.as_ref() != self.hovered().map(|h| &h.url) {
Self::_hover(None); b |= self.hover(None);
} }
b b
} }

View file

@ -37,7 +37,7 @@ impl Manager {
tasks.preload_affected(paged, &updates); tasks.preload_affected(paged, &updates);
self.mimetype.extend(updates); self.mimetype.extend(updates);
self.peek(()); self.peek(false);
true true
} }
} }

View file

@ -1,3 +1,4 @@
use yazi_adaptor::ADAPTOR;
use yazi_config::BOOT; use yazi_config::BOOT;
use yazi_shared::fs::Url; use yazi_shared::fs::Url;

View file

@ -78,9 +78,6 @@ impl Tab {
handle.abort(); handle.abort();
} }
if self.current.cwd.is_search() { if self.current.cwd.is_search() {
// TODO: plugin system
// self.preview.reset_image();
let rep = self.history_new(&self.current.cwd.to_regular()); let rep = self.history_new(&self.current.cwd.to_regular());
drop(mem::replace(&mut self.current, rep)); drop(mem::replace(&mut self.current, rep));
Manager::_refresh(); Manager::_refresh();

View file

@ -14,9 +14,9 @@ pub enum FinderCase {
} }
pub struct Finder { pub struct Finder {
query: Regex, query: Regex,
matched: BTreeMap<Url, u8>, matched: BTreeMap<Url, u8>,
version: u64, revision: u64,
} }
impl Finder { impl Finder {
@ -29,7 +29,7 @@ impl Finder {
FinderCase::Sensitive => Regex::new(s)?, FinderCase::Sensitive => Regex::new(s)?,
FinderCase::Insensitive => RegexBuilder::new(s).case_insensitive(true).build()?, FinderCase::Insensitive => RegexBuilder::new(s).case_insensitive(true).build()?,
}; };
Ok(Self { query, matched: Default::default(), version: 0 }) Ok(Self { query, matched: Default::default(), revision: 0 })
} }
pub(super) fn prev(&self, files: &Files, cursor: usize, include: bool) -> Option<isize> { pub(super) fn prev(&self, files: &Files, cursor: usize, include: bool) -> Option<isize> {
@ -53,7 +53,7 @@ impl Finder {
} }
pub(super) fn catchup(&mut self, files: &Files) -> bool { pub(super) fn catchup(&mut self, files: &Files) -> bool {
if self.version == files.revision { if self.revision == files.revision {
return false; return false;
} }
self.matched.clear(); self.matched.clear();
@ -72,7 +72,7 @@ impl Finder {
i += 1; i += 1;
} }
self.version = files.revision; self.revision = files.revision;
true true
} }

View file

@ -14,10 +14,12 @@ pub struct Preview {
impl Preview { impl Preview {
pub fn go(&mut self, file: File, mime: String) { pub fn go(&mut self, file: File, mime: String) {
if self.content_unchanged(&file.url, &file.cha) { if !self.content_unchanged(&file.url, &file.cha) {
return; self.force(file, mime);
} }
}
pub fn force(&mut self, file: File, mime: String) {
let Some(previewer) = PLUGIN.previewer(&file.url, &mime) else { let Some(previewer) = PLUGIN.previewer(&file.url, &mime) else {
self.reset(); self.reset();
return; return;
@ -44,6 +46,12 @@ impl Preview {
self.lock.take().is_some() self.lock.take().is_some()
} }
#[inline]
pub fn reset_image(&mut self) {
self.abort();
ADAPTOR.image_hide().ok();
}
#[inline] #[inline]
pub fn same_url(&self, url: &Url) -> bool { pub fn same_url(&self, url: &Url) -> bool {
matches!(self.lock, Some(ref lock) if lock.url == *url) matches!(self.lock, Some(ref lock) if lock.url == *url)

View file

@ -76,9 +76,9 @@ impl Tab {
let apply = |f: &mut Folder| { let apply = |f: &mut Folder| {
let hovered = f.hovered().map(|h| h.url()); let hovered = f.hovered().map(|h| h.url());
let mut b = f.files.set_show_hidden(self.conf.show_hidden); f.files.set_show_hidden(self.conf.show_hidden);
b |= f.files.set_sorter(self.conf.sorter()); f.files.set_sorter(self.conf.sorter());
b | f.repos(hovered) f.files.catchup_revision() | f.repos(hovered)
}; };
let mut b = false; let mut b = false;

View file

@ -86,9 +86,7 @@ impl App {
if !COLLISION.load(Ordering::Relaxed) { if !COLLISION.load(Ordering::Relaxed) {
if collision { if collision {
// Reload preview if collision is resolved // Reload preview if collision is resolved
// TODO: plugin system self.cx.manager.peek(true);
// self.cx.manager.active_mut().preview.reset_image();
self.cx.manager.peek(());
} }
return Ok(()); return Ok(());
} }
@ -117,7 +115,7 @@ impl App {
self.dispatch_render()?; self.dispatch_render()?;
self.cx.manager.current_mut().set_page(true); self.cx.manager.current_mut().set_page(true);
self.cx.manager.peek(()); self.cx.manager.peek(false);
Ok(()) Ok(())
} }

View file

@ -1,5 +1,6 @@
use anyhow::Result; use anyhow::Result;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use yazi_adaptor::ADAPTOR;
use yazi_core::manager::Manager; use yazi_core::manager::Manager;
use yazi_shared::{emit, event::Exec, term::Term}; use yazi_shared::{emit, event::Exec, term::Term};
@ -24,16 +25,16 @@ impl App {
return false; return false;
}; };
// TODO: plugin system self.cx.manager.active_mut().preview.reset_image();
// self.cx.manager.active_mut().preview.reset_image();
if opt.state { if opt.state {
self.signals.stop_term(true); self.signals.stop_term(true);
self.term = None; self.term = None;
} else { } else {
self.term = Some(Term::start().unwrap()); self.term = Some(Term::start().unwrap());
self.signals.stop_term(false); self.signals.stop_term(false);
self.cx.manager.hover(None);
self.cx.manager.peek(true);
emit!(Render); emit!(Render);
Manager::_hover(None);
} }
if let Some(tx) = opt.tx { if let Some(tx) = opt.tx {
tx.send(()).ok(); tx.send(()).ok();