diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 2e3a7beb..421a6329 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -344,6 +344,7 @@ pub struct FilmcraftApp { pub shortcut_editor: panels::shortcuts_dialog::EditorState, pub toast: Option<(String, f64)>, pub tl: panels::timeline::TlState, + pub(crate) transcript_cache: panels::transcript_cache::TranscriptCache, /// Commands from outside the UI (native menu bar), invoked on the UI thread. pub command_inbox: Option>, /// A V key press (or a Ctrl+V paste) reached the app and its release hasn't yet. @@ -568,6 +569,7 @@ impl FilmcraftApp { toast: None, graphics_notice: None, tl: Default::default(), + transcript_cache: Default::default(), command_inbox: None, v_down: false, stale_clipboard_media: None, diff --git a/crates/ui-egui/src/panels/effect_controls.rs b/crates/ui-egui/src/panels/effect_controls.rs index d453e8e2..972b1004 100644 --- a/crates/ui-egui/src/panels/effect_controls.rs +++ b/crates/ui-egui/src/panels/effect_controls.rs @@ -99,7 +99,10 @@ pub fn show(app: &mut FilmcraftApp, ui: &mut egui::Ui, rect: Rect) { crate::dock::placeholder(ui, rect, &t, tl!("(no clip selected)")); return; }; - let Some(seq) = app.session.active_sequence().cloned() else { + // Keep the immutable project snapshot alive while UI commands mutate the session. + // Cloning a sequence here copies every clip and effect on every redraw. + let project = app.session.project.clone(); + let Some(seq) = app.session.state.active_sequence.and_then(|id| project.sequence(id)) else { crate::dock::placeholder(ui, rect, &t, tl!("(no sequences)")); return; }; diff --git a/crates/ui-egui/src/panels/misc.rs b/crates/ui-egui/src/panels/misc.rs index 63e494b8..01a2aee2 100644 --- a/crates/ui-egui/src/panels/misc.rs +++ b/crates/ui-egui/src/panels/misc.rs @@ -61,7 +61,10 @@ pub const MARKER_FILTER: [filmcraft_project::Label; 7] = { /// `markers.filter.