fix: set a dedicated Mimetype agency to reconcile regular files and search results (#1627)

This commit is contained in:
三咲雅 · Misaki Masa 2024-09-10 13:39:44 +08:00 committed by GitHub
parent b87361023f
commit 61c0db8630
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 77 additions and 24 deletions

View file

@ -41,7 +41,7 @@ impl Manager {
let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]);
for u in selected {
if self.mimetype.contains_key(u) {
if self.mimetype.contains(u) {
done.push((u.clone(), String::new()));
} else if self.guess_folder(u) {
done.push((u.clone(), MIME_DIR.to_owned()));
@ -78,7 +78,7 @@ impl Manager {
.targets
.into_iter()
.filter_map(|(u, m)| {
Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.get(&u).cloned()).map(|m| (u, m))
Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.get_owned(&u)).map(|m| (u, m))
})
.collect();

View file

@ -55,7 +55,7 @@ impl Manager {
return;
}
let mime = self.mimetype.get(hovered.url()).cloned().unwrap_or_default();
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);

View file

@ -1,12 +1,10 @@
use std::collections::HashMap;
use ratatui::layout::Rect;
use yazi_adapter::Dimension;
use yazi_config::popup::{Origin, Position};
use yazi_fs::Folder;
use yazi_shared::fs::{File, Url};
use super::{Tabs, Watcher, Yanked};
use super::{Mimetype, Tabs, Watcher, Yanked};
use crate::tab::Tab;
pub struct Manager {
@ -14,7 +12,7 @@ pub struct Manager {
pub yanked: Yanked,
pub(super) watcher: Watcher,
pub mimetype: HashMap<Url, String>,
pub mimetype: Mimetype,
}
impl Manager {

View file

@ -0,0 +1,46 @@
use std::{collections::HashMap, path::PathBuf};
use yazi_shared::fs::{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() {
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())
}
#[inline]
pub fn get_owned(&self, url: &Url) -> Option<String> { self.get(url).map(|s| s.to_owned()) }
#[inline]
pub fn contains(&self, url: &Url) -> bool {
match url.scheme() {
UrlScheme::Regular => self.0.contains_key(url.as_path()),
UrlScheme::Search => false,
UrlScheme::SearchItem => self.0.contains_key(url.as_path()),
UrlScheme::Archive => false,
}
}
pub fn extend(&mut self, iter: impl IntoIterator<Item = (Url, String)>) {
self.0.extend(iter.into_iter().filter_map(|(u, s)| {
Some((
match u.scheme() {
UrlScheme::Regular => u.into_path(),
UrlScheme::Search => None?,
UrlScheme::SearchItem => u.into_path(),
UrlScheme::Archive => None?,
},
s,
))
}))
}
}

View file

@ -1,12 +1,14 @@
mod commands;
mod linked;
mod manager;
mod mimetype;
mod tabs;
mod watcher;
mod yanked;
pub use linked::*;
pub use manager::*;
pub use mimetype::*;
pub use tabs::*;
pub use watcher::*;
pub use yanked::*;

View file

@ -1,18 +1,16 @@
use std::collections::HashMap;
use yazi_config::{manager::SortBy, plugin::MAX_PREWORKERS, PLUGIN};
use yazi_fs::Files;
use yazi_shared::{fs::{File, Url}, MIME_DIR};
use yazi_shared::{fs::File, MIME_DIR};
use super::Tasks;
use crate::manager::Mimetype;
impl Tasks {
pub fn fetch_paged(&self, paged: &[File], mimetype: &HashMap<Url, String>) {
pub fn fetch_paged(&self, paged: &[File], mimetype: &Mimetype) {
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()).map(|s| &**s).unwrap_or_default() };
let mime = if f.is_dir() { MIME_DIR } else { mimetype.get(f.url()).unwrap_or_default() };
let factors = |s: &str| match s {
"mime" => !mime.is_empty(),
_ => false,
@ -36,11 +34,10 @@ impl Tasks {
}
}
pub fn preload_paged(&self, paged: &[File], mimetype: &HashMap<Url, String>) {
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()).map(|s| &**s).unwrap_or_default() };
let mime = if f.is_dir() { MIME_DIR } else { mimetype.get(f.url()).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,
@ -52,7 +49,7 @@ impl Tasks {
}
}
pub fn prework_affected(&self, affected: &[File], mimetype: &HashMap<Url, String>) {
pub fn prework_affected(&self, affected: &[File], mimetype: &Mimetype) {
let mask = PLUGIN.fetchers_mask();
{
let mut loaded = self.scheduler.prework.loaded.lock();

View file

@ -43,7 +43,7 @@ impl File {
});
reg.add_method("mime", |lua, me, ()| {
let cx = lua.named_registry_value::<CtxRef>("cx")?;
Ok(cx.manager.mimetype.get(me.url()).cloned())
Ok(cx.manager.mimetype.get_owned(me.url()))
});
reg.add_method("prefix", |lua, me, ()| {
if !me.folder().loc.is_search() {
@ -59,7 +59,7 @@ impl File {
let mime = if me.is_dir() {
MIME_DIR
} else {
cx.manager.mimetype.get(me.url()).map(|x| &**x).unwrap_or_default()
cx.manager.mimetype.get(me.url()).unwrap_or_default()
};
Ok(THEME.filetypes.iter().find(|&x| x.matches(me, mime)).map(|x| Style::from(x.style)))

View file

@ -17,6 +17,7 @@ pub enum UrlScheme {
#[default]
Regular,
Search,
SearchItem,
Archive,
}
@ -98,12 +99,12 @@ impl AsRef<OsStr> for Url {
impl Display for Url {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
if self.scheme == UrlScheme::Regular {
if matches!(self.scheme, UrlScheme::Regular | UrlScheme::SearchItem) {
return f.write_str(&self.path.to_string_lossy());
}
let scheme = match self.scheme {
UrlScheme::Regular => unreachable!(),
UrlScheme::Regular | UrlScheme::SearchItem => unreachable!(),
UrlScheme::Search => "search://",
UrlScheme::Archive => "archive://",
};
@ -128,7 +129,8 @@ impl Url {
let url = Self::from(self.path.join(path));
match self.scheme {
UrlScheme::Regular => url,
UrlScheme::Search => url.into_search(),
UrlScheme::Search => url.into_search_item(),
UrlScheme::SearchItem => url,
UrlScheme::Archive => url.into_archive(),
}
}
@ -140,6 +142,7 @@ impl Url {
match self.scheme {
UrlScheme::Regular => url,
UrlScheme::Search => url,
UrlScheme::SearchItem => url,
UrlScheme::Archive => url,
}
})
@ -187,8 +190,8 @@ impl Url {
}
#[inline]
pub fn into_search(mut self) -> Self {
self.scheme = UrlScheme::Search;
pub fn into_search_item(mut self) -> Self {
self.scheme = UrlScheme::SearchItem;
self.frag = String::new();
self
}
@ -208,10 +211,17 @@ impl Url {
self
}
// --- Scheme
#[inline]
pub fn scheme(&self) -> UrlScheme { self.scheme }
// --- Path
#[inline]
pub fn set_path(&mut self, path: PathBuf) { self.path = path; }
#[inline]
pub fn into_path(self) -> PathBuf { self.path }
// --- Frag
#[inline]
pub fn frag(&self) -> &str { &self.frag }