use std::fs;
use std::sync::{OnceLock, RwLock};
use super::config::THEME_SKELETON_CONTENT;
use super::paths::config_dir;
use super::resolve::{ThemeSource, resolve_theme};
use super::types::Theme;
static THEME_STORE: OnceLock<RwLock<Theme>> = OnceLock::new();
fn load_initial_theme() -> Theme {
let resolved = resolve_theme();
if resolved.source == ThemeSource::Default {
ensure_theme_file_exists();
}
resolved.theme
}
fn ensure_theme_file_exists() {
let path = config_dir().join("theme.conf");
let should_create = fs::metadata(&path).map_or(true, |meta| meta.len() == 0);
if should_create {
if let Some(dir) = path.parent()
&& let Err(e) = fs::create_dir_all(dir)
{
tracing::error!(
path = %dir.display(),
error = %e,
"Failed to create theme config directory"
);
return;
}
match fs::write(&path, THEME_SKELETON_CONTENT) {
Ok(()) => {
tracing::info!(path = %path.display(), "Created theme.conf skeleton");
}
Err(e) => {
tracing::error!(
path = %path.display(),
error = %e,
"Failed to write theme.conf skeleton"
);
}
}
}
}
pub fn theme() -> Theme {
let lock = THEME_STORE.get_or_init(|| RwLock::new(load_initial_theme()));
*lock.read().expect("theme store poisoned")
}
pub fn reload_theme() -> std::result::Result<(), String> {
let resolved = resolve_theme();
let lock = THEME_STORE.get_or_init(|| RwLock::new(load_initial_theme()));
lock.write().map_or_else(
|_| Err("Failed to acquire theme store for writing".to_string()),
|mut guard| {
*guard = resolved.theme;
tracing::info!(source = ?resolved.source, "Theme reloaded");
Ok(())
},
)
}