mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 13:08:07 -06:00
File dialogs: offer every movie type the importer reads (#1701)
Import and Set Proxy build their filters from the shared movie list, so they offer AVI; the web build's file picker gets the same list.
This commit is contained in:
@@ -1337,6 +1337,8 @@ fn file_dialog(app: &mut EffectcraftApp, id: &str, params: &Value) -> Option<Res
|
||||
OpenProject,
|
||||
Save(&'static str),
|
||||
Open(&'static [&'static str]),
|
||||
/// A movie, or a file with one of these extensions.
|
||||
OpenFootage(&'static [&'static str]),
|
||||
}
|
||||
let (key, ask) = match id {
|
||||
"file.import" | "file.importMultiple" => ("paths", Ask::Import),
|
||||
@@ -1366,7 +1368,7 @@ fn file_dialog(app: &mut EffectcraftApp, id: &str, params: &Value) -> Option<Res
|
||||
"keys.rpfCameraImport" => ("path", Ask::Open(&["json", "csv", "txt"])),
|
||||
"essential.exportTemplate" => ("path", Ask::Save("Template.ectemplate")),
|
||||
"essential.importTemplate" => ("path", Ask::Open(&["ectemplate"])),
|
||||
"file.setProxy" => ("path", Ask::Open(&["mp4", "mov", "m4v", "mkv", "webm", "mxf", "png", "jpg", "jpeg", "gif", "webp", "tif", "tiff", "bmp", "exr"])),
|
||||
"file.setProxy" => ("path", Ask::OpenFootage(&["png", "jpg", "jpeg", "gif", "webp", "tif", "tiff", "bmp", "exr"])),
|
||||
_ => return None,
|
||||
};
|
||||
if params.get(key).is_some()
|
||||
@@ -1377,19 +1379,22 @@ fn file_dialog(app: &mut EffectcraftApp, id: &str, params: &Value) -> Option<Res
|
||||
{
|
||||
return None;
|
||||
}
|
||||
// Importable files besides movies.
|
||||
const MEDIA: &[&str] = &[
|
||||
"mp4", "mov", "m4v", "mkv", "webm", "mxf", "png", "jpg", "jpeg", "gif", "webp", "tif", "tiff", "bmp", "exr", "dpx", "cin", "wav", "aif", "aiff", "mp3",
|
||||
"flac", "ogg", "opus", "svg", "pdf", "ai", "eps", "psd", "psb", "tga", "hdr", "gltf", "glb", "obj", "stl", "fbx", "json", "csv", "tsv",
|
||||
"png", "jpg", "jpeg", "gif", "webp", "tif", "tiff", "bmp", "exr", "dpx", "cin", "wav", "aif", "aiff", "mp3", "flac", "ogg", "opus", "svg", "pdf", "ai",
|
||||
"eps", "psd", "psb", "tga", "hdr", "gltf", "glb", "obj", "stl", "fbx", "json", "csv", "tsv",
|
||||
];
|
||||
let footage = |more: &[&'static str]| effectcraft_project::VIDEO_EXTENSIONS.iter().chain(more).copied().collect::<Vec<_>>();
|
||||
// A host whose modal dialogs would run a nested event loop inside this frame (macOS: a
|
||||
// drag over the window then re-entered winit's event handler and aborted, #511) shows the
|
||||
// dialog without blocking; the command continues when the answer arrives.
|
||||
if let Some(spawn) = app.hooks.file_dialog_async.as_ref() {
|
||||
let request = match ask {
|
||||
Ask::Folder => crate::FileDialog::Folder,
|
||||
Ask::Import => crate::FileDialog::Open { exts: MEDIA.iter().map(|e| e.to_string()).collect(), many: key == "paths" },
|
||||
Ask::Import => crate::FileDialog::Open { exts: footage(MEDIA).iter().map(|e| e.to_string()).collect(), many: key == "paths" },
|
||||
Ask::OpenProject => crate::FileDialog::OpenProject,
|
||||
Ask::Open(exts) => crate::FileDialog::Open { exts: exts.iter().map(|e| e.to_string()).collect(), many: false },
|
||||
Ask::OpenFootage(more) => crate::FileDialog::Open { exts: footage(more).iter().map(|e| e.to_string()).collect(), many: false },
|
||||
Ask::Save(default) => crate::FileDialog::save(default),
|
||||
};
|
||||
let tx = app.dialog_answers.0.clone();
|
||||
@@ -1409,7 +1414,7 @@ fn file_dialog(app: &mut EffectcraftApp, id: &str, params: &Value) -> Option<Res
|
||||
}
|
||||
Ask::Import => {
|
||||
let Some(f) = app.hooks.pick_files.as_ref() else { return Some(Err("no file dialog available (pass `paths`)".into())) };
|
||||
picked_value(key, f(MEDIA))
|
||||
picked_value(key, f(&footage(MEDIA)))
|
||||
}
|
||||
Ask::OpenProject => {
|
||||
let Some(f) = app.hooks.pick_open_project.as_ref() else { return Some(Err("no file dialog available (pass `path`)".into())) };
|
||||
@@ -1419,6 +1424,10 @@ fn file_dialog(app: &mut EffectcraftApp, id: &str, params: &Value) -> Option<Res
|
||||
let Some(f) = app.hooks.pick_files.as_ref() else { return Some(Err("no file dialog available (pass `path`)".into())) };
|
||||
f(exts).first().map(|s| json!(s))
|
||||
}
|
||||
Ask::OpenFootage(more) => {
|
||||
let Some(f) = app.hooks.pick_files.as_ref() else { return Some(Err("no file dialog available (pass `path`)".into())) };
|
||||
f(&footage(more)).first().map(|s| json!(s))
|
||||
}
|
||||
Ask::Save(default) => {
|
||||
let Some(picked) = app.hooks.save_dialog(default) else { return Some(Err("no file dialog available (pass `path`)".into())) };
|
||||
picked.map(|s| json!(s))
|
||||
|
||||
@@ -205,10 +205,10 @@ fn relink_restores_decoded_pixels_and_invalidates_viewer_content() {
|
||||
std::fs::remove_dir_all(dir).unwrap();
|
||||
}
|
||||
|
||||
/// #767: File ▸ Import ▸ File… offers MXF footage (OP1a / OP-Atom from broadcast cameras and
|
||||
/// Avid), which the Media Browser lists and the importer reads.
|
||||
/// #767, #1701: File ▸ Import ▸ File… and the proxy dialog offer every movie type the importer
|
||||
/// reads (MXF from broadcast cameras and Avid, AVI, …), the list the Media Browser goes by too.
|
||||
#[test]
|
||||
fn import_dialog_offers_mxf() {
|
||||
fn import_and_proxy_dialogs_offer_every_movie_type() {
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
@@ -219,11 +219,15 @@ fn import_dialog_offers_mxf() {
|
||||
*seen.borrow_mut() = exts.iter().map(|e| e.to_string()).collect();
|
||||
Vec::new()
|
||||
}));
|
||||
let result = effectcraft_ui_egui::menus::invoke(&mut app, &egui::Context::default(), "file.import", json!({})).unwrap();
|
||||
assert!(result.is_null(), "cancelled: nothing imported");
|
||||
let offered = offered.borrow();
|
||||
assert!(offered.iter().any(|e| e == "mxf"), "offered {offered:?}");
|
||||
assert!(offered.iter().any(|e| e == "mov"));
|
||||
for (command, still) in [("file.import", "psd"), ("file.setProxy", "png")] {
|
||||
let result = effectcraft_ui_egui::menus::invoke(&mut app, &egui::Context::default(), command, json!({})).unwrap();
|
||||
assert!(result.is_null(), "{command} cancelled: nothing done");
|
||||
let offered = offered.borrow();
|
||||
for ext in effectcraft_project::VIDEO_EXTENSIONS.iter().chain([&still]) {
|
||||
assert!(offered.iter().any(|e| e == ext), "{command} offers {ext}: {offered:?}");
|
||||
}
|
||||
assert!(offered.iter().any(|e| e == "avi"), "{command}: {offered:?}");
|
||||
}
|
||||
}
|
||||
|
||||
/// #1059: opening the demo from the start screen and immediately pressing Spacebar previews
|
||||
|
||||
Reference in New Issue
Block a user