Atualiza PRD para versão 1.4, adiciona novos requisitos funcionais (RF-12 a RF-15) e remove o arquivo PROGRESS.md. Implementa painel de debug para exibir o comando gerado pelo FFmpeg/mkvmerge na ExecutionPanel, permitindo cópia e inspeção do comando. Melhora a interface e a persistência de estado do projeto.

This commit is contained in:
2026-03-01 22:10:13 -03:00
parent 8b031f07ec
commit e347202e95
4 changed files with 285 additions and 1066 deletions
+162
View File
@@ -0,0 +1,162 @@
# Implementação — DT-10: Painel de Debug do Comando Gerado
**Data:** 01/03/2026
**Status:** Planejado
**Prioridade:** Baixa — melhoria de DX para usuário técnico
**Arquivos afetados:**
- `src/ui/components/execution_panel.rs`
- `src/ui/app.rs`
- `PRD.md` (documentação ao concluir)
---
## Objetivo
Exibir, de forma colapsável na `ExecutionPanel`, o comando exato (`ffmpeg …` ou `mkvmerge …`) que foi enviado ao processo externo na última geração. Permite que o usuário técnico inspecione, copie e reproduza o comando manualmente para diagnóstico.
---
## Viabilidade
| Ponto | Situação |
| ------------------------------------------------ | ------------------------------------------------ | --- | ---------------------------------- |
| `args: Vec<String>` já construído antes do spawn | `start_generation()` — linha ~244 de `app.rs` |
| `ExecutionPanel` já usa `ui.collapsing()` | Padrão reutilizado do "Log detalhado" |
| Nenhuma camada nova necessária | Mudanças em 2 arquivos apenas |
| Sem impacto em testes existentes | Campo additive — nenhuma assinatura pública muda |
| Botão "Copiar" sem dependência adicional | `ui.output_mut( | o | o.copied_text = …)` nativo do egui |
**Estimativa:** ~30 linhas adicionadas. Risco zero de regressão.
---
## Passo 1 — Campo `last_command` em `ExecutionPanel`
**Arquivo:** `src/ui/components/execution_panel.rs`
Adicionar o campo à struct:
```rust
pub struct ExecutionPanel {
pub state: ExecutionState,
pub log_lines: Vec<String>,
/// Comando completo enviado ao FFmpeg/mkvmerge na última geração.
/// Exemplo: "ffmpeg -i input.mkv -c copy ... output.mkv"
pub last_command: Option<String>,
}
```
Inicializar em `ExecutionPanel::new()`:
```rust
pub fn new() -> Self {
ExecutionPanel {
state: ExecutionState::Idle,
log_lines: Vec::new(),
last_command: None,
}
}
```
---
## Passo 2 — Formatar e armazenar o comando em `app.rs`
**Arquivo:** `src/ui/app.rs`
**Localização:** método `start_generation()`, logo após construir `args` e antes do `thread::spawn`
```rust
// Formatar comando legível para o painel de debug
let binary = if uses_mkvmerge { "mkvmerge" } else { "ffmpeg" };
let cmd_str = format!(
"{} {}",
binary,
args.iter()
.map(|a| if a.contains(' ') { format!("\"{}\"", a) } else { a.clone() })
.collect::<Vec<_>>()
.join(" ")
);
self.execution_panel.last_command = Some(cmd_str);
```
> **Atenção:** replicar o mesmo bloco em `start_batch_generation()` para cobrir o modo Lote (RF-09).
---
## Passo 3 — Renderizar o painel colapsável em `ExecutionPanel::ui()`
**Arquivo:** `src/ui/components/execution_panel.rs`
**Localização:** após o bloco `"Log detalhado"`, antes do `});` de fechamento do `ui.group`
```rust
if let Some(cmd) = &self.last_command {
ui.collapsing("🛠 Comando gerado", |ui| {
let mut cmd_str = cmd.as_str();
ui.add(
egui::TextEdit::multiline(&mut cmd_str)
.desired_rows(3)
.desired_width(f32::INFINITY)
.font(egui::TextStyle::Monospace),
);
if ui.small_button("📋 Copiar").clicked() {
ui.output_mut(|o| o.copied_text = cmd.clone());
}
});
}
```
**Comportamento esperado:**
- Colapsável fechado por padrão — não ocupa espaço visual desnecessário
- `TextEdit` somente leitura (variável local imutável no contexto do egui)
- Botão "📋 Copiar" coloca o comando no clipboard do sistema
- Argumento com espaço interno é envolvido em aspas para reprodutibilidade no terminal
---
## Passo 4 — Comportamento de limpeza
`last_command` **não** é limpo ao iniciar nova geração — ele é sobrescrito. O usuário vê sempre o comando da execução atual.
`last_command` **não** é limpo em `cancel_generation()` — o usuário pode querer inspecionar o comando de uma geração cancelada.
Não há necessidade de resetar em nenhum outro ponto.
---
## Passo 5 — Atualizar PRD e débitos técnicos
Ao concluir a implementação:
1. Marcar DT-10 como `✅ Resolvido` na tabela da seção 10 do `PRD.md`
2. Remover o item do backlog da seção 11
3. Adicionar critério de aceitação na seção 12:
- `[x] O comando FFmpeg/mkvmerge gerado é exibido em painel colapsável na ExecutionPanel (DT-10)`
---
## Ordem de execução recomendada
| # | Passo | Testável após |
| --- | --------------------------------------------------------------------- | ---------------------------------- |
| 1 | Adicionar campo + init em `ExecutionPanel` | `cargo check` |
| 2 | Renderizar painel colapsável (Passo 3) com valor hardcoded temporário | `cargo run` — inspeção visual |
| 3 | Wiring em `start_generation()` (Passo 2) | `cargo run` — geração real |
| 4 | Replicar wiring em `start_batch_generation()` | `cargo run` — modo lote |
| 5 | Remover hardcode temporário se usado; `cargo test` | 33 testes devem continuar passando |
| 6 | Atualizar PRD (Passo 5) | — |
---
## Critério de aceitação
- [ ] O painel "🛠 Comando gerado" aparece na `ExecutionPanel` após a primeira geração
- [ ] O painel está colapsado por padrão
- [ ] O conteúdo exibe o binário (`ffmpeg` ou `mkvmerge`) seguido de todos os argumentos
- [ ] Argumentos com espaços internos são envolvidos em aspas duplas
- [ ] O botão "📋 Copiar" coloca o texto no clipboard
- [ ] O comando é exibido também para gerações canceladas
- [ ] O painel **não** aparece antes da primeira geração (estado `Idle` inicial)
- [ ] Modo Lote exibe o comando do último item processado
- [ ] `cargo test` — 33 testes passando sem regressão