Skip to content

Commit

Permalink
fix: one file's mime-type changed multiple times without triggering a…
Browse files Browse the repository at this point in the history
… preview again (#1682)
  • Loading branch information
sxyazi authored Sep 25, 2024
1 parent 631afd0 commit 5b66192
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 58 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion yazi-adapter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ static SHOWN: RoCell<arc_swap::ArcSwapOption<ratatui::layout::Rect>> = RoCell::n

pub fn init() {
// Tmux support
TMUX.init(env_exists("TMUX") && env_exists("TMUX_PANE"));
TMUX.init(env_exists("TMUX_PANE") && env_exists("TMUX"));
ESCAPE.init(if *TMUX { "\x1b\x1b" } else { "\x1b" });
START.init(if *TMUX { "\x1bPtmux;\x1b\x1b" } else { "\x1b" });
CLOSE.init(if *TMUX { "\x1b\\" } else { "" });
Expand Down
2 changes: 0 additions & 2 deletions yazi-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ tokio = { workspace = true }
toml_edit = "0.22.21"

[build-dependencies]
yazi-shared = { path = "../yazi-shared", version = "0.3.3" }

# External build dependencies
anyhow = { workspace = true }
clap = { workspace = true }
Expand Down
17 changes: 8 additions & 9 deletions yazi-core/src/manager/commands/peek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@ impl From<bool> for Opt {
impl Manager {
pub fn peek(&mut self, opt: impl Into<Opt>) {
let Some(hovered) = self.hovered().cloned() else {
return render!(self.active_mut().preview.reset());
return self.active_mut().preview.reset();
};

let mime = self.mimetype.get_owned(&hovered.url).unwrap_or_default();
let folder = self.active().hovered_folder().map(|f| (f.offset, f.cha));

if !self.active().preview.same_url(&hovered.url) {
self.active_mut().preview.skip = folder.map(|f| f.0).unwrap_or_default();
render!(self.active_mut().preview.reset());
}
if !self.active().preview.same_file(&hovered, &mime) {
self.active_mut().preview.reset();
}

let opt = opt.into() as Opt;
Expand All @@ -52,13 +56,8 @@ impl Manager {

if hovered.is_dir() {
self.active_mut().preview.go_folder(hovered, folder.map(|f| f.1), opt.force);
return;
}

let mime = self.mimetype.get_owned(&hovered.url).unwrap_or_default();
if !mime.is_empty() {
// Wait till mimetype is resolved to avoid flickering
self.active_mut().preview.go(hovered, &mime, opt.force);
} else {
self.active_mut().preview.go(hovered, mime.into(), opt.force);
}
}
}
6 changes: 3 additions & 3 deletions yazi-core/src/manager/commands/seek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ impl From<Cmd> for Opt {
impl Manager {
pub fn seek(&mut self, opt: impl Into<Opt>) {
let Some(hovered) = self.hovered() else {
return render!(self.active_mut().preview.reset());
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 {
return render!(self.active_mut().preview.reset());
return self.active_mut().preview.reset();
};

let Some(previewer) = PLUGIN.previewer(&hovered.url, mime) else {
return render!(self.active_mut().preview.reset());
return self.active_mut().preview.reset();
};

let opt = opt.into() as Opt;
Expand Down
2 changes: 1 addition & 1 deletion yazi-core/src/tab/commands/preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl TryFrom<Cmd> for Opt {
impl Tab {
pub fn preview(&mut self, opt: impl TryInto<Opt>) {
let Some(hovered) = self.current.hovered().map(|h| &h.url) else {
return render!(self.preview.reset());
return self.preview.reset();
};

let Ok(opt) = opt.try_into() else {
Expand Down
47 changes: 23 additions & 24 deletions yazi-core/src/tab/preview.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::time::Duration;
use std::{borrow::Cow, ops::Not, time::Duration};

use tokio::{pin, task::JoinHandle};
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
Expand All @@ -7,7 +7,7 @@ use yazi_adapter::ADAPTOR;
use yazi_config::PLUGIN;
use yazi_fs::Files;
use yazi_plugin::{external::Highlighter, isolate, utils::PreviewLock};
use yazi_shared::{MIME_DIR, fs::{Cha, File, FilesOp, Url}};
use yazi_shared::{MIME_DIR, fs::{Cha, File, FilesOp, Url}, render};

#[derive(Default)]
pub struct Preview {
Expand All @@ -19,32 +19,30 @@ pub struct Preview {
}

impl Preview {
pub fn go(&mut self, file: File, mime: &str, force: bool) {
if !force && self.content_unchanged(&file.url, file.cha) {
pub fn go(&mut self, file: File, mime: Cow<'static, str>, force: bool) {
if mime.is_empty() {
return; // Wait till mimetype is resolved to avoid flickering
} else if !force && self.same_lock(&file, &mime) {
return;
}

let Some(previewer) = PLUGIN.previewer(&file.url, mime) else {
self.reset();
return;
let Some(previewer) = PLUGIN.previewer(&file.url, &mime) else {
return self.reset();
};

self.abort();
if previewer.sync {
isolate::peek_sync(&previewer.run, file, self.skip);
isolate::peek_sync(&previewer.run, file, mime, self.skip);
} else {
self.previewer_ct = Some(isolate::peek(&previewer.run, file, self.skip));
self.previewer_ct = Some(isolate::peek(&previewer.run, file, mime, self.skip));
}
}

pub fn go_folder(&mut self, file: File, dir: Option<Cha>, force: bool) {
let (cha, cwd) = (file.cha, file.url_owned());
self.go(file, MIME_DIR, force);

if self.content_unchanged(&cwd, cha) {
return;
}
let cwd = self.same_file(&file, MIME_DIR).not().then(|| file.url_owned());
self.go(file, Cow::Borrowed(MIME_DIR), force);

let Some(cwd) = cwd else { return };
self.folder_loader.take().map(|h| h.abort());
self.folder_loader = Some(tokio::spawn(async move {
let Some(new) = Files::assert_stale(&cwd, dir.unwrap_or(Cha::dummy())).await else {
Expand All @@ -71,10 +69,10 @@ impl Preview {
}

#[inline]
pub fn reset(&mut self) -> bool {
pub fn reset(&mut self) {
self.abort();
ADAPTOR.image_hide().ok();
self.lock.take().is_some()
render!(self.lock.take().is_some())
}

#[inline]
Expand All @@ -84,15 +82,16 @@ impl Preview {
}

#[inline]
pub fn same_url(&self, url: &Url) -> bool {
matches!(self.lock, Some(ref lock) if lock.url == *url)
pub fn same_url(&self, url: &Url) -> bool { self.lock.as_ref().is_some_and(|l| *url == l.url) }

#[inline]
pub fn same_file(&self, file: &File, mime: &str) -> bool {
self.same_url(&file.url)
&& self.lock.as_ref().is_some_and(|l| file.cha.hits(l.cha) && mime == l.mime)
}

#[inline]
fn content_unchanged(&self, url: &Url, cha: Cha) -> bool {
match &self.lock {
Some(l) => *url == l.url && self.skip == l.skip && cha.hits(l.cha),
None => false,
}
pub fn same_lock(&self, file: &File, mime: &str) -> bool {
self.same_file(file, mime) && self.lock.as_ref().is_some_and(|l| self.skip == l.skip)
}
}
6 changes: 3 additions & 3 deletions yazi-fm/src/app/commands/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ use crossterm::{execute, queue, terminal::{BeginSynchronizedUpdate, EndSynchroni
use ratatui::{CompletedFrame, backend::{Backend, CrosstermBackend}, buffer::Buffer};
use scopeguard::defer;
use yazi_plugin::elements::COLLISION;
use yazi_shared::event::NEED_RENDER;

use crate::{app::App, lives::Lives, root::Root};

impl App {
pub(crate) fn render(&mut self) {
let Some(term) = &mut self.term else {
return;
};
NEED_RENDER.store(false, Ordering::Relaxed);
let Some(term) = &mut self.term else { return };

queue!(stderr(), BeginSynchronizedUpdate).ok();
defer! { execute!(stderr(), EndSynchronizedUpdate).ok(); }
Expand Down
13 changes: 11 additions & 2 deletions yazi-plugin/src/isolate/peek.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::borrow::Cow;

use mlua::{ExternalError, ExternalResult, HookTriggers, Table, TableExt};
use tokio::{runtime::Handle, select};
use tokio_util::sync::CancellationToken;
Expand All @@ -8,7 +10,12 @@ use yazi_shared::{Layer, emit, event::Cmd};
use super::slim_lua;
use crate::{LUA, Opt, OptCallback, bindings::{Cast, Window}, elements::Rect, file::File, loader::LOADER};

pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> CancellationToken {
pub fn peek(
cmd: &Cmd,
file: yazi_shared::fs::File,
mime: Cow<'static, str>,
skip: usize,
) -> CancellationToken {
let ct = CancellationToken::new();

let name = cmd.name.to_owned();
Expand All @@ -31,6 +38,7 @@ pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> Cancellation
return Err("unloaded plugin".into_lua_err());
};
plugin.raw_set("file", File::cast(&lua, file)?)?;
plugin.raw_set("_mime", mime)?;
plugin.raw_set("skip", skip)?;
plugin.raw_set("area", Rect::cast(&lua, LAYOUT.load().preview)?)?;
plugin.raw_set("window", Window::default())?;
Expand All @@ -55,9 +63,10 @@ pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> Cancellation
ct
}

pub fn peek_sync(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) {
pub fn peek_sync(cmd: &Cmd, file: yazi_shared::fs::File, mime: Cow<'static, str>, skip: usize) {
let cb: OptCallback = Box::new(move |_, plugin| {
plugin.raw_set("file", File::cast(&LUA, file)?)?;
plugin.raw_set("_mime", mime)?;
plugin.raw_set("skip", skip)?;
plugin.raw_set("area", Rect::cast(&LUA, LAYOUT.load().preview)?)?;
plugin.raw_set("window", Window::default())?;
Expand Down
13 changes: 8 additions & 5 deletions yazi-plugin/src/utils/preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use super::Utils;
use crate::{bindings::Window, cast_to_renderable, elements::{Paragraph, RectRef, Renderable, WRAP, WRAP_NO}, external::Highlighter, file::FileRef};

pub struct PreviewLock {
pub url: yazi_shared::fs::Url,
pub cha: yazi_shared::fs::Cha,
pub url: yazi_shared::fs::Url,
pub cha: yazi_shared::fs::Cha,
pub mime: String,

pub skip: usize,
pub window: Window,
Expand All @@ -18,10 +19,12 @@ impl<'a> TryFrom<Table<'a>> for PreviewLock {
type Error = mlua::Error;

fn try_from(t: Table) -> Result<Self, Self::Error> {
let file: FileRef = t.raw_get("file")?;
let file: FileRef = t.raw_get("file")?; // TODO: use `_file` instead of `file`
Ok(Self {
cha: file.cha,
url: file.url_owned(),
url: file.url_owned(),
cha: file.cha,
mime: t.raw_get("_mime")?,

skip: t.raw_get("skip")?,
window: t.raw_get("window")?,
data: Default::default(),
Expand Down

0 comments on commit 5b66192

Please sign in to comment.