Decouple option codes, fix encode bugs, add test suite

Maintainability:
- Choice options now carry a stable `code` separate from the display
  `label`. The command builder and recipe storage key off codes, so
  relabeling a menu entry no longer silently changes the encode or
  breaks a saved recipe. Format/Audio dispatch is now a clean code
  match instead of `starts_with` on display strings. Old recipes that
  stored labels still load via a label fallback.

Correctness:
- Fade start times now scale by the speed factor already applied in the
  filter chain, so Speed + Fade produces a fade in the right place
  regardless of op order (video and audio).
- Two-pass pass 1 uses the platform null device (NUL on Windows).
- The stderr drain thread is joined before Finished is sent, so the
  failure tail reported to the user is never truncated.

Features / cleanup:
- Accept multiple file arguments on the CLI to open batch mode directly.
- try_recv() instead of recv_timeout(ZERO); drop unused import.

Testing:
- 23 unit tests covering build() arg generation, speed/fade ordering,
  recipe round-trip + old-label fallback, and the pure helpers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-17 15:47:16 +01:00
parent 16acb43daf
commit 4daca8247c
7 changed files with 680 additions and 232 deletions
+1 -1
View File
@@ -320,7 +320,7 @@ fn draw_modal(f: &mut Frame, app: &mut App, modal: &Modal) {
};
let value = match &fld.value {
FieldValue::Choice { options, selected: s } => {
format!("\u{25c2} {} \u{25b8}", options[*s])
format!("\u{25c2} {} \u{25b8}", options[*s].label)
}
FieldValue::Text(s) => {
if selected {