//! App state: the open [`Catalog`] and fuzzy [`NameIndex`], plus the db paths. use std::path::PathBuf; use mtgc_core::{Catalog, NameIndex}; /// Managed application state, guarded by a `Mutex` in Tauri's state store. pub struct AppState { pub library_path: PathBuf, pub reference_path: PathBuf, pub catalog: Option, pub index: Option, } impl AppState { /// Initialize with default paths under the app data dir and open the catalog /// if a reference db already exists. pub fn new(data_dir: PathBuf) -> Self { let mut s = Self { library_path: data_dir.join("library.db"), reference_path: data_dir.join("reference.db"), catalog: None, index: None, }; // Best-effort open; failures just leave the catalog unloaded. let _ = s.reopen(); s } /// (Re)open the catalog + rebuild the name index. Only opens when a reference /// db exists — attaching a non-existent file would create an empty (tableless) /// db and make every query fail. pub fn reopen(&mut self) -> Result<(), String> { if self.reference_path.exists() { let catalog = Catalog::open(&self.library_path, &self.reference_path) .map_err(|e| e.to_string())?; let index = catalog.build_name_index().map_err(|e| e.to_string())?; self.index = Some(index); self.catalog = Some(catalog); } else { self.catalog = None; self.index = None; } Ok(()) } pub fn catalog(&self) -> Result<&Catalog, String> { self.catalog .as_ref() .ok_or_else(|| "Card data not loaded yet — click 'Download card data'.".to_string()) } pub fn index(&self) -> Result<&NameIndex, String> { self.index .as_ref() .ok_or_else(|| "Card data not loaded yet — click 'Download card data'.".to_string()) } }