use crate::domain::entities::Project; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; use std::path::PathBuf; /// Dados de sessão persistidos — abrange o Projeto Único e o carrinho de Lote. #[derive(Serialize, Deserialize, Default)] pub struct SessionData { /// Projeto aberto na aba "Projeto Único". pub single_project: Option, /// Projetos do carrinho de Lote (estados de execução são descartados ao salvar). pub batch_projects: Vec, } /// Retorna o caminho do arquivo de sessão de acordo com o SO. /// /// - Linux / macOS : `$HOME/.config/simple-mkv-editor/session.json` /// - Windows : `%APPDATA%\simple-mkv-editor\session.json` fn session_path() -> PathBuf { #[cfg(target_os = "windows")] let base = std::env::var("APPDATA") .map(PathBuf::from) .unwrap_or_else(|_| PathBuf::from(".")); #[cfg(not(target_os = "windows"))] let base = std::env::var("HOME") .map(|h| PathBuf::from(h).join(".config")) .unwrap_or_else(|_| PathBuf::from(".")); base.join("simple-mkv-editor").join("session.json") } /// Verifica se existe um arquivo de sessão gravado em disco. pub fn session_exists() -> bool { session_path().exists() } /// Serializa a `SessionData` para JSON e grava no arquivo de sessão. /// /// Cria o diretório pai automaticamente se ele não existir. pub fn save_session(data: &SessionData) -> Result<()> { let path = session_path(); if let Some(parent) = path.parent() { std::fs::create_dir_all(parent).with_context(|| { format!( "Não foi possível criar o diretório de sessão: {}", parent.display() ) })?; } let json = serde_json::to_string_pretty(data).context("Falha ao serializar a sessão")?; std::fs::write(&path, json) .with_context(|| format!("Falha ao gravar sessão em: {}", path.display()))?; Ok(()) } /// Lê e desserializa a `SessionData` do arquivo de sessão. /// /// Retorna erro amigável se o arquivo estiver ausente, corrompido ou em /// versão incompatível com a estrutura atual do domínio. pub fn load_session() -> Result { let path = session_path(); let json = std::fs::read_to_string(&path).with_context(|| { format!( "Não foi possível ler o arquivo de sessão: {}", path.display() ) })?; // Tenta desserializar como SessionData (formato novo). // Se falhar, tenta o formato antigo (Project direto) e migra automaticamente. if let Ok(data) = serde_json::from_str::(&json) { return Ok(data); } // Migração transparente: arquivo gerado pela Fase 7 continha apenas um Project. serde_json::from_str::(&json) .map(|project| SessionData { single_project: Some(project), batch_projects: Vec::new(), }) .with_context(|| { "Falha ao carregar a sessão. O arquivo pode estar corrompido ou em versão incompatível. \ Delete o arquivo de sessão e tente novamente." }) }