feat: make the hover state for reveal, sort, and hidden commands stable (#2657)

This commit is contained in:
三咲雅 · Misaki Masa 2025-04-21 22:44:15 +08:00 committed by sxyazi
parent 7169e19ff0
commit a29dbb9f06
No known key found for this signature in database
16 changed files with 77 additions and 76 deletions

View file

@ -1 +1 @@
{"version":"0.2","language":"en","words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition"],"flagWords":[]}
{"version":"0.2","language":"en","flagWords":[],"words":["Punct","KEYMAP","splitn","crossterm","YAZI","peekable","ratatui","syntect","pbpaste","pbcopy","oneshot","Posix","Lsar","XADDOS","zoxide","cands","Deque","precache","imageops","IFBLK","IFCHR","IFDIR","IFIFO","IFLNK","IFMT","IFSOCK","IRGRP","IROTH","IRUSR","ISGID","ISUID","ISVTX","IWGRP","IWOTH","IWUSR","IXGRP","IXOTH","IXUSR","libc","winsize","TIOCGWINSZ","xpixel","ypixel","ioerr","appender","Catppuccin","macchiato","gitmodules","Dotfiles","bashprofile","vimrc","flac","webp","exiftool","mediainfo","ripgrep","indexmap","indexmap","unwatch","canonicalize","serde","fsevent","Ueberzug","iterm","wezterm","sixel","chafa","ueberzugpp","Konsole","Überzug","pkgs","pdftoppm","poppler","singlefile","jpegopt","EXIF","rustfmt","mktemp","nanos","xclip","xsel","natord","Mintty","nixos","nixpkgs","SIGTSTP","SIGCONT","SIGCONT","mlua","nonstatic","userdata","metatable","natsort","backstack","luajit","Succ","Succ","cand","fileencoding","foldmethod","lightgreen","darkgray","lightred","lightyellow","lightcyan","nushell","msvc","aarch","linemode","sxyazi","rsplit","ZELLIJ","bitflags","bitflags","USERPROFILE","Neovim","vergen","gitcl","Renderable","preloaders","prec","Upserting","prio","Ghostty","Catmull","Lanczos","cmds","unyank","scrolloff","headsup","unsub","uzers","scopeguard","SPDLOG","globset","filetime","magick","magick","prefetcher","Prework","prefetchers","PREWORKERS","conds","translit","rxvt","Urxvt","realpath","realname","REPARSE","hardlink","hardlinking","nlink","nlink","linemodes","SIGSTOP","sevenzip","rsplitn","replacen","DECSET","DECRQM","repeek","cwds","tcsi","Hyprland","Wayfire","SWAYSOCK","btime","nsec","codegen","gethostname","fchmod","fdfind","Rustc","rustc","ffprobe","vframes","luma","obase","outln","errln","tmtheme","twox","cfgs","fstype","objc","rdev","runloop","exfat","rclone","DECRQSS","DECSCUSR","libvterm","Uninit","lockin","rposition","resvg"]}

View file

@ -93,6 +93,7 @@ impl Actions {
writeln!(s, " zoxide : {}", Self::process_output("zoxide", "--version"))?;
#[rustfmt::skip]
writeln!(s, " 7zz/7z : {} / {}", Self::process_output("7zz", "i"), Self::process_output("7z", "i"))?;
writeln!(s, " resvg : {}", Self::process_output("resvg", "--version"))?;
writeln!(s, " jq : {}", Self::process_output("jq", "--version"))?;
writeln!(s, "\nClipboard")?;

View file

@ -1,50 +0,0 @@
use yazi_dds::Pubsub;
use yazi_macro::render;
use yazi_shared::{Id, event::{CmdCow, Data}, url::{Url, Urn}};
use crate::mgr::Mgr;
struct Opt {
url: Option<Url>,
tab: Option<Id>,
}
impl From<CmdCow> for Opt {
fn from(mut c: CmdCow) -> Self {
Self { url: c.take_first_url(), tab: c.get("tab").and_then(Data::as_id) }
}
}
impl From<Option<Url>> for Opt {
fn from(url: Option<Url>) -> Self { Self { url, tab: None } }
}
impl Mgr {
#[yazi_codegen::command]
pub fn hover(&mut self, opt: Opt) {
if let Some(u) = opt.url {
self.hover_do(u, opt.tab);
} else {
self.current_or_mut(opt.tab).arrow(0);
}
// Refresh watcher
self.watch(());
// Publish through DDS
Pubsub::pub_from_hover(self.active().id, self.hovered().map(|h| &h.url));
}
fn hover_do(&mut self, url: Url, tab: Option<Id>) {
// Hover on the file
if let Ok(p) = url.strip_prefix(&self.current_or(tab).url) {
render!(self.current_or_mut(tab).hover(Urn::new(p)));
}
// Turn on tracing
if self.current_or(tab).hovered().is_some_and(|h| h.url == url) {
// `hover(Some)` occurs after user actions, such as create, rename, reveal, etc.
// At this point, it's intuitive to track the location of the file regardless.
self.current_or_mut(tab).trace = Some(url.urn_owned());
}
}
}

View file

@ -3,7 +3,6 @@ yazi_macro::mod_flat!(
close
create
hardlink
hover
link
open
paste

View file

@ -21,8 +21,8 @@ impl Mgr {
self.watcher.trigger_dirs(&[self.current()]);
}
self.watch(());
self.peek(false);
self.watch(());
self.update_paged((), tasks);
tasks.prework_sorted(&self.current().files);

View file

@ -30,10 +30,12 @@ impl Mgr {
}
render!(self.yanked.catchup_revision(false));
self.active_mut().apply_files_attrs();
if revision != self.current().files.revision {
self.active_mut().apply_files_attrs();
self.hover(None);
self.active_mut().hover(None);
self.peek(false);
self.watch(());
self.update_paged((), tasks);
}
}

View file

@ -36,8 +36,10 @@ impl Tab {
}
}
MgrProxy::hover(None, self.id);
self.hover(None);
MgrProxy::peek(false);
MgrProxy::watch();
render!();
}
}

