From 9f9d186742c1267e459b239017ab5212cc70775f Mon Sep 17 00:00:00 2001 From: unsecretised Date: Thu, 26 Mar 2026 00:26:12 +0800 Subject: [PATCH] add persistent search ranking --- src/app.rs | 2 ++ src/app/tile.rs | 29 ++++++++++++++++++++++++++--- src/app/tile/elm.rs | 11 +++++++++++ src/app/tile/update.rs | 22 +++++++++++++++++++++- 4 files changed, 60 insertions(+), 4 deletions(-) diff --git a/src/app.rs b/src/app.rs index aad3b86..aa792b8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -80,6 +80,8 @@ pub enum Editable { #[derive(Debug, Clone)] pub enum Message { WriteConfig(bool), + SaveRanking, + LoadRanking, UpdateAvailable, ResizeWindow(Id, f32), OpenWindow, diff --git a/src/app/tile.rs b/src/app/tile.rs index 9ccba3a..e9d67e2 100644 --- a/src/app/tile.rs +++ b/src/app/tile.rs @@ -71,6 +71,25 @@ impl AppIndex { app.ranking += 1; } + fn set_ranking(&mut self, name: &str, rank: i32) { + let app = match self.by_name.get_mut(name) { + Some(a) => a, + None => return, + }; + + app.ranking = rank; + } + + fn get_rankings(&self) -> HashMap { + HashMap::from_iter(self.by_name.iter().filter_map(|(name, app)| { + if app.ranking > 0 { + Some((name.to_owned(), app.ranking.to_owned())) + } else { + None + } + })) + } + fn empty() -> AppIndex { AppIndex { by_name: HashMap::new(), @@ -115,6 +134,7 @@ pub struct Tile { pub query: String, pub current_mode: String, pub update_available: bool, + pub ranking: HashMap, query_lc: String, results: Vec, options: AppIndex, @@ -180,7 +200,7 @@ impl Tile { Subscription::run(handle_hot_reloading), keyboard, Subscription::run(handle_recipient), - Subscription::run(check_version), + Subscription::run(handle_version_and_rankings), Subscription::run(handle_clipboard_history), Subscription::run(handle_file_search), window::close_events().map(Message::HideWindow), @@ -533,7 +553,7 @@ fn handle_recipient() -> impl futures::Stream { }) } -fn check_version() -> impl futures::Stream { +fn handle_version_and_rankings() -> impl futures::Stream { stream::channel(100, async |mut output| { let current_version = format!("\"{}\"", option_env!("APP_VERSION").unwrap_or("")); @@ -576,7 +596,10 @@ fn check_version() -> impl futures::Stream { } else { warn!("Error getting resp"); } - tokio::time::sleep(Duration::from_secs(60)).await; + tokio::time::sleep(Duration::from_secs(30)).await; + output.send(Message::SaveRanking).await.ok(); + info!("Sent save ranking"); + tokio::time::sleep(Duration::from_secs(30)).await; } }) } diff --git a/src/app/tile/elm.rs b/src/app/tile/elm.rs index 54132a0..7d6d5f6 100644 --- a/src/app/tile/elm.rs +++ b/src/app/tile/elm.rs @@ -1,6 +1,9 @@ //! This module handles the logic for the new and view functions according to the elm //! architecture. If the subscription function becomes too large, it should be moved to this file +use std::collections::HashMap; +use std::fs; + use global_hotkey::hotkey::HotKey; use iced::border::Radius; use iced::widget::scrollable::{Anchor, Direction, Scrollbar}; @@ -65,6 +68,13 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task) { .unwrap_or("SUPER+SHIFT+C".parse().unwrap()), }; + let home = std::env::var("HOME").unwrap_or("/".to_string()); + + let ranking = toml::from_str( + &fs::read_to_string(home + "/.config/rustcast/ranking.toml").unwrap_or("".to_string()), + ) + .unwrap_or(HashMap::new()); + ( Tile { update_available: false, @@ -80,6 +90,7 @@ pub fn new(hotkey: HotKey, config: &Config) -> (Tile, Task) { frontmost: None, focused: false, config: config.clone(), + ranking, theme: config.theme.to_owned().clone().into(), clipboard_content: vec![], tray_icon: None, diff --git a/src/app/tile/update.rs b/src/app/tile/update.rs index 8f1933f..aabaa49 100644 --- a/src/app/tile/update.rs +++ b/src/app/tile/update.rs @@ -221,6 +221,23 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { ) } + Message::LoadRanking => { + for (name, rank) in &tile.ranking { + tile.options.set_ranking(name, rank.to_owned()); + } + + Task::none() + } + + Message::SaveRanking => { + tile.ranking = tile.options.get_rankings(); + let string_rep = toml::to_string(&tile.ranking).unwrap_or("".to_string()); + let ranking_file_path = + std::env::var("HOME").unwrap_or("/".to_string()) + "/.config/rustcast/ranking.toml"; + fs::write(ranking_file_path, string_rep).ok(); + Task::none() + } + Message::OpenFocused => { info!("Open Focussed called"); let results = if tile.page == Page::ClipboardHistory { @@ -238,7 +255,10 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { .. }) => { info!("Updating ranking for: {name}"); + let current_ranking = tile.ranking.get(name).map(|x| x.to_owned()).unwrap_or(0); + tile.ranking.insert(name.to_owned(), current_ranking); tile.options.update_ranking(name); + Task::done(Message::RunFunction(func.to_owned())) } Some(App { @@ -290,7 +310,7 @@ pub fn handle_update(tile: &mut Tile, message: Message) -> Task { tile.theme = new_config.theme.to_owned().into(); tile.config = new_config; - Task::none() + Task::done(Message::LoadRanking) } Message::KeyPressed(hk_id) => {