- real.rs rewritten over module Rust APIs (Arc<Mutex<Project>> +
NodeId; the addref handle dance and renderer boxes are gone);
AppEngine trait and all panels untouched
- new app assembly layers: graphops (project/timeline/edit
primitives), effectchain (chain composition with undo groups),
renderops (montage build + ticket render + ExportTask export),
library via oakstorage directly
- module-side safe API additions: oakundo global value-semantic
push/undo/redo + from_closures, oakstorage project_arc_of
- deleted: src/oakui/ffi.rs, src/oakui/host_syms.rs, the dylib link
config in build.rs (only the gpui IOSurface framework link remains)
- the binary carries zero liboakengine references (otool/nm verified);
101 app tests green incl. the real-render and full-res e2e tests
- behavior improvements for free: sequences land in the project graph
(the facade scratch-project deviation is gone), footage drops take
one undo record, effect remove/reorder undo restores edges
- viewers show the 480px proxy immediately and a background thread
fills the sequence-resolution frame (per-monitor in-flight job,
generation-based staleness, playback skips full-res)
- preferences dialog complete: cache dir (now consumed by
default_disk_cache_path), proxy policy/divider, snapshot interval
(write-through era autosave), default transition length, audio
in/out devices (new facade device-enumeration exports; audio init
from config — playback was never creating the audio instance),
language/theme/renderer backend, all persisted via config
- shortcut map (src/shortcuts.rs): space/J/K/L, I/O, S split, A/^A,
⌘Z/⌘⇧Z, ⌘N/⌘O/⌘S/⌘E/⌘Q, frame step, Home, track zoom; dispatch
shares the menu action path and stays silent over modals
- screenshots: preferences dialog zh/en captured and reviewed
- oakengine_sequence_move_clip implemented for real (oaktimeline
TrackMoveBlockCommand; fixes the graph-ownership/gap-anchor/ripple
trim bugs the stub was hiding); same-track via the frozen C ABI,
cross-track supported by the module command
- oaknode clip blocks now declare a tex_in texture input and set
effect_input to it, so timeline clips can host effect chains; facade
test covers effect insert/remove on a real clip
- oakffmpeg-link: FFMPEG_DIR is now mandatory with a clear panic (a
Homebrew upgrade left the system ffmpeg .pc pointing at a deleted
dav1d Cellar path, breaking links); reads a git-ignored workspace
.env for IDEs that cannot inject env vars (RustRover); links the C++
stdlib for C++ codec libs (svt-av1)
- oakengine re-exports oaknode so tests share one crate instance;
it_node uses the direct instance's value type where it calls the
module FFI (the --workspace dev-dependency feature split builds
oaknode twice)
- App no longer depends on the oakengine rlib: build.rs links the
built liboakengine.dylib (+rpath, -export_dynamic, IOSurface) and
src/oakui/ffi.rs declares the pure-C surface; RealEngine calls only
the frozen oakengine_* C ABI
- host_syms.rs provides the oakcore_*/fb_* host symbols the dylib
imports via dynamic lookup
- Fix Preferences dialog crash (spawn_modal reentrancy) with a
regression test
- Timeline toolbar and viewer transport render C++-era icons (16px
grid, dark/light themes) with localized tooltips
- i18n: complete en-US table, add untranslated-key detection test
- New dialogs module (preferences, export, progress)