- Added `ActiveTab` enum to manage active tab state in `App`.
- Created `BatchItem` struct and integrated `batch_items` vector in `App`.
- Developed `BatchPanel` component for managing batch projects with inline forms.
- Implemented sequential processing in `App::start_batch_item()` with automatic advancement in `poll_background()`.
- Updated UI to display individual item states (`⏳ Aguardando | ⟳ Processando | ✓ Concluído | ⊸ Cancelado | ✗ Erro`).
- Blocked item addition/removal during processing.
- Enhanced session persistence to include batch projects in `SessionData`.
- Updated session save/load functions to handle new session structure.
93 lines
3.1 KiB
Rust
93 lines
3.1 KiB
Rust
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<Project>,
|
|
/// Projetos do carrinho de Lote (estados de execução são descartados ao salvar).
|
|
pub batch_projects: Vec<Project>,
|
|
}
|
|
|
|
/// 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<SessionData> {
|
|
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::<SessionData>(&json) {
|
|
return Ok(data);
|
|
}
|
|
|
|
// Migração transparente: arquivo gerado pela Fase 7 continha apenas um Project.
|
|
serde_json::from_str::<crate::domain::entities::Project>(&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."
|
|
})
|
|
}
|