From ad2c6dc56e4c1286bbf5f73cea5dfa1c8c844b5a Mon Sep 17 00:00:00 2001 From: spinline Date: Sun, 8 Feb 2026 04:10:02 +0300 Subject: [PATCH] feat(torrent): add date sorting and display - Sort torrents by added date (newest first) by default - Add Date column to desktop table (after ETA) - Add Date to mobile card view (grid-cols-3 -> grid-cols-4) - Add Date option to mobile sort dropdown - Display dates in DD/MM/YYYY HH:mm format - Add chrono wasm-bindgen feature --- frontend/Cargo.toml | 2 +- frontend/src/components/torrent/table.rs | 45 +++++++++++++++++------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index c190a12..96c2a1b 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -21,7 +21,7 @@ wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" uuid = { version = "1", features = ["v4", "js"] } futures = "0.3" -chrono = { version = "0.4", features = ["serde"] } +chrono = { version = "0.4", features = ["serde", "wasm-bindgen"] } web-sys = { version = "0.3", features = [ "HtmlDivElement", "HtmlUListElement", diff --git a/frontend/src/components/torrent/table.rs b/frontend/src/components/torrent/table.rs index 302cb64..1f031aa 100644 --- a/frontend/src/components/torrent/table.rs +++ b/frontend/src/components/torrent/table.rs @@ -45,6 +45,14 @@ fn format_duration(seconds: i64) -> String { } } +fn format_date(timestamp: i64) -> String { + let dt = chrono::DateTime::from_timestamp(timestamp, 0); + match dt { + Some(dt) => dt.format("%d/%m/%Y %H:%M").to_string(), + None => "N/A".to_string(), + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum SortColumn { Name, @@ -54,6 +62,7 @@ enum SortColumn { DownSpeed, UpSpeed, ETA, + AddedDate, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -66,8 +75,8 @@ enum SortDirection { pub fn TorrentTable() -> impl IntoView { let store = use_context::().expect("store not provided"); - let sort_col = create_rw_signal(SortColumn::Name); - let sort_dir = create_rw_signal(SortDirection::Ascending); + let sort_col = create_rw_signal(SortColumn::AddedDate); + let sort_dir = create_rw_signal(SortDirection::Descending); let filtered_torrents = move || { let mut torrents = store @@ -127,6 +136,7 @@ pub fn TorrentTable() -> impl IntoView { let b_eta = if b.eta <= 0 { i64::MAX } else { b.eta }; a_eta.cmp(&b_eta) } + SortColumn::AddedDate => a.added_date.cmp(&b.added_date), }; if dir == SortDirection::Descending { cmp.reverse() @@ -264,6 +274,9 @@ pub fn TorrentTable() -> impl IntoView {
"ETA" {move || sort_arrow(SortColumn::ETA)}
+ +
"Date" {move || sort_arrow(SortColumn::AddedDate)}
+ @@ -317,6 +330,7 @@ pub fn TorrentTable() -> impl IntoView { {format_speed(t.down_rate)} {format_speed(t.up_rate)} {format_duration(t.eta)} + {format_date(t.added_date)} } }).collect::>()} @@ -358,15 +372,16 @@ pub fn TorrentTable() -> impl IntoView { > { - let columns = vec![ - (SortColumn::Name, "Name"), - (SortColumn::Size, "Size"), - (SortColumn::Progress, "Progress"), - (SortColumn::Status, "Status"), - (SortColumn::DownSpeed, "Down Speed"), - (SortColumn::UpSpeed, "Up Speed"), - (SortColumn::ETA, "ETA"), - ]; + let columns = vec![ + (SortColumn::Name, "Name"), + (SortColumn::Size, "Size"), + (SortColumn::Progress, "Progress"), + (SortColumn::Status, "Status"), + (SortColumn::DownSpeed, "Down Speed"), + (SortColumn::UpSpeed, "Up Speed"), + (SortColumn::ETA, "ETA"), + (SortColumn::AddedDate, "Date"), + ]; columns.into_iter().map(|(col, label)| { let is_active = move || sort_col.get() == col; @@ -500,7 +515,7 @@ pub fn TorrentTable() -> impl IntoView { -
+
"Down" {format_speed(t.down_rate)} @@ -509,10 +524,14 @@ pub fn TorrentTable() -> impl IntoView { "Up" {format_speed(t.up_rate)}
-
+
"ETA" {format_duration(t.eta)}
+
+ "Date" + {format_date(t.added_date)} +