Merge pull request #749 from vangel76/fix-456-new-bin-name
#456: a new bin asks for its name
This commit is contained in:
commit
a270f5cf34
|
|
@ -483,6 +483,15 @@ pub fn invoke(app: &mut FilmcraftApp, ctx: &egui::Context, id: &str, mut params:
|
||||||
crate::panels::color_dialogs::open_sequence(app);
|
crate::panels::color_dialogs::open_sequence(app);
|
||||||
return Ok(json!({"dialog": "sequenceColor"}));
|
return Ok(json!({"dialog": "sequenceColor"}));
|
||||||
}
|
}
|
||||||
|
// New Bin from menus, shortcuts and the Project panel asks for the name (inline rename);
|
||||||
|
// agents pass `name` to name the bin directly
|
||||||
|
"file.newBin" if params.get("name").is_none() => {
|
||||||
|
let r = crate::panels::project::new_bin(app, ¶ms);
|
||||||
|
if let Err(e) = &r {
|
||||||
|
app.ui.status = e.clone();
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
// From menus/shortcuts (no params) these ask first; agents pass params to act directly.
|
// From menus/shortcuts (no params) these ask first; agents pass params to act directly.
|
||||||
"file.revert" if params.as_object().is_none_or(|m| m.is_empty()) && app.session.is_dirty() => {
|
"file.revert" if params.as_object().is_none_or(|m| m.is_empty()) && app.session.is_dirty() => {
|
||||||
if app.session.path.is_none() {
|
if app.session.path.is_none() {
|
||||||
|
|
|
||||||
|
|
@ -622,7 +622,7 @@ fn footer(app: &mut FilmcraftApp, ui: &mut egui::Ui, bar: Rect, v: &View, action
|
||||||
"find" => actions.push(("edit.find".into(), json!({}))),
|
"find" => actions.push(("edit.find".into(), json!({}))),
|
||||||
"file.newBin" => {
|
"file.newBin" => {
|
||||||
let parent = (v.bin != app.session.project.root.id).then_some(v.bin.0);
|
let parent = (v.bin != app.session.project.root.id).then_some(v.bin.0);
|
||||||
actions.push(("file.newBin".into(), json!({"name": "New Bin", "parent": parent})));
|
actions.push(("file.newBin".into(), json!({"parent": parent, "panel": pre})));
|
||||||
}
|
}
|
||||||
"project.delete" => match crate::panels::project_views::clear_params(&app.session.state.project_selection, app.ui.project_panel.selected_bin) {
|
"project.delete" => match crate::panels::project_views::clear_params(&app.session.state.project_selection, app.ui.project_panel.selected_bin) {
|
||||||
Some(p) => actions.push((id.into(), p)),
|
Some(p) => actions.push((id.into(), p)),
|
||||||
|
|
@ -719,7 +719,7 @@ pub fn panel_menu(app: &mut FilmcraftApp, ui: &mut egui::Ui) -> bool {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
if item(ui, "newBin", tl!("New Bin"), true, s_bin.as_deref()) {
|
if item(ui, "newBin", tl!("New Bin"), true, s_bin.as_deref()) {
|
||||||
let parent = (v.bin != app.session.project.root.id).then_some(v.bin.0);
|
let parent = (v.bin != app.session.project.root.id).then_some(v.bin.0);
|
||||||
actions.push(("file.newBin".into(), json!({"name": "New Bin", "parent": parent})));
|
actions.push(("file.newBin".into(), json!({"parent": parent})));
|
||||||
}
|
}
|
||||||
if item(ui, "newBinFromSelection", tl!("New Bin From Selection"), !app.session.state.project_selection.is_empty(), Some("Shift+B")) {
|
if item(ui, "newBinFromSelection", tl!("New Bin From Selection"), !app.session.state.project_selection.is_empty(), Some("Shift+B")) {
|
||||||
actions.push(("file.newBinFromSelection".into(), json!({})));
|
actions.push(("file.newBinFromSelection".into(), json!({})));
|
||||||
|
|
@ -958,6 +958,32 @@ fn start_rename(app: &mut FilmcraftApp, params: &Value) -> Result<Value, String>
|
||||||
Ok(json!({"item": item, "bin": bin}))
|
Ok(json!({"item": item, "bin": bin}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// New Bin from a menu, a shortcut or the panel's buttons (no `name`): make a "New Bin" in `parent`
|
||||||
|
/// (left out: the bin the Project panel shows; null: the project's root) and start renaming it, so
|
||||||
|
/// its name can be typed right away (#456). `panel` names the panel instance that edits the name.
|
||||||
|
/// Agents pass `name` to `file.newBin` to name the bin directly.
|
||||||
|
pub fn new_bin(app: &mut FilmcraftApp, params: &Value) -> Result<Value, String> {
|
||||||
|
let shown = view_of(app, shown_inst(app));
|
||||||
|
let parent = match params.get("parent") {
|
||||||
|
None => (shown.bin != app.session.project.root.id).then_some(shown.bin.0),
|
||||||
|
Some(Value::Null) => None,
|
||||||
|
Some(p) => Some(p.as_u64().ok_or("`parent` must be a bin id")?),
|
||||||
|
};
|
||||||
|
let r = app.session.execute("file.newBin", json!({"name": tl!("New Bin"), "parent": parent})).map_err(|e| e.to_string())?;
|
||||||
|
let bin = r.get("bin").and_then(Value::as_u64).ok_or("the new bin has no id")?;
|
||||||
|
let text = app.session.project.root.find_bin(BinId(bin)).map(|b| b.name.clone()).ok_or("no such bin")?;
|
||||||
|
// a bin made inside a collapsed bin of the list opens it, so the name field is visible
|
||||||
|
if let Some(p) = parent
|
||||||
|
&& !app.ui.expanded_bins.contains(&p)
|
||||||
|
{
|
||||||
|
app.ui.expanded_bins.push(p);
|
||||||
|
}
|
||||||
|
let panel = params.get("panel").and_then(Value::as_str).map_or(shown.prefix, str::to_string);
|
||||||
|
app.ui.project_panel.selected_bin = Some(bin);
|
||||||
|
app.ui.project_panel.rename = Some(Rename { item: None, bin: Some(bin), text, panel });
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
|
||||||
/// Commit the inline rename (Enter / focus lost).
|
/// Commit the inline rename (Enter / focus lost).
|
||||||
pub fn commit_rename(app: &mut FilmcraftApp) {
|
pub fn commit_rename(app: &mut FilmcraftApp) {
|
||||||
let Some(r) = app.ui.project_panel.rename.take() else { return };
|
let Some(r) = app.ui.project_panel.rename.take() else { return };
|
||||||
|
|
|
||||||
|
|
@ -311,7 +311,7 @@ fn bin_menu(app: &mut FilmcraftApp, ui: &mut egui::Ui, v: &View, bin: u64, actio
|
||||||
ui.close();
|
ui.close();
|
||||||
}
|
}
|
||||||
if ui.button(tl!("New Bin")).clicked() {
|
if ui.button(tl!("New Bin")).clicked() {
|
||||||
actions.push(("file.newBin".into(), json!({"name": "New Bin", "parent": bin})));
|
actions.push(("file.newBin".into(), json!({"parent": bin, "panel": v.prefix})));
|
||||||
ui.close();
|
ui.close();
|
||||||
}
|
}
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
@ -599,7 +599,7 @@ fn background_menu(app: &mut FilmcraftApp, ui: &mut egui::Ui, v: &View, bin: Opt
|
||||||
(tl!("Import…"), "file.import"),
|
(tl!("Import…"), "file.import"),
|
||||||
] {
|
] {
|
||||||
if ui.button(label).clicked() {
|
if ui.button(label).clicked() {
|
||||||
let p = if cmd == "file.newBin" { json!({"name": tl!("New Bin"), "parent": bin}) } else { json!({}) };
|
let p = if cmd == "file.newBin" { json!({"parent": bin, "panel": v.prefix}) } else { json!({}) };
|
||||||
actions.push((cmd.into(), p));
|
actions.push((cmd.into(), p));
|
||||||
ui.close();
|
ui.close();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -515,6 +515,26 @@ fn footer_buttons_are_wired() {
|
||||||
assert_eq!(d.app().session.prefs.project_panel.view.icon_sort.column, "Name");
|
assert_eq!(d.app().session.prefs.project_panel.view.icon_sort.column, "Name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_bin_asks_for_its_name() {
|
||||||
|
// #456: New Bin opens the name field of the new bin instead of leaving it "New Bin"
|
||||||
|
let mut d = project_driver();
|
||||||
|
d.exec("project.view.set", json!({"view": "list"}));
|
||||||
|
d.click("project.button.file.newBin");
|
||||||
|
d.frames(2);
|
||||||
|
let bin = d.app().ui.project_panel.rename.as_ref().and_then(|r| r.bin).expect("the new bin's name is being edited");
|
||||||
|
assert!(d.has("project.rename"), "the name field is shown");
|
||||||
|
d.key("Cmd+A");
|
||||||
|
d.ok("ui.type", json!({"text": "Interviews"}));
|
||||||
|
d.key("Enter");
|
||||||
|
let name = d.app().session.project.root.find_bin(filmcraft_project::BinId(bin)).unwrap().name.clone();
|
||||||
|
assert_eq!(name, "Interviews");
|
||||||
|
// with a name (agents) the bin is named directly and nothing is edited
|
||||||
|
let r = d.ok("ui.menu.invoke", json!({"id": "file.newBin", "params": {"name": "B-roll"}}));
|
||||||
|
assert!(r["bin"].as_u64().is_some(), "{r}");
|
||||||
|
assert!(d.app().ui.project_panel.rename.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------ Media Browser
|
// ------------------------------------------------------------------------------------ Media Browser
|
||||||
|
|
||||||
fn media_dir(tag: &str) -> std::path::PathBuf {
|
fn media_dir(tag: &str) -> std::path::PathBuf {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue