diff --git a/app/src/status/left.rs b/app/src/status/left.rs index cf72e39d..6ab724fb 100644 --- a/app/src/status/left.rs +++ b/app/src/status/left.rs @@ -14,7 +14,7 @@ impl<'a> Left<'a> { impl<'a> Widget for Left<'a> { fn render(self, area: Rect, buf: &mut Buffer) { - let manager = self.cx.manager.current(); + let folder = self.cx.manager.current(); let mode = self.cx.manager.active().mode(); // Colors @@ -33,10 +33,14 @@ impl<'a> Widget for Left<'a> { primary.bg().fg(**secondary).add_modifier(Modifier::BOLD), )); - if let Some(h) = &manager.hovered { + if let Some(h) = &folder.hovered { // Length - if let Some(len) = h.length() { - spans.push(Span::styled(format!(" {} ", readable_size(len)), body.bg().fg(**primary))); + { + let size = if h.is_dir() { folder.files.size(h.url()) } else { None }; + spans.push(Span::styled( + format!(" {} ", readable_size(size.unwrap_or(h.length()))), + body.bg().fg(**primary), + )); spans.push(Span::styled(&separator.closing, body.fg())); } diff --git a/core/src/files/file.rs b/core/src/files/file.rs index fb6bc342..3e01c076 100644 --- a/core/src/files/file.rs +++ b/core/src/files/file.rs @@ -8,7 +8,7 @@ use tokio::fs; pub struct File { pub(super) url: Url, pub(super) meta: Metadata, - pub(super) length: Option, + pub(super) length: u64, pub(super) link_to: Option, pub(super) is_link: bool, pub(super) is_hidden: bool, @@ -30,7 +30,7 @@ impl File { link_to = fs::read_link(&url).await.map(Url::from).ok(); } - let length = if meta.is_dir() { None } else { Some(meta.len()) }; + let length = meta.len(); let is_hidden = url.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false); Self { url, meta, length, link_to, is_link, is_hidden } } @@ -76,7 +76,7 @@ impl File { // --- Length #[inline] - pub fn length(&self) -> Option { self.length } + pub fn length(&self) -> u64 { self.length } // --- Link to #[inline] diff --git a/core/src/files/files.rs b/core/src/files/files.rs index 2c69bba7..f17df4b4 100644 --- a/core/src/files/files.rs +++ b/core/src/files/files.rs @@ -126,7 +126,7 @@ impl Files { if !self.show_hidden { (self.hidden, items) = items.into_iter().partition(|f| f.is_hidden); } - self.sorter.sort(&mut items); + self.sorter.sort(&mut items, &self.sizes); self.items = items; self.version = FILES_VERSION.fetch_add(1, Ordering::Relaxed); true @@ -146,7 +146,7 @@ impl Files { self.hidden.extend(hidden); } - self.sorter.sort(&mut self.items); + self.sorter.sort(&mut self.items, &self.sizes); return true; } @@ -162,7 +162,7 @@ impl Files { pub fn update_size(&mut self, items: BTreeMap) -> bool { self.sizes.extend(items); if self.sorter.by == SortBy::Size { - self.sorter.sort(&mut self.items); + self.sorter.sort(&mut self.items, &self.sizes); } true } @@ -186,6 +186,10 @@ impl Files { #[inline] pub fn duplicate(&self, idx: usize) -> Option { self.items.get(idx).cloned() } + // --- Size + #[inline] + pub fn size(&self, url: &Url) -> Option { self.sizes.get(url).copied() } + // --- Selected pub fn selected(&self, pending: &BTreeSet, unset: bool) -> Vec<&File> { if self.selected.is_empty() && (unset || pending.is_empty()) { @@ -234,7 +238,7 @@ impl Files { return false; } self.sorter = sorter; - self.sorter.sort(&mut self.items) + self.sorter.sort(&mut self.items, &self.sizes) } // --- Show hidden @@ -248,7 +252,7 @@ impl Files { if state { self.items.append(&mut self.hidden); - self.sorter.sort(&mut self.items); + self.sorter.sort(&mut self.items, &self.sizes); } else { let items = mem::take(&mut self.items); (self.hidden, self.items) = items.into_iter().partition(|f| f.is_hidden); diff --git a/core/src/files/sorter.rs b/core/src/files/sorter.rs index b9f7789e..2a872618 100644 --- a/core/src/files/sorter.rs +++ b/core/src/files/sorter.rs @@ -1,6 +1,7 @@ -use std::{cmp::Ordering, mem}; +use std::{cmp::Ordering, collections::BTreeMap, mem}; use config::{manager::SortBy, MANAGER}; +use shared::Url; use super::File; @@ -22,7 +23,7 @@ impl Default for FilesSorter { } impl FilesSorter { - pub(super) fn sort(&self, items: &mut Vec) -> bool { + pub(super) fn sort(&self, items: &mut Vec, sizes: &BTreeMap) -> bool { if items.is_empty() { return false; } @@ -45,7 +46,9 @@ impl FilesSorter { }), SortBy::Natural => self.sort_naturally(items), SortBy::Size => items.sort_unstable_by(|a, b| { - self.cmp(a.length().unwrap_or(0), b.length().unwrap_or(0), self.promote(a, b)) + let aa = if a.is_dir() { sizes.get(a.url()).copied() } else { None }; + let bb = if b.is_dir() { sizes.get(b.url()).copied() } else { None }; + self.cmp(aa.unwrap_or(a.length), bb.unwrap_or(b.length), self.promote(a, b)) }), } true @@ -73,7 +76,7 @@ impl FilesSorter { let dummy = File { url: Default::default(), meta: items[0].meta.clone(), - length: None, + length: 0, link_to: None, is_link: false, is_hidden: false, diff --git a/core/src/tasks/tasks.rs b/core/src/tasks/tasks.rs index 697c749e..ef204105 100644 --- a/core/src/tasks/tasks.rs +++ b/core/src/tasks/tasks.rs @@ -211,8 +211,11 @@ impl Tasks { return false; } - let targets: Vec<_> = - targets.iter().filter(|f| f.is_dir() && f.length().is_none()).map(|f| f.url()).collect(); + let targets: Vec<_> = targets + .iter() + .filter(|f| f.is_dir() && targets.size(f.url()).is_none()) + .map(|f| f.url()) + .collect(); if !targets.is_empty() { self.scheduler.precache_size(targets);