From 358ce775812cbdbf897f73fceb1149d7b2d31cb7 Mon Sep 17 00:00:00 2001 From: sxyazi Date: Wed, 6 Sep 2023 20:05:14 +0800 Subject: [PATCH] .. --- app/src/app.rs | 7 +++--- core/src/files/files.rs | 33 ++++++++++++++++++++++------- core/src/files/op.rs | 17 +++++++++++---- core/src/manager/folder.rs | 3 ++- core/src/manager/manager.rs | 2 +- core/src/manager/preview/preview.rs | 14 ++++++------ core/src/manager/tab.rs | 7 +++--- core/src/manager/watcher.rs | 22 +++++-------------- shared/src/url.rs | 7 ++++++ 9 files changed, 67 insertions(+), 45 deletions(-) diff --git a/app/src/app.rs b/app/src/app.rs index ab83a0ab..54328bf0 100644 --- a/app/src/app.rs +++ b/app/src/app.rs @@ -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); } } diff --git a/core/src/files/files.rs b/core/src/files/files.rs index 1ad66f5a..0a81a05f 100644 --- a/core/src/files/files.rs +++ b/core/src/files/files.rs @@ -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, - hidden: Vec, + items: Vec, + hidden: Vec, + version: u64, sizes: BTreeMap, selected: BTreeSet, @@ -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) -> bool { + pub fn update_full(&mut self, mut items: Vec) -> 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) -> 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(); diff --git a/core/src/files/op.rs b/core/src/files/op.rs index 4d3723c0..2ed3191a 100644 --- a/core/src/files/op.rs +++ b/core/src/files/op.rs @@ -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), + Full(Url, Vec), + Part(Url, u64, Vec), Size(Url, BTreeMap), 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 + } } diff --git a/core/src/manager/folder.rs b/core/src/manager/folder.rs index d9bb6166..3f765477 100644 --- a/core/src/manager/folder.rs +++ b/core/src/manager/folder.rs @@ -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!(), }; diff --git a/core/src/manager/manager.rs b/core/src/manager/manager.rs index 87be9ce2..3bdd93db 100644 --- a/core/src/manager/manager.rs +++ b/core/src/manager/manager.rs @@ -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); diff --git a/core/src/manager/preview/preview.rs b/core/src/manager/preview/preview.rs index 6ab350d6..31a1f6db 100644 --- a/core/src/manager/preview/preview.rs +++ b/core/src/manager/preview/preview.rs @@ -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))); } })); } diff --git a/core/src/manager/tab.rs b/core/src/manager/tab.rs index 3a062dff..25a44637 100644 --- a/core/src/manager/tab.rs +++ b/core/src/manager/tab.rs @@ -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); } diff --git a/core/src/manager/watcher.rs b/core/src/manager/watcher.rs index bde32398..0bb5aa4c 100644 --- a/core/src/manager/watcher.rs +++ b/core/src/manager/watcher.rs @@ -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 { 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))); } } diff --git a/shared/src/url.rs b/shared/src/url.rs index 16a24449..72a8172a 100644 --- a/shared/src/url.rs +++ b/shared/src/url.rs @@ -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 }