Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions contributors/people.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,7 @@ sync_github_name = false

[people.webdevtodayjason]
display_name = "Jason Brashear"

[people.dotCooCoo]
real_name = "Robert Lee"
sync_github_name = true
4 changes: 4 additions & 0 deletions crates/ui-egui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,10 @@ impl FilmcraftApp {
}
"file.open" => self.pick(FileDialog::OpenProject, |app, paths| {
let Some(path) = paths.into_iter().next() else { return Ok(Value::Null) };
// unsaved changes: Save / Don't Save / Cancel first
if panels::clip_dialogs::intercept_open(app, &path) {
return Ok(json!({"dialog": "openProject"}));
}
app.session.execute("file.open", json!({"path": path})).map_err(|e| e.to_string())
}),
"graphics.newFromFile" => {
Expand Down
4 changes: 4 additions & 0 deletions crates/ui-egui/src/menus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,10 @@ pub fn invoke(app: &mut FilmcraftApp, ctx: &egui::Context, id: &str, mut params:
// File ▸ Open Recent
if let Some(i) = id.strip_prefix("file.openRecent.") {
let path = i.parse::<usize>().ok().and_then(|i| app.session.prefs.general.recent_projects.get(i).cloned()).ok_or("no such recent project")?;
// unsaved changes: Save / Don't Save / Cancel first
if crate::panels::clip_dialogs::intercept_open(app, &path) {
return Ok(json!({"dialog": "openProject"}));
}
return invoke(app, ctx, "file.open", json!({"path": path}));
}
if id == "file.clearRecent" {
Expand Down
32 changes: 28 additions & 4 deletions crates/ui-egui/src/panels/clip_dialogs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Edit / Clip / File menu dialogs (M3.10): Paste Attributes, Remove Attributes, Offline File,
//! Make Subclip, Edit Subclip, Modify ▸ Audio Channels, Modify ▸ Timecode, Frame Hold Options,
//! Field Options, Clip Speed / Duration, Nest… (Nested Sequence Name), and the Close Project and
//! Quit "save changes?" prompts.
//! Field Options, Clip Speed / Duration, Nest… (Nested Sequence Name), and the Close Project,
//! Open Project and Quit "save changes?" prompts.
//!
//! The open dialog lives in `UiState::clip_dialog` (serde): the engine command it runs and the
//! parameters being edited — the same JSON the command takes — so agents can open a dialog from
Expand All @@ -27,6 +27,8 @@
//! - Clip Speed / Duration `speedDuration.*`: `speed`, `reverse`, `ripple`,
//! `interpolation.<frameSampling|frameBlending|opticalFlow>`;
//! - Close Project `closeProject.save`, `closeProject.dontSave`, `closeProject.cancel`;
//! - Open Project (asked once the project to open is chosen, see [`intercept_open`])
//! `openProject.save`, `openProject.dontSave`, `openProject.cancel`;
//! - Quit (asked when the window is closed with unsaved changes, see [`intercept_quit`])
//! `quit.save`, `quit.dontSave`, `quit.cancel`.

Expand Down Expand Up @@ -59,6 +61,7 @@ fn meta(command: &str) -> Option<(&'static str, &'static str)> {
"clip.fieldOptions" => (tl!("Field Options"), "fieldOptions"),
"clip.speedDuration" => (tl!("Clip Speed / Duration"), "speedDuration"),
"file.closeProject" => (tl!("Save Project"), "closeProject"),
"file.open" => (tl!("Save Project"), "openProject"),
"app.quit" => (tl!("Save Project"), "quit"),
_ => return None,
})
Expand Down Expand Up @@ -93,7 +96,8 @@ pub fn route(app: &mut FilmcraftApp, id: &str, params: &Value) -> Option<Result<
if id == "file.saveAll" && app.session.path.is_none() {
return Some(app.file_dialog("file.save", params));
}
if (id == "file.closeProject" && !app.session.is_dirty()) || id == "app.quit" {
// Open Project asks once the project to open is chosen (`intercept_open`)
if (id == "file.closeProject" && !app.session.is_dirty()) || id == "app.quit" || id == "file.open" {
return None;
}
meta(id)?;
Expand All @@ -119,6 +123,17 @@ pub fn intercept_quit(app: &mut FilmcraftApp) -> bool {
true
}

/// File ▸ Open Project once the project at `path` is chosen, File ▸ Open Recent and Home's Recent
/// list: with unsaved changes Save / Don't Save / Cancel is asked first, as Close Project asks, and
/// `path` opens after Save or Don't Save. Returns whether it asked.
pub fn intercept_open(app: &mut FilmcraftApp, path: &str) -> bool {
if !app.session.is_dirty() {
return false;
}
app.ui.clip_dialog = Some(ClipDialogDraft { command: "file.open".into(), params: json!({"path": path}), info: Value::Null, error: String::new() });
true
}

/// Initial parameters (and display info) of a command's dialog.
fn defaults(app: &FilmcraftApp, id: &str) -> (Value, Value) {
let s = &app.session;
Expand Down Expand Up @@ -539,7 +554,7 @@ pub fn show(app: &mut FilmcraftApp, ctx: &egui::Context) {
}
}
}
"file.closeProject" | "app.quit" => {
"file.closeProject" | "file.open" | "app.quit" => {
ui.label(tlf!("Save changes to “{project_name}” before closing?", project_name));
ui.add_space(8.0);
ui.horizontal(|ui| {
Expand Down Expand Up @@ -622,6 +637,15 @@ pub fn show(app: &mut FilmcraftApp, ctx: &egui::Context) {
return;
}
}
// Open Project opens the chosen project; when that fails, this project stays open with
// its unsaved changes
if d.command == "file.open" {
if let Err(e) = app.session.execute("file.open", d.params.clone()) {
app.ui.status = e.to_string();
}
app.ui.clip_dialog = None;
return;
}
// Quit ▸ Don't Save discards the changes: closing the project also clears their recovery
// snapshot, so the next launch doesn't offer them back
let close = d.command != "app.quit" || app.session.is_dirty();
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
Expand Down
3 changes: 2 additions & 1 deletion crates/ui-egui/src/panels/import_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ fn recent(app: &mut FilmcraftApp, ui: &mut egui::Ui, rect: Rect, y: f32) -> f32
}
if let Some(path) = open {
let ctx = ui.ctx().clone();
if crate::menus::invoke(app, &ctx, "file.open", json!({"path": path})).is_ok() {
// unsaved changes: Save / Don't Save / Cancel first, asked over the project they were made in
if crate::panels::clip_dialogs::intercept_open(app, &path) || crate::menus::invoke(app, &ctx, "file.open", json!({"path": path})).is_ok() {
app.ui.mode = crate::state::Mode::Edit;
}
}
Expand Down
Loading
Loading