Files
simple-multimidia-track-aud…/docs/impl-dt10-debug-panel.md
T

163 lines
6.1 KiB
Markdown

# Implementação — DT-10: Painel de Debug do Comando Gerado
**Data:** 01/03/2026
**Status:** ✅ Implementado
**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
- [x] O painel "🛠 Comando gerado" aparece na `ExecutionPanel` após a primeira geração
- [x] O painel está colapsado por padrão
- [x] O conteúdo exibe o binário (`ffmpeg` ou `mkvmerge`) seguido de todos os argumentos
- [x] Argumentos com espaços internos são envolvidos em aspas duplas
- [x] O botão "📋 Copiar" coloca o texto no clipboard
- [x] O comando é exibido também para gerações canceladas
- [x] O painel **não** aparece antes da primeira geração (estado `Idle` inicial)
- [x] Modo Lote exibe o comando do último item processado
- [x] `cargo test` — 68 testes passando sem regressão