mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
..
This commit is contained in:
parent
5a6179005c
commit
358ce77581
9 changed files with 67 additions and 45 deletions
|
|
@ -128,16 +128,17 @@ impl App {
|
|||
manager.refresh();
|
||||
}
|
||||
Event::Files(op) => {
|
||||
let read = matches!(op, FilesOp::Read(..));
|
||||
let calc = matches!(op, FilesOp::Full(..) | FilesOp::Part(..));
|
||||
let b = match op {
|
||||
FilesOp::Read(..) => manager.update_read(op),
|
||||
FilesOp::Full(..) => manager.update_read(op),
|
||||
FilesOp::Part(..) => manager.update_read(op),
|
||||
FilesOp::Size(..) => manager.update_read(op),
|
||||
FilesOp::IOErr(..) => manager.update_ioerr(op),
|
||||
};
|
||||
if b {
|
||||
emit!(Render);
|
||||
}
|
||||
if read {
|
||||
if calc {
|
||||
tasks.precache_size(&manager.current().files);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
use std::{collections::{BTreeMap, BTreeSet}, mem, ops::Deref, time::Duration};
|
||||
use std::{collections::{BTreeMap, BTreeSet}, mem, ops::Deref, sync::atomic::Ordering};
|
||||
|
||||
use anyhow::Result;
|
||||
use config::manager::SortBy;
|
||||
use shared::Url;
|
||||
use tokio::{fs, select, sync::mpsc::{self, UnboundedReceiver}, time::sleep};
|
||||
use tokio::{fs, select, sync::mpsc::{self, UnboundedReceiver}};
|
||||
|
||||
use super::{File, FilesSorter};
|
||||
use super::{File, FilesSorter, FILES_VERSION};
|
||||
|
||||
pub struct Files {
|
||||
items: Vec<File>,
|
||||
hidden: Vec<File>,
|
||||
items: Vec<File>,
|
||||
hidden: Vec<File>,
|
||||
version: u64,
|
||||
|
||||
sizes: BTreeMap<Url, u64>,
|
||||
selected: BTreeSet<Url>,
|
||||
|
|
@ -21,8 +22,9 @@ pub struct Files {
|
|||
impl Default for Files {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
items: Default::default(),
|
||||
hidden: Default::default(),
|
||||
items: Default::default(),
|
||||
hidden: Default::default(),
|
||||
version: Default::default(),
|
||||
|
||||
sizes: Default::default(),
|
||||
selected: Default::default(),
|
||||
|
|
@ -108,8 +110,22 @@ impl Files {
|
|||
applied
|
||||
}
|
||||
|
||||
pub fn update_read(&mut self, items: Vec<File>) -> bool {
|
||||
pub fn update_full(&mut self, mut items: Vec<File>) -> bool {
|
||||
if !self.show_hidden {
|
||||
(self.hidden, items) = items.into_iter().partition(|f| f.is_hidden);
|
||||
}
|
||||
self.sorter.sort(&mut items);
|
||||
self.items = items;
|
||||
self.version = FILES_VERSION.fetch_add(1, Ordering::Relaxed);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn update_part(&mut self, version: u64, items: Vec<File>) -> bool {
|
||||
if !items.is_empty() {
|
||||
if version != self.version {
|
||||
return false;
|
||||
}
|
||||
|
||||
if self.show_hidden {
|
||||
self.items.extend(items);
|
||||
} else {
|
||||
|
|
@ -122,6 +138,7 @@ impl Files {
|
|||
return true;
|
||||
}
|
||||
|
||||
self.version = version;
|
||||
if !self.items.is_empty() {
|
||||
self.items.clear();
|
||||
self.hidden.clear();
|
||||
|
|
|
|||
|
|
@ -1,12 +1,16 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::{collections::BTreeMap, sync::atomic::{AtomicU64, Ordering}};
|
||||
|
||||
use shared::Url;
|
||||
|
||||
use super::File;
|
||||
use crate::emit;
|
||||
|
||||
pub(super) static FILES_VERSION: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FilesOp {
|
||||
Read(Url, Vec<File>),
|
||||
Full(Url, Vec<File>),
|
||||
Part(Url, u64, Vec<File>),
|
||||
Size(Url, BTreeMap<Url, u64>),
|
||||
IOErr(Url),
|
||||
}
|
||||
|
|
@ -15,7 +19,8 @@ impl FilesOp {
|
|||
#[inline]
|
||||
pub fn url(&self) -> Url {
|
||||
match self {
|
||||
Self::Read(url, _) => url,
|
||||
Self::Full(url, _) => url,
|
||||
Self::Part(url, ..) => url,
|
||||
Self::Size(url, _) => url,
|
||||
Self::IOErr(url) => url,
|
||||
}
|
||||
|
|
@ -23,5 +28,9 @@ impl FilesOp {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clear(url: &Url) -> Self { Self::Read(url.clone(), Vec::new()) }
|
||||
pub fn prepare(url: &Url) -> u64 {
|
||||
let version = FILES_VERSION.fetch_add(1, Ordering::Relaxed);
|
||||
emit!(Files(Self::Part(url.clone(), version, Vec::new())));
|
||||
version
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,8 @@ impl From<&Url> for Folder {
|
|||
impl Folder {
|
||||
pub fn update(&mut self, op: FilesOp) -> bool {
|
||||
let b = match op {
|
||||
FilesOp::Read(_, items) => self.files.update_read(items),
|
||||
FilesOp::Full(_, items) => self.files.update_full(items),
|
||||
FilesOp::Part(_, version, items) => self.files.update_part(version, items),
|
||||
FilesOp::Size(_, items) => self.files.update_size(items),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ impl Manager {
|
|||
|
||||
pub fn update_ioerr(&mut self, op: FilesOp) -> bool {
|
||||
let url = op.url();
|
||||
let op = FilesOp::clear(&url);
|
||||
let op = FilesOp::Full(url.clone(), Vec::new());
|
||||
|
||||
if url == *self.cwd() {
|
||||
self.current_mut().update(op);
|
||||
|
|
|
|||
|
|
@ -89,17 +89,17 @@ impl Preview {
|
|||
return;
|
||||
};
|
||||
|
||||
if files.is_some() {
|
||||
emit!(Files(FilesOp::Full(url, UnboundedReceiverStream::new(rx).collect().await)));
|
||||
return;
|
||||
}
|
||||
|
||||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(10000, Duration::from_millis(500));
|
||||
pin!(rx);
|
||||
|
||||
let mut first = false;
|
||||
let version = FilesOp::prepare(&url);
|
||||
while let Some(chunk) = rx.next().await {
|
||||
if first {
|
||||
emit!(Files(FilesOp::clear(&url)));
|
||||
first = false;
|
||||
}
|
||||
|
||||
emit!(Files(FilesOp::Read(url.clone(), chunk)));
|
||||
emit!(Files(FilesOp::Part(url.clone(), version, chunk)));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -252,9 +252,9 @@ impl Tab {
|
|||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(1000, Duration::from_millis(300));
|
||||
pin!(rx);
|
||||
|
||||
emit!(Files(FilesOp::clear(&cwd)));
|
||||
let version = FilesOp::prepare(&cwd);
|
||||
while let Some(chunk) = rx.next().await {
|
||||
emit!(Files(FilesOp::Read(cwd.clone(), chunk)));
|
||||
emit!(Files(FilesOp::Part(cwd.clone(), version, chunk)));
|
||||
}
|
||||
Ok(())
|
||||
}));
|
||||
|
|
@ -268,8 +268,7 @@ impl Tab {
|
|||
if self.current.cwd.is_search() {
|
||||
self.preview_reset_image();
|
||||
|
||||
let cwd = self.current.cwd.clone();
|
||||
let rep = self.history_new(&cwd);
|
||||
let rep = self.history_new(&self.current.cwd.to_none());
|
||||
drop(mem::replace(&mut self.current, rep));
|
||||
emit!(Refresh);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -174,9 +174,6 @@ impl Watcher {
|
|||
return;
|
||||
};
|
||||
|
||||
let rx = UnboundedReceiverStream::new(rx).chunks_timeout(10000, Duration::from_millis(500));
|
||||
pin!(rx);
|
||||
|
||||
let linked_files = |files: &[File], ori: &Url| -> Vec<File> {
|
||||
let mut new = Vec::with_capacity(files.len());
|
||||
for file in files {
|
||||
|
|
@ -187,20 +184,11 @@ impl Watcher {
|
|||
new
|
||||
};
|
||||
|
||||
let mut first = true;
|
||||
while let Some(chunk) = rx.next().await {
|
||||
if first {
|
||||
emit!(Files(FilesOp::clear(url)));
|
||||
for ori in &linked {
|
||||
emit!(Files(FilesOp::clear(ori)));
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
|
||||
for ori in &linked {
|
||||
emit!(Files(FilesOp::Read(ori.clone(), linked_files(&chunk, ori))));
|
||||
}
|
||||
emit!(Files(FilesOp::Read(url.clone(), chunk)));
|
||||
let files: Vec<_> = UnboundedReceiverStream::new(rx).collect().await;
|
||||
for ori in linked {
|
||||
let files = linked_files(&files, &ori);
|
||||
emit!(Files(FilesOp::Full(ori, files)));
|
||||
}
|
||||
emit!(Files(FilesOp::Full(url.clone(), files)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,13 @@ impl Url {
|
|||
#[inline]
|
||||
pub fn is_none(&self) -> bool { self.scheme == UrlScheme::None }
|
||||
|
||||
#[inline]
|
||||
pub fn to_none(&self) -> Self {
|
||||
let mut url = self.clone();
|
||||
url.scheme = UrlScheme::None;
|
||||
url
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_search(&self) -> bool { self.scheme == UrlScheme::Search }
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue