feat: atualiza versão do projeto para 1.3 e revisa o plano de desenvolvimento e PRD com novas funcionalidades e requisitos

This commit is contained in:
2026-02-28 18:19:03 -03:00
parent 16dcb0b9d4
commit 18739c3ce7
3 changed files with 266 additions and 136 deletions
+66 -54
View File
@@ -2,7 +2,7 @@
**Data:** 28/02/2026
**Status:** Fases 16 concluídas + exportação de faixa + exibição/remoção de faixas adicionadas + layout responsivo + progresso em tempo real + cancelamento de geração — compilando, 33 testes passando, zero warnings do projeto, aplicação executável
**Referência:** DEVELOPMENT_PLAN.md v1.1
**Referência:** DEVELOPMENT_PLAN.md v1.3
---
@@ -14,6 +14,7 @@ Todas as 6 fases do plano de desenvolvimento foram implementadas. O projeto comp
Todos os 14 warnings de `unused`/`dead_code` foram resolvidos: assignment morto em `command_builder.rs` removido, lifetime explícito em `FilePath::to_string_lossy` corrigido, e APIs arquiteturais não chamadas pela UI suprimidas com `#[allow(dead_code)]`.
Após a conclusão das fases, foram implementadas funcionalidades adicionais:
- Exportação de faixa de áudio ou legenda diretamente da lista de faixas existentes
- Exibição das faixas externas adicionadas com opção de remoção individual
- Layout responsivo com painéis fixos (cabeçalho, rodapé, barra lateral) e área central com scroll
@@ -24,14 +25,14 @@ Após a conclusão das fases, foram implementadas funcionalidades adicionais:
## Status por Fase
| Fase | Descrição | Status |
|------|----------------------------------|-------------|
| 1 | Setup do projeto | ✅ Concluída |
| 2 | Domain (núcleo puro) | ✅ Concluída |
| 3 | Application (use cases + ports) | ✅ Concluída |
| 4 | Adapters (FFmpeg + filesystem) | ✅ Concluída |
| 5 | Infrastructure (processo async) | ✅ Concluída |
| 6 | UI (eframe/egui) | ✅ Concluída |
| Fase | Descrição | Status |
| ---- | ------------------------------- | ------------ |
| 1 | Setup do projeto | ✅ Concluída |
| 2 | Domain (núcleo puro) | ✅ Concluída |
| 3 | Application (use cases + ports) | ✅ Concluída |
| 4 | Adapters (FFmpeg + filesystem) | ✅ Concluída |
| 5 | Infrastructure (processo async) | ✅ Concluída |
| 6 | UI (eframe/egui) | ✅ Concluída |
---
@@ -110,61 +111,67 @@ src/
## Testes Unitários (33/33 passando)
### Domain — Value Objects
| Teste | Resultado |
|-------|-----------|
| `sync_offset::from_seconds_str_positivo``"1.2"``SyncOffset(1200)` | ✅ |
| `sync_offset::from_seconds_str_negativo``"-0.5"``SyncOffset(-500)` | ✅ |
| `sync_offset::from_seconds_str_com_sufixo_s` | ✅ |
| `sync_offset::from_seconds_str_invalido` | ✅ |
| `sync_offset::from_seconds_str_zero` | ✅ |
| `track_language::idioma_valido``"por"`, `"eng"` | ✅ |
| `track_language::idioma_invalido_curto``"pt"` | ✅ |
| `track_language::idioma_invalido_maiusculo``"POR"` | ✅ |
| `track_language::idioma_invalido_longo``"port"` | ✅ |
| Teste | Resultado |
| ------------------------------------------------------------------------ | --------- |
| `sync_offset::from_seconds_str_positivo``"1.2"``SyncOffset(1200)` | ✅ |
| `sync_offset::from_seconds_str_negativo``"-0.5"``SyncOffset(-500)` | ✅ |
| `sync_offset::from_seconds_str_com_sufixo_s` | ✅ |
| `sync_offset::from_seconds_str_invalido` | ✅ |
| `sync_offset::from_seconds_str_zero` | ✅ |
| `track_language::idioma_valido``"por"`, `"eng"` | ✅ |
| `track_language::idioma_invalido_curto``"pt"` | ✅ |
| `track_language::idioma_invalido_maiusculo``"POR"` | ✅ |
| `track_language::idioma_invalido_longo``"port"` | ✅ |
### Domain — Entities
| Teste | Resultado |
|-------|-----------|
| `project::projeto_valido` | ✅ |
| `project::projeto_invalido_mesmo_caminho` — output == source retorna erro | ✅ |
| `project::track_id_opaco` — TrackId não expõe indexação interna | ✅ |
| Teste | Resultado |
| ------------------------------------------------------------------------- | --------- |
| `project::projeto_valido` | ✅ |
| `project::projeto_invalido_mesmo_caminho` — output == source retorna erro | ✅ |
| `project::track_id_opaco` — TrackId não expõe indexação interna | ✅ |
### Application — Use Cases (todos com mocks, sem I/O real)
| Teste | Resultado |
|-------|-----------|
| `load_media_info::carrega_faixas_no_projeto` | ✅ |
| `add_audio_track::adiciona_audio_no_projeto` | ✅ |
| `add_subtitle::adiciona_legenda_no_projeto` | ✅ |
| `adjust_sync::ajusta_offset_existente` | ✅ |
| `adjust_sync::erro_se_id_inexistente` | ✅ |
| `edit_existing_track_sync::edita_offset_de_faixa_existente` | ✅ |
| `edit_existing_track_sync::erro_se_faixa_existente_nao_encontrada` | ✅ |
| `set_track_language::altera_idioma_da_faixa` | ✅ |
| `generate_output::sempre_inclui_c_copy` | ✅ |
| Teste | Resultado |
| ------------------------------------------------------------------ | --------- |
| `load_media_info::carrega_faixas_no_projeto` | ✅ |
| `add_audio_track::adiciona_audio_no_projeto` | ✅ |
| `add_subtitle::adiciona_legenda_no_projeto` | ✅ |
| `adjust_sync::ajusta_offset_existente` | ✅ |
| `adjust_sync::erro_se_id_inexistente` | ✅ |
| `edit_existing_track_sync::edita_offset_de_faixa_existente` | ✅ |
| `edit_existing_track_sync::erro_se_faixa_existente_nao_encontrada` | ✅ |
| `set_track_language::altera_idioma_da_faixa` | ✅ |
| `generate_output::sempre_inclui_c_copy` | ✅ |
### Adapters — FfmpegCommandBuilder
| Teste | Resultado |
|-------|-----------|
| `sempre_contem_c_copy` — invariante RNF-01 | ✅ |
| `output_e_o_ultimo_argumento` | ✅ |
| `itsoffset_formato_correto``1200ms``"1.200"` | ✅ |
| `mapa_faixa_externa_de_audio``map 1:a` | ✅ |
| `metadata_idioma_audio``-metadata:s:a:0 language=por` | ✅ |
| Teste | Resultado |
| -------------------------------------------------------- | --------- |
| `sempre_contem_c_copy` — invariante RNF-01 | ✅ |
| `output_e_o_ultimo_argumento` | ✅ |
| `itsoffset_formato_correto``1200ms``"1.200"` | ✅ |
| `mapa_faixa_externa_de_audio``map 1:a` | ✅ |
| `metadata_idioma_audio``-metadata:s:a:0 language=por` | ✅ |
### Application — ExportTrack
| Teste | Resultado |
|-------|-----------|
| `export_track::exporta_audio_com_c_a_copy``-c:a copy` presente, sem `-c copy` genérico | ✅ |
| `export_track::exporta_audio_mapeia_stream_correto``0:stream_index` correto | ✅ |
| `export_track::exporta_legenda_sem_c_copy` — nenhuma forma de `-c` para legendas | ✅ |
| `export_track::exporta_legenda_output_e_ultimo_argumento` | ✅ |
| `export_track::rejeita_faixa_de_video` — retorna erro para `TrackKind::Video` | ✅ |
| Teste | Resultado |
| ----------------------------------------------------------------------------------------- | --------- |
| `export_track::exporta_audio_com_c_a_copy``-c:a copy` presente, sem `-c copy` genérico | ✅ |
| `export_track::exporta_audio_mapeia_stream_correto``0:stream_index` correto | ✅ |
| `export_track::exporta_legenda_sem_c_copy` — nenhuma forma de `-c` para legendas | ✅ |
| `export_track::exporta_legenda_output_e_ultimo_argumento` | ✅ |
| `export_track::rejeita_faixa_de_video` — retorna erro para `TrackKind::Video` | ✅ |
### Application — RemoveTrack
| Teste | Resultado |
|-------|-----------|
| `remove_track::remove_faixa_existente` — faixa removida do Vec | ✅ |
| `remove_track::erro_se_id_inexistente`retorna erro se id não existe | ✅ |
| Teste | Resultado |
| ---------------------------------------------------------------------- | --------- |
| `remove_track::remove_faixa_existente`faixa removida do Vec | ✅ |
| `remove_track::erro_se_id_inexistente` — retorna erro se id não existe | ✅ |
---
@@ -195,12 +202,16 @@ rfd = "0.14"
## O Que Falta (Backlog de Refinamento)
### Funcional
- [x] Exportar faixa de áudio ou legenda existente para arquivo separado
- [x] Exibição de faixas externas adicionadas com opção de remover
- [x] Progresso em tempo real via `run_ffmpeg_async``run_ffmpeg_async` usa `std::sync::mpsc::Sender<String>`; `start_generation` cria tokio Runtime + thread encaminhadora; cada linha de stderr do FFmpeg aparece no log antes do término
- [x] Cancelamento de geração — botão "Cancelar" visível durante `Running`; sinal via `tokio::sync::oneshot`; `child.kill().await` no `tokio::select!`; estado `ExecutionState::Cancelled` exibido em amarelo
- [ ] **Fase 7 — Persistência do Estado** — salvar/carregar `Project` em JSON (`~/.config/...`); botões "Salvar sessão" / "Carregar sessão" no header; novo módulo `infrastructure/persistence` — ver DEVELOPMENT_PLAN.md Fase 7
- [ ] **Fase 8 — Modo Lote via Abas** — navegação por abas (`Projeto Único` / `Lote`); `Vec<BatchItem>` em `App`; processamento sequencial (um por vez); novo componente `BatchPanel` — ver DEVELOPMENT_PLAN.md Fase 8
### Qualidade
- [x] Corrigir 14 warnings de `unused`/`dead_code` identificados por `cargo build`:
- `next_input_idx += 1` removido do loop externo em `command_builder.rs` (assignment nunca lido)
- Lifetime explícito `Cow<'_, str>` adicionado em `FilePath::to_string_lossy`
@@ -210,6 +221,7 @@ rfd = "0.14"
- [ ] Testes de snapshot para o `FfmpegCommandBuilder` com projetos mais complexos
### UI
- [x] Layout responsivo mais refinado
- [ ] Exibição do comando FFmpeg gerado em modo debug (ex: painel colapsável na `ExecutionPanel`)
- [ ] Persistência do estado do projeto em disco (`serde` já disponível)