fix: preserve open order for files with post-resolved mime-types (#2931)

Co-authored-by: TKperson <TKperson@users.noreply.github.com>
Co-authored-by: sxyazi <sxyazi@gmail.com>
This commit is contained in:
TKperson 2025-06-28 18:07:59 +08:00 committed by GitHub
parent 8ef28ec678
commit a8a1b5625b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 35 additions and 29 deletions

View file

@ -1,4 +1,4 @@
use std::borrow::Cow;
use std::{borrow::Cow, iter};
use tracing::error;
use yazi_config::{YAZI, popup::PickCfg};
@ -31,57 +31,60 @@ impl Mgr {
return;
};
let selected = if opt.hovered { vec![&hovered] } else { self.selected_or_hovered().collect() };
if Self::quit_with_selected(opt, &selected) {
let mut selected =
if opt.hovered { Box::new(iter::once(&hovered)) } else { self.selected_or_hovered() };
if Self::quit_with_selected(opt, &mut selected) {
return;
}
let cwd = self.cwd().clone();
let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]);
for u in selected {
if self.mimetype.contains(u) {
done.push((u.clone(), ""));
} else if self.guess_folder(u) {
done.push((u.clone(), MIME_DIR));
} else {
todo.push(u.clone());
}
}
let mut todo = vec![];
let targets: Vec<_> = selected
.cloned()
.enumerate()
.map(|(i, u)| {
if self.mimetype.contains(&u) {
(u, "")
} else if self.guess_folder(&u) {
(u, MIME_DIR)
} else {
todo.push(i);
(u, "")
}
})
.collect();
let cwd = self.cwd().clone();
if todo.is_empty() {
return self
.open_do(OpenDoOpt { cwd, hovered, targets: done, interactive: opt.interactive }, tasks);
.open_do(OpenDoOpt { cwd, hovered, targets, interactive: opt.interactive }, tasks);
}
tokio::spawn(async move {
let mut files = Vec::with_capacity(todo.len());
for u in todo {
if let Ok(f) = File::new(u).await {
for i in todo {
if let Ok(f) = File::new(targets[i].0.clone()).await {
files.push(f);
}
}
done.extend(files.iter().map(|f| (f.url_owned(), "")));
for (fetcher, files) in YAZI.plugin.mime_fetchers(files) {
if let Err(e) = isolate::fetch(CmdCow::from(&fetcher.run), files).await {
error!("Fetch mime failed on opening: {e}");
}
}
MgrProxy::open_do(OpenDoOpt { cwd, hovered, targets: done, interactive: opt.interactive });
MgrProxy::open_do(OpenDoOpt { cwd, hovered, targets, interactive: opt.interactive });
});
}
#[yazi_codegen::command]
pub fn open_do(&mut self, opt: OpenDoOpt, tasks: &Tasks) {
let targets: Vec<_> = opt
.targets
.into_iter()
.filter_map(|(u, m)| {
Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.by_url(&u)).map(|m| (u, m))
})
.collect();
let mut targets = opt.targets;
targets.iter_mut().filter(|(_, m)| m.is_empty()).for_each(|(u, m)| {
*m = self.mimetype.by_url(u).unwrap_or_default();
});
targets.retain(|(_, m)| !m.is_empty());
if targets.is_empty() {
return;
} else if !opt.interactive {

View file

@ -74,12 +74,15 @@ impl Mgr {
});
}
pub(super) fn quit_with_selected(opt: super::open::Opt, selected: &[&Url]) -> bool {
pub(super) fn quit_with_selected<'a, I>(opt: super::open::Opt, selected: I) -> bool
where
I: Iterator<Item = &'a Url>,
{
if opt.interactive || ARGS.chooser_file.is_none() {
return false;
}
let paths = selected.iter().fold(OsString::new(), |mut s, &u| {
let paths = selected.fold(OsString::new(), |mut s, u| {
s.push(u.as_os_str());
s.push("\n");
s

View file

@ -87,7 +87,7 @@ impl Tab {
pub fn selected_or_hovered(&self) -> Box<dyn Iterator<Item = &Url> + '_> {
if self.selected.is_empty() {
Box::new(self.hovered().map(|h| vec![&h.url]).unwrap_or_default().into_iter())
Box::new(self.hovered().map(|h| &h.url).into_iter())
} else {
Box::new(self.selected.keys())
}