feat: implementa persistência de sessão com opções para salvar e carregar estado do projeto
This commit is contained in:
+107
-8
@@ -50,6 +50,9 @@ pub struct App {
|
||||
|
||||
// Mensagem de erro global (ex: dependências ausentes)
|
||||
global_error: Option<String>,
|
||||
|
||||
// Mensagem de feedback de persistência (sucesso ou erro)
|
||||
session_msg: Option<(String, bool)>, // (texto, é_erro)
|
||||
}
|
||||
|
||||
impl App {
|
||||
@@ -59,6 +62,17 @@ impl App {
|
||||
.err()
|
||||
.map(|e| e.to_string());
|
||||
|
||||
// Notifica o usuário se existe sessão salva ao iniciar
|
||||
let session_msg = if crate::infrastructure::persistence::session_exists() {
|
||||
Some((
|
||||
"Sessão anterior encontrada. Clique em \"Carregar sessão\" para restaurar."
|
||||
.to_string(),
|
||||
false,
|
||||
))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
App {
|
||||
project: None,
|
||||
pending_source: None,
|
||||
@@ -73,6 +87,7 @@ impl App {
|
||||
bg_rx: None,
|
||||
cancel_tx: None,
|
||||
global_error,
|
||||
session_msg,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,22 +222,106 @@ impl eframe::App for App {
|
||||
}
|
||||
|
||||
// ── Cabeçalho (fixo no topo) ──────────────────────────────────────────
|
||||
let header_height = 42.0
|
||||
+ if self.global_error.is_some() { 22.0 } else { 0.0 }
|
||||
+ if self.session_msg.is_some() { 22.0 } else { 0.0 };
|
||||
egui::TopBottomPanel::top("header_panel")
|
||||
.exact_height(if self.global_error.is_some() {
|
||||
58.0
|
||||
} else {
|
||||
38.0
|
||||
})
|
||||
.exact_height(header_height)
|
||||
.show(ctx, |ui| {
|
||||
ui.add_space(6.0);
|
||||
ui.heading("Editor de Faixas de Mídia");
|
||||
ui.add_space(4.0);
|
||||
ui.horizontal(|ui| {
|
||||
ui.heading("Editor de Faixas de Mídia");
|
||||
|
||||
ui.with_layout(
|
||||
egui::Layout::right_to_left(egui::Align::Center),
|
||||
|ui| {
|
||||
// Botão "Salvar sessão"
|
||||
let can_save = self.project.is_some();
|
||||
if ui
|
||||
.add_enabled(
|
||||
can_save,
|
||||
egui::Button::new("💾 Salvar sessão"),
|
||||
)
|
||||
.on_disabled_hover_text(
|
||||
"Abra um projeto para poder salvar a sessão.",
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
if let Some(ref project) = self.project {
|
||||
match crate::infrastructure::persistence::save_session(
|
||||
project,
|
||||
) {
|
||||
Ok(_) => {
|
||||
self.session_msg = Some((
|
||||
"Sessão salva com sucesso.".to_string(),
|
||||
false,
|
||||
));
|
||||
}
|
||||
Err(e) => {
|
||||
self.session_msg =
|
||||
Some((format!("Erro ao salvar: {}", e), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Botão "Carregar sessão"
|
||||
let can_load =
|
||||
crate::infrastructure::persistence::session_exists();
|
||||
if ui
|
||||
.add_enabled(
|
||||
can_load,
|
||||
egui::Button::new("📂 Carregar sessão"),
|
||||
)
|
||||
.on_disabled_hover_text("Nenhuma sessão salva encontrada.")
|
||||
.clicked()
|
||||
{
|
||||
match crate::infrastructure::persistence::load_session() {
|
||||
Ok(project) => {
|
||||
self.pending_source =
|
||||
Some(project.source.path.clone());
|
||||
self.pending_output =
|
||||
Some(project.output.path.clone());
|
||||
self.existing_track_list
|
||||
.sync_tracks(&project.existing_tracks);
|
||||
self.project = Some(project);
|
||||
self.session_msg = Some((
|
||||
"Sessão carregada com sucesso.".to_string(),
|
||||
false,
|
||||
));
|
||||
}
|
||||
Err(e) => {
|
||||
self.session_msg = Some((
|
||||
format!("Erro ao carregar sessão: {}", e),
|
||||
true,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
if let Some(ref err) = self.global_error {
|
||||
ui.add_space(2.0);
|
||||
ui.colored_label(
|
||||
egui::Color32::RED,
|
||||
format!("⚠ Dependência ausente: {}", err),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some((msg, is_err)) = self.session_msg.clone() {
|
||||
let color = if is_err {
|
||||
egui::Color32::RED
|
||||
} else {
|
||||
egui::Color32::from_rgb(0, 180, 80)
|
||||
};
|
||||
ui.horizontal(|ui| {
|
||||
ui.colored_label(color, &msg);
|
||||
if ui.small_button("✕").clicked() {
|
||||
self.session_msg = None;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ── Painel de execução (fixo no rodapé) ───────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user