This commit is contained in:
sxyazi 2023-09-06 20:05:14 +08:00
parent 5a6179005c
commit 358ce77581
No known key found for this signature in database
9 changed files with 67 additions and 45 deletions

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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
}
}

View file

@ -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!(),
};

View file

@ -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);

View file

@ -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)));
}
}));
}

View file

@ -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);
}

View file

@ -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)));
}
}

View file

@ -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 }