The only use is in a #[cfg(unix)] symlink test, so clippy -D warnings
flagged the import on Windows. Name the function at its use instead.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sequences already store a work area, and Export > Range lists Work
Area, but no command set one, so the Work Area range was grayed out.
The Timeline panel menu's Work Area Bar now shows the bar over the
whole sequence or hides it. Alt+[ and Alt+] in the Timeline move its
start and end to the playhead. On the ruler the bar's ends and middle
can be dragged, a double-click fits it to the part of the sequence the
ruler shows, and its tooltip shows the start, end and duration.
The new commands are sequence.workAreaBar, sequence.setWorkAreaIn,
sequence.setWorkAreaOut and sequence.setWorkArea. The two keys move
from the skipped table in docs/keyboard.md to the keyboard-only
commands.
* media: import animated WebP as a clip
* animated WebP test: use is_multiple_of (clippy)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The History panel's menu had no entries of its own. It now has Delete
Redoable Actions, which asks for OK and then removes the dimmed steps
after the current state, and Clear History, which removes every step.
Neither one changes the project or its unsaved state. Backspace in the
History panel opens the same confirmation.
The engine commands are history.deleteRedoable and history.clear; both
return {"deleted": n}.
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Text panel: the Captions list follows the playhead
As the playhead reaches a caption, the Captions list scrolls it to the middle, so the list stays
lined up with the Timeline during playback and scrubbing. Each caption is brought into view once
(scrolling the list by hand still works), and never while a field in the panel has focus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Move the Captions list follow test into the shared ui-egui test binary
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Edit: Copy, Cut and Paste work on captions selected in the Timeline
With only captions selected, Edit ▸ Copy / Cut (⌘C / ⌘X) copy them to a caption clipboard,
and Paste / Paste Insert (⌘V / ⇧⌘V) place them at the playhead on the caption tracks they came
from (the last track when that one is gone), overwriting what is there; Paste Insert first pushes
later captions on by the copied span. The pasted captions are selected, the playhead moves past
them, and it is one undo step. Copying clips empties the caption clipboard and the other way
round, so Paste places whichever was copied last. Before, Copy did nothing with only captions
selected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Move the caption copy/paste UI test into the shared ui-egui test binary
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Timeline: Option-drag duplicates captions
Option-dragging a caption block leaves the original in place and drops a copy where it is
released; the cursor turns into a copy cursor and the original stays drawn under the copy while
dragging. A drag now carries the whole caption selection, not only the grabbed block.
New command `captions.duplicate` {captions, delta|deltaFrames}: copies on their own tracks,
never before 0, selected afterwards, one undo step. Captions never overlap, so
`edit::captions::overwrite_captions` places copies over what is there: captions under a copy are
trimmed, split around it or removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* captions.duplicate: refuse an empty caption list and copy each caption once; move its UI test into the shared ui-egui test binary
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Timeline: the Razor tool cuts captions
With the Razor tool (C), a click on a caption block in the Timeline splits it there, snapped like
a clip cut, with the same white preview line; Shift cuts every caption on an unlocked caption
track at that time. Before, the caption blocks took every click for select/move whatever the
tool, so the Razor did nothing on them. Locked caption tracks ignore it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Move the caption Razor UI test into the shared ui-egui test binary
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
After Stop the meters kept the playback ballistics (20 dB/s bars, 6 dB/s
peak holds), so a -23 dB peak took ~11 s to clear and the meters looked
like audio was still playing. Once nothing is live, bars and peak holds
now fall at 360 dB/s and reach the floor within ~0.25 s. Playback,
recording and scrubbing ballistics are unchanged; the no-input repaint
from #1133 (#1062) still drives the release.
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* control: preserve MCP pointer input defaults (#2784)
The MCP bridge emits null for omitted click counts and drag steps. Treat null like an absent value in bounded_repetitions, preserving the bounds introduced by #2868 and all other invalid-input errors. Add six regression tests and document the current limits and defaults.
Validation: both null-default tests failed against upstream before the fix; 205 UI unit tests and seven UI integration tests now pass. Formatting, layers, assets and browser WASM pass. Full CI stops at an unrelated upstream Clippy diagnostic in crates/prores/src/decode.rs:133. Prepared as a non-draft PR at the contributor’s explicit request.
Co-authored-by: Codex <noreply@openai.com>
* docs: explain pointer input defaults and regression coverage (#2784)
Document the bounded repetition helper, MCP pointer handlers and regression tests in response to CodeRabbit docstring coverage feedback. No executable behavior changes.
Validation: formatting and Rustdoc generation pass. Full CI still stops at the unchanged upstream ProRes nonminimal_bool Clippy diagnostic in crates/prores/src/decode.rs:133.
Co-authored-by: Codex <noreply@openai.com>
---------
Co-authored-by: Codex <noreply@openai.com>
Write the required run after the final alpha difference, including a singleton. Add exact-codeword and strict slice conformance regressions; document native macOS and EffectCraft export validation.
Stop deleting after the first filesystem error and restore failed, unprocessed
and unselected candidates before returning it. Keep completed deletions removed.
Three real filesystem regressions reproduced list loss. Fourteen autosave
tests, formatting and strict engine lint pass; full CI runs on GitHub.
Refs #2792.
Co-authored-by: Codex <noreply@openai.com>
Keep unique frame identities while lazily caching one gray backing for
the active geometry and plane depths. Invalidate it on format changes
and release it on flush without invalidating readers.
Fixes#2797.
Co-authored-by: Codex <noreply@openai.com>
Set two-minute read/write timeouts and close expired connections quietly.
Keep partial requests out of the UI queue and preserve the separate UI
reply wait and active connection reuse.
Fixes#2807.
Co-authored-by: Codex <noreply@openai.com>
The Format list greyed H.265 and AV1 out as "not supported yet". It now gives the reason: they
have no software encoder, and a hardware one (NVENC on NVIDIA, VideoToolbox on macOS) was not
found. A preset that names such a format shows the same note under the Format row
(export.format.unavailable) before the export would fail. Where the encoder exists, an NVENC
H.265 export still works (ffprobe reads hvc1 Main 4:2:0 BT.709). Spanish, Japanese and Chinese
for the two notes.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/edit/src/through.rs:21 (is_through_edit) and :61-102 (join_through_edits_where)
Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
When an AAF or OMF import finds its embedded-audio path taken, it writes
the audio under a numbered name. The numbered path was built with
`Path::with_file_name`, which on Windows joins the folder and the new name
with `\` whatever separator the path was written with:
`/files/cut Audio.wav` became `/files\cut Audio (2).wav`. A document
imported by a forward-slash path stored media paths with mixed separators,
and `virtual_extraction_keeps_existing_media` failed on Windows, because
its in-memory files are keyed by string and the `(2)` name looked free.
A numbered name now replaces only the file name and keeps the folder as
written. New test `numbered_names_keep_the_path_separators` covers a `/`
and a `\` path.