From 8934e66f6d803e6dfa721f7621d162f09221c551 Mon Sep 17 00:00:00 2001 From: lashman Date: Fri, 27 Feb 2026 23:41:22 +0200 Subject: [PATCH] Add launch statistics to dashboard --- src/core/database.rs | 47 ++++++++++++++++++++++++++++++++++++++++++++ src/ui/dashboard.rs | 39 +++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/core/database.rs b/src/core/database.rs index 173d440..8083f0e 100644 --- a/src/core/database.rs +++ b/src/core/database.rs @@ -1744,6 +1744,53 @@ impl Database { Ok(self.conn.last_insert_rowid()) } + // --- Launch statistics --- + + pub fn get_top_launched(&self, limit: i32) -> SqlResult> { + let mut stmt = self.conn.prepare( + "SELECT a.app_name, COUNT(l.id) as cnt + FROM launch_events l + JOIN appimages a ON a.id = l.appimage_id + GROUP BY l.appimage_id + ORDER BY cnt DESC + LIMIT ?1" + )?; + let rows = stmt.query_map(params![limit], |row| { + Ok(( + row.get::<_, Option>(0)?.unwrap_or_else(|| "Unknown".to_string()), + row.get::<_, u64>(1)?, + )) + })?; + rows.collect() + } + + pub fn get_total_launch_count(&self) -> SqlResult { + self.conn.query_row( + "SELECT COUNT(*) FROM launch_events", + [], + |row| row.get(0), + ) + } + + pub fn get_last_launch(&self) -> SqlResult> { + match self.conn.query_row( + "SELECT a.app_name, l.launched_at + FROM launch_events l + JOIN appimages a ON a.id = l.appimage_id + ORDER BY l.launched_at DESC + LIMIT 1", + [], + |row| Ok(( + row.get::<_, Option>(0)?.unwrap_or_else(|| "Unknown".to_string()), + row.get::<_, String>(1)?, + )), + ) { + Ok(pair) => Ok(Some(pair)), + Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None), + Err(e) => Err(e), + } + } + // --- Source URL --- pub fn set_source_url(&self, id: i64, url: Option<&str>) -> SqlResult<()> { diff --git a/src/ui/dashboard.rs b/src/ui/dashboard.rs index fd26de8..4fd0fbc 100644 --- a/src/ui/dashboard.rs +++ b/src/ui/dashboard.rs @@ -39,7 +39,10 @@ pub fn build_dashboard_page(db: &Rc) -> adw::NavigationPage { // Section 5: Disk Usage (actionable) content.append(&build_disk_usage_group(db)); - // Section 6: Quick Actions + // Section 6: Activity + content.append(&build_activity_group(db)); + + // Section 7: Quick Actions content.append(&build_quick_actions_group()); clamp.set_child(Some(&content)); @@ -350,6 +353,40 @@ fn build_disk_usage_group(db: &Rc) -> adw::PreferencesGroup { group } +fn build_activity_group(db: &Rc) -> adw::PreferencesGroup { + let group = adw::PreferencesGroup::builder() + .title("Activity") + .description("Launch history and usage statistics") + .build(); + + let total_launches = db.get_total_launch_count().unwrap_or(0); + let total_row = adw::ActionRow::builder() + .title("Total launches") + .subtitle(&total_launches.to_string()) + .build(); + group.add(&total_row); + + if let Ok(Some((name, time))) = db.get_last_launch() { + let last_row = adw::ActionRow::builder() + .title("Last launched") + .subtitle(&format!("{} - {}", name, time)) + .build(); + group.add(&last_row); + } + + if let Ok(top) = db.get_top_launched(5) { + for (name, count) in &top { + let row = adw::ActionRow::builder() + .title(name) + .subtitle(&format!("{} launches", count)) + .build(); + group.add(&row); + } + } + + group +} + fn build_quick_actions_group() -> adw::PreferencesGroup { let group = adw::PreferencesGroup::builder() .title("Quick Actions")