rfd's Linux backend goes through the XDG desktop portal, and a blocking
`rfd::FileDialog` leaves the main thread waiting on the portal's answer
without pumping winit's events: while the Open dialog is up the window stops
answering the compositor, which offers to force-quit the app ("EffectCraft is
not responding"), until a file is picked.
The non-blocking host hook for the commands' dialogs (`rfd::AsyncFileDialog`
on a worker thread, run when the dialog closes) was macOS-only since #511.
Install it on Linux too. Windows keeps the blocking pickers (its dialog pumps
its own messages), and the panel buttons' pickers (Settings, effect file
pickers) are unchanged.
Checked headlessly against a mock XDG portal: with the hook the main thread
stays in the event loop while a worker blocks in the portal wait, `ui.inspect`
still answers 7.5 s after the dialog opened, and an answered dialog runs
File ▸ Import; without it the main thread itself blocks in the portal wait and
the app answers nothing until the dialog closes.
Co-Authored-By: DeepSeek V4.1 Flash Free <[email protected]>
The interface below the menu bar is localized (618 fixed menu entries, ~490 panel rows) but an
effect's name still rendered in English everywhere it appeared: the generated Effect menu, Effect
Controls, the Timeline and Effects & Presets.
The registry's English name is the effect's identity: `effect.list`, `effect.apply {"effect": …}`,
scripts, expressions and the property tree's group name all match on it. Only the drawing changes.
`crates/ui-egui/src/i18n/effects.rs` keys the names by effect **id** rather than by the English
string — a repeat is stored as `Gaussian Blur 2` (an English key would miss it) and upstream
renames a display name now and then, while the id is stable. It carries 306 rows for Simplified
Chinese, one per effect in the registry, taken from the installed After Effects 2026 (26.5.0.89)
Simplified Chinese interface, with the `CC` series following Adobe's Chinese documentation (which
names 68 of the 69 that its interface leaves in English). `Cryptomatte`, `EXtractoR`, `IDentifier`,
`Key Light` and `Unmult` stay in English as brand names; `Face Measurements` and `Face Track
Points` are EffectCraft's own effects. The 21 category folder names are in the same file, worded
after the effect names (channel → 通道, noise → 杂色, matte → 遮罩 …).
What draws the catalog now:
- **Effect menu:** the entries and the category submenus. The command and its `{"effect": <id>}`
params are untouched, so the menu still applies by id.
- **Effect Controls:** the header, its Rename field, the accessible name and the About popup.
- **Timeline:** effect group rows, and the search (a Chinese interface is searchable in Chinese).
- **Effects & Presets:** the rows, the drag ghost, the folder rows and the search.
Kept as they are: the effect id, the property tree's `PropGroup.name`, every automation id and
label, `effect.list`'s `name`/`category`, and the undo label (`Apply Gaussian Blur`). A name the
user typed in Effect Controls stays verbatim, and a repeated instance keeps the index the engine
appends (`Gaussian Blur 2` → `高斯模糊 2`). No other language has rows yet, Traditional Chinese
included, so those draw the registry's English name.
Tests: nine unit tests under `cargo test -p effectcraft-ui-egui --lib i18n` cover the data (every
effect has a row, the row still carries the registry's English name, ids are unique, only the five
brand names repeat their English name, every category has a row, a row names an effect the registry
knows) and the behaviour (the instance index, user renames, English and untranslated languages,
search) plus a scan pinning the drawing sites. `crates/ui-egui/tests/ui_effect_names.rs` checks the
Effect Controls header, the generated Effect menu and that the ids, automation labels and
`effect.list` stay English.
`docs/localization-parity.md` and `docs/gaps.md` no longer record effect names as deliberately
English; effect *parameter* names are still untranslated and stay the next piece.
Refs #821
window.toggleCompTimeline (\) switches between the Composition viewer
and the Timeline. window.previousPanel / nextPanel (Alt+Shift+, / .)
step through the tabs of the focused panel's frame. window.closeAll
(Cmd+Shift+W) closes every open composition when a viewer or the
Timeline is active, otherwise the focused panel.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
view.fitUpTo100 (Alt+/) fits the viewer without magnifying past 100 %.
view.previousItem / view.nextItem (Shift+, / Shift+.) activate the
previous / next open composition, wrapping.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
timeline.scrollToTime (D) centres the current time in the time graph,
timeline.scrollToLayer (X) puts the topmost selected layer at the top;
both are done when the Timeline is next drawn. timeline.parentColumn
(Shift+F4) shows or hides the Parent column.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
keys.deselectAll (Shift+F2, Cmd+Alt+Shift+A) clears the selected
keyframes, properties and groups and leaves the layers selected.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
comp.workAreaToSelection (Cmd+Alt+B) spans the selected layers, or the
whole composition with none selected. comp.activateRecent (Shift+Esc)
goes back to the composition that was active most recently within the
active one's nesting hierarchy; EditorState keeps recent_comps for it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
time.workAreaStart / time.workAreaEnd (Shift+Home / End) and
time.previousInOut / time.nextInOut (Cmd+Alt+Shift+Left / Right): the In
and Out points of the selected layers, of every layer with none selected.
time.go takes nextInOut and prevInOut.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The Timeline footer's zoom-out / zoom-in mountain icons were painted but not
interactive, and the zoom slider only reacted to drags (a click on the track did
nothing) and set the zoom without the whole-comp clamp. The icons are now buttons
(timeline.zoomOutButton / timeline.zoomInButton, one = / - step), the slider
jumps on click, and both go through set_zoom, centred on the CTI.
The layer bars and the Graph Editor share one time zoom (TimelineState start /
pps, as in After Effects); regression tests drive = / -, the buttons, the slider
and the navigator over the control channel in both views and check switching
views keeps the zoom.
Co-Authored-By: Claude <[email protected]>
(cherry picked from commit 2ee0fb656ff6bd16eed6857be10495d9f30e3a64)
(cherry picked from commit f1997d32d4c51b58467a04944889131fd741a22a)
(cherry picked from commit 1c25aeb51d37357b4b37857858db4dbea246b13a)
(cherry picked from commit 81d7fcccfc91f76f7b9640cbb7d3f75dcea56e30)
Shortcut presets accept Physical+<key> (egui US-position names) so layouts that report the
same logical key for two physical keys (AZERTY's - and )) can bind them separately; physical
bindings win for that press, and a focused panel's binding wins over an application command on
the same chord. ui.key accepts the same notation. Adds time.workAreaStart / time.workAreaEnd.
(cherry picked from commit 209543e9e0ba32f809f9ff333abb8b8ec4125cea)
(cherry picked from commit f8301a9e3e0b60e200e8a233455398741658481e)
(cherry picked from commit 4d002fabf992934e1bb73a0c32bc9f3fd3ae5447)
(cherry picked from commit 5d466c5955ee934d5347c194ec7d15fb5f58bba4)
File > Import > EffectCraft Project (and .ecproj/.ecprojx given to File > Import)
merges the project into a folder named after the file, with every id shifted past
the open project's, in one undo step. Relative footage resolves next to the file;
the result lists comps, root comps, primaryComp and missing media.
offset_ids now shifts tracker Motion Targets and saturates instead of overflowing;
fix_next_id saturates too, so a damaged file can't overflow on open or import.
Menu entry translated in all ten menu catalogues.
Rebased onto current upstream main for the split of #858 (test module list in
engine lib.rs; es/pt-br/ru/fr/de/cs menu translations).
(cherry picked from commit 19c653fccc95133fb35e978a7f7f20a18c0e8c89)
(cherry picked from commit 4e751ad2)
(cherry picked from commit ceed706cc3b5f3755769738a1ddb3d965a94ab6b)
First in the menu, as in After Effects, and for the right-clicked comp rather than the one in the viewer: the dialog keeps the comp it edits and OK passes it to comp.settings. comp.settings with only {"comp": id} opens the dialog on that comp.
Zoom to Fit Comp remembers the span it left and goes back to it when pressed
again from the whole comp.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The viewer.nudge shortcuts bailed out unless Composition, Viewer or Timeline
had focus, so with any other panel focused the arrows silently did nothing.
After Effects nudges from almost anywhere; only the Project panel owns the
arrows for its own keyboard navigation. Typing, dialogs, menus and selected
mask vertices still keep the keys.
Tests: arrow nudge from Effect Controls, no nudge from Project, Shift+arrow
10x, time untouched, click-row path.
Numpad * always added a composition marker. As in After Effects, it now
adds a layer marker to the selected layers at the current time, and a
composition marker only when no layer is selected.
- Footage sources: the cancellable wrapper (#784) forwards frame_with (#752 float curves)
and problem (#887); problem's default lives on the trait.
- Media: a called-off decode (#784) is not a footage problem (#887).
- Effect Controls rename (#953): Escape cancels (egui drops focus on Escape the same
frame), the Rename item is translated; regression test.
- i18n (#873): drop the /out-i18n/ ignore rule and the note about an uncommitted script.
- Tests: text range selector caps (#926) re-borrow the layer; the RAM preview test (#793)
sets the comp's own Resolution (#462).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Viewer: each composition keeps its Resolution in the project, as in After Effects (#417)
# Conflicts:
# crates/ui-egui/src/control.rs
# crates/ui-egui/src/menus.rs
# crates/ui-egui/src/panels/viewer_tools.rs