View file

@ -27,8 +27,9 @@ impl Tab {
self.current.repos(hovered.as_ref());
if self.hovered().map(|f| f.urn()) != hovered.as_ref().map(|u| u.as_urn()) {
MgrProxy::hover(None, self.id);
self.hover(None);
MgrProxy::peek(false);
MgrProxy::watch();
}
render!();

View file

@ -15,8 +15,9 @@ impl Tab {
self.apply_files_attrs();
if hovered.as_ref() != self.hovered().map(|f| &f.url) {
MgrProxy::hover(hovered, self.id);
self.hover(hovered);
MgrProxy::peek(false);
MgrProxy::watch();
} else if self.hovered().is_some_and(|f| f.is_dir()) {
MgrProxy::peek(true);
}

View file

@ -0,0 +1,44 @@
use yazi_dds::Pubsub;
use yazi_macro::render;
use yazi_shared::{event::CmdCow, url::{Url, Urn}};
use crate::tab::Tab;
struct Opt {
url: Option<Url>,
}
impl From<CmdCow> for Opt {
fn from(mut c: CmdCow) -> Self { Self { url: c.take_first_url() } }
}
impl From<Option<Url>> for Opt {
fn from(url: Option<Url>) -> Self { Self { url } }
}
impl Tab {
#[yazi_codegen::command]
pub fn hover(&mut self, opt: Opt) {
if let Some(u) = opt.url {
self.hover_do(u);
} else {
self.current.arrow(0);
}
// Publish through DDS
Pubsub::pub_from_hover(self.id, self.hovered().map(|h| &h.url));
}
fn hover_do(&mut self, url: Url) {
// Hover on the file
if let Ok(p) = url.strip_prefix(self.cwd()) {
render!(self.current.hover(Urn::new(p)));
}
// Turn on tracing
if self.hovered().is_some_and(|h| h.url == url) {
// `hover(Some)` occurs after user actions, such as create, rename, reveal, etc.
// At this point, it's intuitive to track the location of the file regardless.
self.current.trace = Some(url.urn_owned());
}
}
}

View file

@ -10,8 +10,10 @@ yazi_macro::mod_flat!(
find
find_arrow
find_do
follow
forward
hidden
hover
leave
linemode
reveal
@ -23,5 +25,4 @@ yazi_macro::mod_flat!(
update_peeked
update_spotted
visual_mode
follow,
);

View file

@ -25,14 +25,20 @@ impl From<Url> for Opt {
impl Tab {
#[yazi_codegen::command]
pub fn reveal(&mut self, opt: Opt) {
let Some(parent) = opt.target.parent_url() else {
let Some((parent, child)) = opt.target.pair() else {
return;
};
self.cd(parent.clone());
// TODO
FilesOp::Creating(parent, vec![File::from_dummy(opt.target.clone(), None)]).emit();
MgrProxy::hover(Some(opt.target), self.id);
self.current.hover(child.as_urn());
if self.hovered().is_none_or(|f| &child != f.urn()) {
let op = FilesOp::Creating(parent, vec![File::from_dummy(opt.target.clone(), None)]);
self.current.update_pub(self.id, op);
}
self.hover(Some(opt.target));
MgrProxy::peek(false);
MgrProxy::watch();
}
}

View file

@ -19,11 +19,11 @@ impl Tab {
pref.sort_translit = c.maybe_bool("translit").unwrap_or(pref.sort_translit);
self.apply_files_attrs();
MgrProxy::hover(None, self.id);
MgrProxy::peek(false);
MgrProxy::update_paged();
self.hover(None);
tasks.prework_sorted(&self.current.files);
MgrProxy::peek(false);
MgrProxy::watch();
MgrProxy::update_paged();
}
}

View file

@ -19,7 +19,7 @@ impl App {
self.reflow(());
self.cx.current_mut().sync_page(true);
self.cx.mgr.hover(None);
self.cx.current_mut().arrow(0);
self.cx.mgr.peek(false);
self.cx.mgr.parent_mut().map(|f| f.arrow(0));
}

View file

@ -77,7 +77,6 @@ impl<'a> Executor<'a> {
on!(MGR, update_mimes, &self.app.cx.tasks);
on!(MGR, update_paged, &self.app.cx.tasks);
on!(MGR, update_yanked);
on!(MGR, hover);
on!(MGR, watch);
on!(MGR, peek);
on!(MGR, seek);

View file

@ -1,5 +1,5 @@
use yazi_macro::emit;
use yazi_shared::{Id, event::Cmd, url::Url};
use yazi_shared::{event::Cmd, url::Url};
use crate::options::OpenDoOpt;
@ -16,11 +16,6 @@ impl MgrProxy {
emit!(Call(Cmd::new("mgr:peek").with_bool("force", force)));
}
#[inline]
pub fn hover(url: Option<Url>, tab: Id) {
emit!(Call(Cmd::args("mgr:hover", &url.map_or_else(Vec::new, |u| vec![u])).with("tab", tab)));
}
#[inline]
pub fn watch() {
emit!(Call(Cmd::new("mgr:watch")));