Cache icon results

This commit is contained in:
Javier Feliz 2025-09-06 16:41:47 -04:00
parent ae7d3f7123
commit 6fd3b4eba1
3 changed files with 85 additions and 67 deletions

View File

@ -2,11 +2,25 @@ pub mod errors;
use redb::{Database, ReadableDatabase, ReadableTable, TableDefinition}; use redb::{Database, ReadableDatabase, ReadableTable, TableDefinition};
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use std::path::Path; use std::path::Path;
use std::sync::OnceLock;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use crate::cache::errors::CacheError; use crate::cache::errors::CacheError;
const CACHE_TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("cache"); const CACHE_TABLE: TableDefinition<&str, &[u8]> = TableDefinition::new("cache");
static CACHE_SINGLETON: OnceLock<Cache> = OnceLock::new();
pub struct CacheTTL {}
impl CacheTTL {
pub fn hours(hours: u64) -> Option<Duration> {
return Some(Duration::from_secs(hours * 60 * 60));
}
pub fn minutes(minutes: u64) -> Option<Duration> {
return Some(Duration::from_secs(minutes * 60));
}
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
struct CacheEntry<T> { struct CacheEntry<T> {
@ -18,7 +32,13 @@ pub struct Cache {
db: Database, db: Database,
} }
pub fn new<P: AsRef<Path>>(db_path: P) -> Result<Cache, CacheError> { pub fn get() -> &'static Cache {
CACHE_SINGLETON.get_or_init(|| new("waycast_cache").expect("Failed to initialize cache :("))
}
// Get an existing cache at the given path or
// create it if it doesn't exist
fn new<P: AsRef<Path>>(db_path: P) -> Result<Cache, CacheError> {
let db = Database::create(db_path)?; let db = Database::create(db_path)?;
// Initialize the table if it doesn't exist // Initialize the table if it doesn't exist
@ -47,7 +67,6 @@ impl Cache {
// Check if entry has expired // Check if entry has expired
if let Some(expires_at) = entry.expires_at { if let Some(expires_at) = entry.expires_at {
if SystemTime::now() < expires_at { if SystemTime::now() < expires_at {
println!("Cache hit");
return Ok(entry.data); return Ok(entry.data);
} }
// Entry has expired, continue to recompute // Entry has expired, continue to recompute
@ -57,8 +76,6 @@ impl Cache {
} }
} }
println!("Cache miss");
// Not in cache or expired, compute the value // Not in cache or expired, compute the value
let data = compute(); let data = compute();
let expires_at = ttl.map(|duration| SystemTime::now() + duration); let expires_at = ttl.map(|duration| SystemTime::now() + duration);

View File

@ -1,70 +1,50 @@
use std::time::Duration; mod ui;
mod util;
use waycast_core::cache::Cache; use gtk::prelude::*;
use gtk::Application;
use ui::gtk::GtkLauncherUI;
use waycast_core::WaycastLauncher;
fn main() { fn main() {
let cache: Cache; let app = Application::builder()
if let Ok(db) = waycast_core::cache::new("waycast_cache") { .application_id("dev.thegrind.waycast")
cache = db; .build();
} else {
panic!("Failed to open database"); app.connect_activate(|app| {
let mut file_search_plugin = waycast_plugins::file_search::new();
if let Err(e) = file_search_plugin.add_search_path("/home/javi/working-files/DJ Music/") {
eprintln!("{}", e)
} }
let result = cache.remember_with_ttl("test_key", Some(Duration::from_secs(10)), || { let mut project_plugin = waycast_plugins::projects::new();
String::from("my cool string value") if let Err(e) = project_plugin.add_search_path("/home/javi/projects") {
eprintln!("{}", e)
}
// Create the core launcher
let launcher = WaycastLauncher::new()
.add_plugin(Box::new(waycast_plugins::drun::new()))
.add_plugin(Box::new(file_search_plugin))
.add_plugin(Box::new(project_plugin))
.init();
// Create and show the GTK UI
let ui = GtkLauncherUI::new(app, launcher);
// Apply built-in default styles
if let Err(e) = ui.apply_default_css() {
eprintln!("Warning: Could not apply default styles: {}", e);
}
// Optionally apply user CSS overrides
// if let Err(_) = ui.apply_css("waycast.css") {
// // Silently ignore if user hasn't provided custom CSS
// }
ui.show();
}); });
if let Ok(val) = result { app.run();
println!("{}", val);
} }
}
// mod ui;
// mod util;
// use gtk::prelude::*;
// use gtk::Application;
// use ui::gtk::GtkLauncherUI;
// use waycast_core::WaycastLauncher;
// fn main() {
// let app = Application::builder()
// .application_id("dev.thegrind.waycast")
// .build();
// app.connect_activate(|app| {
// let mut file_search_plugin = waycast_plugins::file_search::new();
// if let Err(e) = file_search_plugin.add_search_path("/home/javi/working-files/DJ Music/") {
// eprintln!("{}", e)
// }
// let mut project_plugin = waycast_plugins::projects::new();
// if let Err(e) = project_plugin.add_search_path("/home/javi/projects") {
// eprintln!("{}", e)
// }
// // Create the core launcher
// let launcher = WaycastLauncher::new()
// .add_plugin(Box::new(waycast_plugins::drun::new()))
// .add_plugin(Box::new(file_search_plugin))
// .add_plugin(Box::new(project_plugin))
// .init();
// // Create and show the GTK UI
// let ui = GtkLauncherUI::new(app, launcher);
// // Apply built-in default styles
// if let Err(e) = ui.apply_default_css() {
// eprintln!("Warning: Could not apply default styles: {}", e);
// }
// // Optionally apply user CSS overrides
// // if let Err(_) = ui.apply_css("waycast.css") {
// // // Silently ignore if user hasn't provided custom CSS
// // }
// ui.show();
// });
// app.run();
// }

View File

@ -13,6 +13,7 @@ use layerShell::LayerShell;
use std::cell::RefCell; use std::cell::RefCell;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::rc::Rc; use std::rc::Rc;
use waycast_core::cache::CacheTTL;
use waycast_core::WaycastLauncher; use waycast_core::WaycastLauncher;
// GObject wrapper to store LauncherListItem in GTK's model system // GObject wrapper to store LauncherListItem in GTK's model system
@ -402,6 +403,25 @@ fn find_icon_file(
icon_name: &str, icon_name: &str,
size: &str, size: &str,
icon_theme: &IconTheme, icon_theme: &IconTheme,
) -> Option<std::path::PathBuf> {
let cache_key = format!("icon:{}:{}", icon_name, size);
let cache = waycast_core::cache::get();
let result = cache.remember_with_ttl(&cache_key, CacheTTL::hours(24), || {
search_for_icon(icon_name, size, icon_theme)
});
if let Ok(opt_path) = result {
return opt_path;
}
search_for_icon(icon_name, size, icon_theme)
}
fn search_for_icon(
icon_name: &str,
size: &str,
icon_theme: &IconTheme,
) -> Option<std::path::PathBuf> { ) -> Option<std::path::PathBuf> {
let pixmap_paths: Vec<PathBuf> = icon_theme let pixmap_paths: Vec<PathBuf> = icon_theme
.search_path() .search_path()
@ -439,6 +459,7 @@ fn find_icon_file(
} }
} }
} }
for base in &search_paths { for base in &search_paths {
for size in sizes { for size in sizes {
for cat in &categories { for cat in &categories {