//! Theme loading commands — thin Tauri wrappers over `theme_common`. use std::path::PathBuf; use tauri::{AppHandle, Manager}; use tracing::instrument; use super::ApiError; pub use theme_common::{ThemeColors, ThemeMeta}; /// Returns theme directories in priority order (later overrides earlier by ID). /// Each entry is `(path, is_custom)`. fn theme_dirs(app: &AppHandle) -> Vec<(PathBuf, bool)> { let mut dirs = Vec::new(); // 1. Bundled themes (production) if let Ok(resource_dir) = app.path().resource_dir() { let bundled = resource_dir.join("themes"); if bundled.is_dir() { dirs.push((bundled, false)); } } // 2. Dev fallback: CARGO_MANIFEST_DIR → 3 parents up → Git/themes/ if let Some(dev_path) = theme_common::dev_themes_dir(env!("CARGO_MANIFEST_DIR").as_ref(), 3) { dirs.push((dev_path, false)); } // 3. User custom themes (highest priority) if let Ok(config_dir) = app.path().app_config_dir() { let custom = config_dir.join("themes"); if custom.is_dir() { dirs.push((custom, true)); } } dirs } #[tauri::command] #[instrument(skip_all)] pub fn list_themes(app: AppHandle) -> Result, ApiError> { let dirs = theme_dirs(&app); Ok(theme_common::list_themes_from_dirs(&dirs)) } #[tauri::command] #[instrument(skip_all)] pub fn get_theme(app: AppHandle, id: String) -> Result { let dirs = theme_dirs(&app); theme_common::load_theme(&dirs, &id).map_err(ApiError::internal) } #[tauri::command] #[instrument(skip_all)] pub fn get_custom_themes_dir(app: AppHandle) -> Result { let dir = app .path() .app_config_dir() .map_err(|e| ApiError::internal(e.to_string()))? .join("themes"); std::fs::create_dir_all(&dir) .map_err(|e| ApiError::internal(format!("Failed to create themes dir: {}", e)))?; Ok(dir.to_string_lossy().to_string()) } #[tauri::command] #[instrument(skip_all)] pub fn import_theme(app: AppHandle, path: String) -> Result { let custom_dir = app .path() .app_config_dir() .map_err(|e| ApiError::internal(e.to_string()))? .join("themes"); theme_common::import_theme(std::path::Path::new(&path), &custom_dir) .map_err(ApiError::internal) } #[tauri::command] #[instrument(skip_all)] pub fn export_theme(app: AppHandle, id: String, path: String) -> Result<(), ApiError> { let dirs = theme_dirs(&app); theme_common::export_theme(&dirs, &id, std::path::Path::new(&path)) .map_err(ApiError::internal) } #[cfg(test)] mod tests { // Core theme logic tests live in theme-common crate. // App-specific tests here only if needed for theme_dirs behavior. }