From 8b2578783a4fec8197342164b5cf84216ac22023 Mon Sep 17 00:00:00 2001 From: Luna Date: Mon, 15 Jun 2026 20:15:27 -0700 Subject: [PATCH] Library sorting: download-date sort + grouped sort options (both UIs) Add "download date" sorting (file mtime, distinct from upload date) plus a broader set of options. Web select is now grouped via ; desktop gains SortMode::DownloadDesc/DownloadAsc/ChannelAsc with matching arms and toolbar entries. Co-Authored-By: Claude Opus 4.8 --- src/app.rs | 23 +++++++++++++++++++++-- src/web_ui/index.html | 34 +++++++++++++++++++++++++++------- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/app.rs b/src/app.rs index cc5e1b3..9318b10 100644 --- a/src/app.rs +++ b/src/app.rs @@ -71,6 +71,9 @@ enum SortMode { SizeDesc, DateDesc, DateAsc, + DownloadDesc, + DownloadAsc, + ChannelAsc, } #[derive(Clone, PartialEq)] @@ -883,6 +886,19 @@ impl App { } }); } + SortMode::DownloadDesc => { + // Most-recently-downloaded first (file mtime); missing → end. + cards.sort_by(|a, b| b.mtime_unix.unwrap_or(0).cmp(&a.mtime_unix.unwrap_or(0))); + } + SortMode::DownloadAsc => { + cards.sort_by(|a, b| a.mtime_unix.unwrap_or(u64::MAX).cmp(&b.mtime_unix.unwrap_or(u64::MAX))); + } + SortMode::ChannelAsc => { + cards.sort_by(|a, b| { + a.channel_name.to_lowercase().cmp(&b.channel_name.to_lowercase()) + .then_with(|| a.title.to_lowercase().cmp(&b.title.to_lowercase())) + }); + } } cards @@ -4131,13 +4147,16 @@ impl App { } ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { - ui.selectable_value(&mut self.sort_mode, SortMode::DateDesc, "Newest"); - ui.selectable_value(&mut self.sort_mode, SortMode::DateAsc, "Oldest"); ui.selectable_value(&mut self.sort_mode, SortMode::SizeDesc, "Largest"); ui.selectable_value(&mut self.sort_mode, SortMode::SizeAsc, "Smallest"); ui.selectable_value(&mut self.sort_mode, SortMode::DurationDesc, "Longest"); ui.selectable_value(&mut self.sort_mode, SortMode::DurationAsc, "Shortest"); + ui.selectable_value(&mut self.sort_mode, SortMode::ChannelAsc, "Channel"); ui.selectable_value(&mut self.sort_mode, SortMode::Title, "Title"); + ui.selectable_value(&mut self.sort_mode, SortMode::DateAsc, "Oldest"); + ui.selectable_value(&mut self.sort_mode, SortMode::DateDesc, "Newest"); + ui.selectable_value(&mut self.sort_mode, SortMode::DownloadAsc, "Oldest DL"); + ui.selectable_value(&mut self.sort_mode, SortMode::DownloadDesc, "Recent DL"); ui.label(egui::RichText::new("Sort:").weak()); }); }); diff --git a/src/web_ui/index.html b/src/web_ui/index.html index ecb5fe7..1dc6a59 100644 --- a/src/web_ui/index.html +++ b/src/web_ui/index.html @@ -216,13 +216,29 @@

yt-offline

@@ -617,6 +633,8 @@ function currentVideos(){ for(const v of pool) if((!q||matchesSearch(v,ch?.name||v.channel,q))&&passesFilter(v))vids.push({...v,channel:ch.name}); } + if(sort==='dl-desc')vids.sort((a,b)=>(b.mtime_unix||0)-(a.mtime_unix||0)); + if(sort==='dl-asc')vids.sort((a,b)=>(a.mtime_unix||0)-(b.mtime_unix||0)); if(sort==='date-desc')vids.sort((a,b)=>(b.upload_date||'').localeCompare(a.upload_date||'')); if(sort==='date-asc')vids.sort((a,b)=>{const ax=a.upload_date||'￿',bx=b.upload_date||'￿';return ax.localeCompare(bx)}); if(sort==='dur-asc')vids.sort((a,b)=>(a.duration_secs??0)-(b.duration_secs??0)); @@ -624,6 +642,8 @@ function currentVideos(){ if(sort==='size-asc')vids.sort((a,b)=>(a.file_size??0)-(b.file_size??0)); if(sort==='size-desc')vids.sort((a,b)=>(b.file_size??0)-(a.file_size??0)); if(sort==='title')vids.sort((a,b)=>a.title.localeCompare(b.title)); + if(sort==='title-desc')vids.sort((a,b)=>b.title.localeCompare(a.title)); + if(sort==='channel')vids.sort((a,b)=>(a.channel||'').localeCompare(b.channel||'')||a.title.localeCompare(b.title)); return vids; }