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:
@@ -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
|
||||
Reference in New Issue
Block a user