Directories sizes in details view (#656)
* translations * folder size in details view * dir size subscription * waldir instead of recursion * opitonal size with calculating label waiting for subscription * removed not necessary code * Bug fixes --------- Co-authored-by: Jeremy Soller <jackpot51@gmail.com>
This commit is contained in:
parent
b76484457f
commit
5f944a3059
4 changed files with 109 additions and 14 deletions
|
|
@ -201,6 +201,13 @@ default-app = {$name} (default)
|
|||
|
||||
## Show details
|
||||
show-details = Show details
|
||||
type = Type: {$mime}
|
||||
items = Items: {$items}
|
||||
item-size = Size: {$size}
|
||||
item-created = Created: {$created}
|
||||
item-modified = Modified: {$modified}
|
||||
item-accessed = Accessed: {$accessed}
|
||||
calculating = Calculating...
|
||||
|
||||
## Settings
|
||||
settings = Settings
|
||||
|
|
|
|||
|
|
@ -189,6 +189,14 @@ default-app = {$name} (default)
|
|||
|
||||
## Show details
|
||||
show-details = Mostra dettagli
|
||||
type = Tipo: {$mime}
|
||||
items = Elementi: {$items}
|
||||
item-size = Dimensione: {$size}
|
||||
item-created = Creato: {$created}
|
||||
item-modified = Modificato: {$modified}
|
||||
item-accessed = Ultimo accesso: {$accessed}
|
||||
calculating = Calcolando...
|
||||
|
||||
|
||||
## Settings
|
||||
settings = Impostazioni
|
||||
|
|
|
|||
|
|
@ -135,6 +135,7 @@ fn network_scan(uri: &str, sizes: IconSizes) -> Result<Vec<tab::Item>, String> {
|
|||
selected: false,
|
||||
highlighted: false,
|
||||
overlaps_drag_rect: false,
|
||||
size: None,
|
||||
});
|
||||
}
|
||||
Ok(items)
|
||||
|
|
|
|||
107
src/tab.rs
107
src/tab.rs
|
|
@ -55,6 +55,7 @@ use std::{
|
|||
time::{Duration, Instant, SystemTime},
|
||||
};
|
||||
use tokio::sync::mpsc;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
use crate::{
|
||||
app::{self, Action, PreviewItem, PreviewKind},
|
||||
|
|
@ -302,6 +303,7 @@ fn format_permissions_owner(metadata: &Metadata, owner: PermissionOwner) -> Stri
|
|||
PermissionOwner::Other => String::from(""),
|
||||
};
|
||||
}
|
||||
|
||||
fn format_permissions(metadata: &Metadata, owner: PermissionOwner) -> String {
|
||||
let mut perms: Vec<String> = Vec::new();
|
||||
if match owner {
|
||||
|
|
@ -489,6 +491,7 @@ pub fn item_from_entry(
|
|||
selected: false,
|
||||
highlighted: false,
|
||||
overlaps_drag_rect: false,
|
||||
size: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -718,6 +721,7 @@ pub fn scan_trash(sizes: IconSizes) -> Vec<Item> {
|
|||
selected: false,
|
||||
highlighted: false,
|
||||
overlaps_drag_rect: false,
|
||||
size: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -901,6 +905,7 @@ pub fn scan_desktop(
|
|||
selected: false,
|
||||
highlighted: false,
|
||||
overlaps_drag_rect: false,
|
||||
size: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -1074,6 +1079,7 @@ pub enum Message {
|
|||
ZoomOut,
|
||||
HighlightDeactivate(usize),
|
||||
HighlightActivate(usize),
|
||||
DirectorySize(PathBuf, u64),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
|
|
@ -1303,6 +1309,7 @@ pub struct Item {
|
|||
pub selected: bool,
|
||||
pub highlighted: bool,
|
||||
pub overlaps_drag_rect: bool,
|
||||
pub size: Option<u64>,
|
||||
}
|
||||
|
||||
impl Item {
|
||||
|
|
@ -1396,33 +1403,43 @@ impl Item {
|
|||
|
||||
let mut details = widget::column().spacing(space_xxxs);
|
||||
details = details.push(widget::text::heading(self.name.clone()));
|
||||
details = details.push(widget::text(format!("Type: {}", self.mime)));
|
||||
details = details.push(widget::text(fl!("type", mime = self.mime.to_string())));
|
||||
let mut settings = Vec::new();
|
||||
//TODO: translate!
|
||||
//TODO: correct display of folder size?
|
||||
match &self.metadata {
|
||||
ItemMetadata::Path { metadata, children } => {
|
||||
if metadata.is_dir() {
|
||||
details = details.push(widget::text(format!("Items: {}", children)));
|
||||
details = details.push(widget::text(fl!("items", items = children)));
|
||||
let size = match self.size {
|
||||
Some(size) => format_size(size),
|
||||
None => fl!("calculating"),
|
||||
};
|
||||
details = details.push(widget::text(fl!("item-size", size = size)));
|
||||
} else {
|
||||
details = details.push(widget::text(format!(
|
||||
"Size: {}",
|
||||
format_size(metadata.len())
|
||||
details = details.push(widget::text(fl!(
|
||||
"item-size",
|
||||
size = format_size(metadata.len())
|
||||
)));
|
||||
}
|
||||
|
||||
if let Ok(time) = metadata.created() {
|
||||
details = details.push(widget::text(format!("Created: {}", format_time(time))));
|
||||
details = details.push(widget::text(fl!(
|
||||
"item-created",
|
||||
created = format_time(time).to_string()
|
||||
)));
|
||||
}
|
||||
|
||||
if let Ok(time) = metadata.modified() {
|
||||
details =
|
||||
details.push(widget::text(format!("Modified: {}", format_time(time))));
|
||||
details = details.push(widget::text(fl!(
|
||||
"item-modified",
|
||||
modified = format_time(time).to_string()
|
||||
)));
|
||||
}
|
||||
|
||||
if let Ok(time) = metadata.accessed() {
|
||||
details =
|
||||
details.push(widget::text(format!("Accessed: {}", format_time(time))));
|
||||
details = details.push(widget::text(fl!(
|
||||
"item-accessed",
|
||||
accessed = format_time(time).to_string()
|
||||
)));
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
|
|
@ -1636,6 +1653,16 @@ pub struct Tab {
|
|||
search_context: Option<SearchContext>,
|
||||
}
|
||||
|
||||
fn calculate_dir_size(path: &Path) -> u64 {
|
||||
WalkDir::new(path)
|
||||
.into_iter()
|
||||
.filter_map(|entry| entry.ok())
|
||||
.filter_map(|entry| fs::metadata(entry.path()).ok())
|
||||
.filter(|metadata| metadata.is_file())
|
||||
.map(|metadata| metadata.len())
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn folder_name<P: AsRef<Path>>(path: P) -> (String, bool) {
|
||||
let path = path.as_ref();
|
||||
let mut found_home = false;
|
||||
|
|
@ -2886,6 +2913,22 @@ impl Tab {
|
|||
Message::ZoomOut => {
|
||||
commands.push(Command::Action(Action::ZoomOut));
|
||||
}
|
||||
Message::DirectorySize(path, dir_size) => {
|
||||
let location = Location::Path(path);
|
||||
if let Some(ref mut item) = self.parent_item_opt {
|
||||
if item.location_opt.as_ref() == Some(&location) {
|
||||
item.size = Some(dir_size);
|
||||
}
|
||||
}
|
||||
if let Some(ref mut items) = self.items_opt {
|
||||
for item in items.iter_mut() {
|
||||
if item.location_opt.as_ref() == Some(&location) {
|
||||
item.size = Some(dir_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll to top if needed
|
||||
|
|
@ -4394,8 +4437,9 @@ impl Tab {
|
|||
continue;
|
||||
};
|
||||
let mime = item.mime.clone();
|
||||
|
||||
subscriptions.push(Subscription::run_with_id(
|
||||
path.clone(),
|
||||
("thumbnail", path.clone()),
|
||||
stream::channel(1, |mut output| async move {
|
||||
let message = {
|
||||
let path = path.clone();
|
||||
|
|
@ -4413,7 +4457,7 @@ impl Tab {
|
|||
match output.send(message).await {
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
log::warn!("failed to send thumbnail for {:?}: {}", path, err);
|
||||
log::warn!("failed to send thumbnail for {:?}: {}", &path, err);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4426,6 +4470,41 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
// Load directory size for selected items
|
||||
for item in items
|
||||
.iter()
|
||||
.filter(|item| {
|
||||
// Item must be a selected directory
|
||||
item.selected && item.metadata.is_dir()
|
||||
})
|
||||
.chain(&self.parent_item_opt)
|
||||
{
|
||||
// Item must have a path
|
||||
let Some(path) = item.path_opt().map(|path| path.to_path_buf()) else {
|
||||
continue;
|
||||
};
|
||||
subscriptions.push(Subscription::run_with_id(
|
||||
("dir_size", path.clone()),
|
||||
stream::channel(1, |mut output| async move {
|
||||
let total_size = calculate_dir_size(&path);
|
||||
|
||||
match output
|
||||
.send(Message::DirectorySize(path.clone(), total_size))
|
||||
.await
|
||||
{
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
log::warn!("failed to send dirsize for {:?}: {}", &path, err);
|
||||
}
|
||||
}
|
||||
|
||||
std::future::pending().await
|
||||
}),
|
||||
));
|
||||
// Only calculate size for one directory
|
||||
break;
|
||||
}
|
||||
|
||||
// Load search items incrementally
|
||||
if let Location::Search(path, term, show_hidden, start) = &self.location {
|
||||
let location = self.location.clone();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue