Merge pull request #478 from joshuamegnauth54/issue-458-show-trashed-on-time

Show file deletion date in Trash
This commit is contained in:
Jeremy Soller 2024-09-25 08:42:00 -06:00 committed by GitHub
commit 181bed29a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 80 additions and 12 deletions

View file

@ -14,6 +14,7 @@ today = Today
# List view
name = Name
modified = Modified
trashed-on = Trashed
size = Size
# Dialogs
@ -198,6 +199,7 @@ remove-from-sidebar = Remove from sidebar
sort-by-name = Sort by name
sort-by-modified = Sort by modified
sort-by-size = Sort by size
sort-by-trashed = Sort by delete time
# Menu

View file

@ -238,7 +238,7 @@ pub fn context_menu<'a>(
} else {
// TODO: Nested menu
children.push(sort_item(fl!("sort-by-name"), HeadingOptions::Name));
children.push(sort_item(fl!("sort-by-modified"), HeadingOptions::Modified));
children.push(sort_item(fl!("sort-by-trashed"), HeadingOptions::TrashedOn));
children.push(sort_item(fl!("sort-by-size"), HeadingOptions::Size));
}
}
@ -277,6 +277,7 @@ pub fn dialog_menu<'a>(
Action::SetSort(sort, dir),
)
};
let in_trash = tab.location == Location::Trash;
MenuBar::new(vec![
menu::Tree::with_children(
@ -315,12 +316,20 @@ pub fn dialog_menu<'a>(
sort_item(fl!("sort-z-a"), tab::HeadingOptions::Name, false),
sort_item(
fl!("sort-newest-first"),
tab::HeadingOptions::Modified,
if in_trash {
tab::HeadingOptions::TrashedOn
} else {
tab::HeadingOptions::Modified
},
false,
),
sort_item(
fl!("sort-oldest-first"),
tab::HeadingOptions::Modified,
if in_trash {
tab::HeadingOptions::TrashedOn
} else {
tab::HeadingOptions::Modified
},
true,
),
sort_item(
@ -357,6 +366,7 @@ pub fn menu_bar<'a>(
Action::SetSort(sort, dir),
)
};
let in_trash = tab_opt.map_or(false, |tab| tab.location == Location::Trash);
MenuBar::new(vec![
menu::Tree::with_children(
@ -444,12 +454,20 @@ pub fn menu_bar<'a>(
sort_item(fl!("sort-z-a"), tab::HeadingOptions::Name, false),
sort_item(
fl!("sort-newest-first"),
tab::HeadingOptions::Modified,
if in_trash {
tab::HeadingOptions::TrashedOn
} else {
tab::HeadingOptions::Modified
},
false,
),
sort_item(
fl!("sort-oldest-first"),
tab::HeadingOptions::Modified,
if in_trash {
tab::HeadingOptions::TrashedOn
} else {
tab::HeadingOptions::Modified
},
true,
),
sort_item(

View file

@ -51,7 +51,7 @@ use std::{
os::unix::fs::MetadataExt,
path::{Path, PathBuf},
sync::{Arc, Mutex},
time::{Duration, Instant},
time::{Duration, Instant, SystemTime},
};
use crate::{
@ -265,6 +265,21 @@ fn format_permissions(metadata: &Metadata, owner: PermissionOwner) -> String {
struct FormatTime(std::time::SystemTime);
impl FormatTime {
fn from_secs(secs: i64) -> Option<Self> {
// This looks convoluted because we need to ensure the units match up
let secs: u64 = secs.try_into().ok()?;
let now = SystemTime::now();
let filetime_diff = now
.duration_since(SystemTime::UNIX_EPOCH)
.map(|from_epoch| from_epoch.as_secs())
.ok()
.and_then(|now_secs| now_secs.checked_sub(secs))
.map(Duration::from_secs)?;
now.checked_add(filetime_diff).map(FormatTime)
}
}
impl Display for FormatTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let date_time = chrono::DateTime::<chrono::Local>::from(self.0);
@ -1219,6 +1234,7 @@ pub enum HeadingOptions {
Name = 0,
Modified,
Size,
TrashedOn,
}
impl fmt::Display for HeadingOptions {
@ -1227,6 +1243,7 @@ impl fmt::Display for HeadingOptions {
HeadingOptions::Name => write!(f, "{}", fl!("name")),
HeadingOptions::Modified => write!(f, "{}", fl!("modified")),
HeadingOptions::Size => write!(f, "{}", fl!("size")),
HeadingOptions::TrashedOn => write!(f, "{}", fl!("trashed-on")),
}
}
}
@ -1237,6 +1254,7 @@ impl HeadingOptions {
HeadingOptions::Name.to_string(),
HeadingOptions::Modified.to_string(),
HeadingOptions::Size.to_string(),
HeadingOptions::TrashedOn.to_string(),
]
}
}
@ -2495,6 +2513,26 @@ impl Tab {
}
});
}
HeadingOptions::TrashedOn => {
let time_deleted = |x: &Item| match &x.metadata {
ItemMetadata::Trash { entry, .. } => Some(entry.time_deleted),
_ => None,
};
items.sort_by(|a, b| {
let a_time_deleted = time_deleted(a.1);
let b_time_deleted = time_deleted(b.1);
if self.config.folders_first {
match (a.1.metadata.is_dir(), b.1.metadata.is_dir()) {
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
_ => check_reverse(a_time_deleted.cmp(&b_time_deleted), heading_sort),
}
} else {
check_reverse(b_time_deleted.cmp(&a_time_deleted), heading_sort)
}
});
}
}
Some(items)
}
@ -2765,12 +2803,19 @@ impl Tab {
let heading_row = widget::row::with_children(vec![
heading_item(fl!("name"), Length::Fill, HeadingOptions::Name),
//TODO: do not show modified column when in the trash
heading_item(
fl!("modified"),
Length::Fixed(modified_width),
HeadingOptions::Modified,
),
if self.location == Location::Trash {
heading_item(
fl!("trashed-on"),
Length::Fixed(modified_width),
HeadingOptions::TrashedOn,
)
} else {
heading_item(
fl!("modified"),
Length::Fixed(modified_width),
HeadingOptions::Modified,
)
},
heading_item(fl!("size"), Length::Fixed(size_width), HeadingOptions::Size),
])
.align_items(Alignment::Center)
@ -3384,6 +3429,9 @@ impl Tab {
Ok(time) => format_time(time).to_string(),
Err(_) => String::new(),
},
ItemMetadata::Trash { entry, .. } => FormatTime::from_secs(entry.time_deleted)
.map(|t| t.to_string())
.unwrap_or_default(),
_ => String::new(),
};