use std::collections::HashMap;
use std::path::PathBuf;
use blinc_platform::WindowConfig;
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct SavedWindowState {
pub x: i32,
pub y: i32,
pub width: u32,
pub height: u32,
pub maximized: bool,
}
impl SavedWindowState {
pub fn apply_to(&self, mut config: WindowConfig) -> WindowConfig {
config.width = self.width;
config.height = self.height;
config.position = Some((self.x, self.y));
config
}
}
pub struct WindowStateStore {
path: PathBuf,
}
impl WindowStateStore {
pub fn new(app_name: &str) -> Self {
let dir = dirs_path(app_name);
Self {
path: dir.join("window_state.json"),
}
}
pub fn with_path(path: impl Into<PathBuf>) -> Self {
Self { path: path.into() }
}
pub fn load(&self, window_name: &str) -> Option<SavedWindowState> {
let content = std::fs::read_to_string(&self.path).ok()?;
let map: HashMap<String, SavedWindowState> = serde_json::from_str(&content).ok()?;
map.get(window_name).cloned()
}
pub fn save(&self, window_name: &str, state: &SavedWindowState) -> bool {
let mut map: HashMap<String, SavedWindowState> = self
.path
.exists()
.then(|| {
std::fs::read_to_string(&self.path)
.ok()
.and_then(|c| serde_json::from_str(&c).ok())
})
.flatten()
.unwrap_or_default();
map.insert(window_name.to_string(), state.clone());
if let Some(parent) = self.path.parent() {
if let Err(e) = std::fs::create_dir_all(parent) {
tracing::warn!("Failed to create window state directory: {}", e);
return false;
}
}
match serde_json::to_string_pretty(&map) {
Ok(json) => std::fs::write(&self.path, json).is_ok(),
Err(_) => false,
}
}
pub fn remove(&self, window_name: &str) -> bool {
if let Ok(content) = std::fs::read_to_string(&self.path) {
if let Ok(mut map) = serde_json::from_str::<HashMap<String, SavedWindowState>>(&content)
{
map.remove(window_name);
if let Ok(json) = serde_json::to_string_pretty(&map) {
return std::fs::write(&self.path, json).is_ok();
}
}
}
false
}
}
fn dirs_path(app_name: &str) -> PathBuf {
#[cfg(target_os = "macos")]
{
let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
PathBuf::from(home)
.join("Library")
.join("Application Support")
.join(app_name)
}
#[cfg(target_os = "windows")]
{
let appdata = std::env::var("APPDATA").unwrap_or_else(|_| "C:\\".to_string());
PathBuf::from(appdata).join(app_name)
}
#[cfg(not(any(target_os = "macos", target_os = "windows")))]
{
let home = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
PathBuf::from(home).join(".config").join(app_name)
}
}