project file: format dialog hands to the SYSTEM dialog (extension-limited)
- 导出工程文件: the in-app dialog only picks the format (OTIO / OVE / FCPXML); OK asks the system save dialog with the suggested file name carrying the format's extension, then exports - 打开项目: the system open dialog restricts the choosable files to .ove/.ovexml/.otio/.fcpxml (PathPromptOptions.allowed_extensions plumbed through gpui; Linux portal glob filter)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
name: CD
|
||||
kiname: CD
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
+38
-29
@@ -424,6 +424,8 @@ pub struct OakApp<E: AppEngine> {
|
||||
plugin_progress_rx: Mutex<mpsc::Receiver<crate::oakui::ofx::PluginProgressEvent>>,
|
||||
/// The library row pending an export save dialog (manager 导出).
|
||||
pending_export: Option<String>,
|
||||
/// The suggested file stem for the export-project system save dialog.
|
||||
export_suggested_name: String,
|
||||
/// The panel that most recently took focus (the target of
|
||||
/// [`Route::FocusedPanel`](crate::actions::Route::FocusedPanel)
|
||||
/// commands; `None` before any panel is focused).
|
||||
@@ -843,6 +845,7 @@ impl<E: AppEngine> OakApp<E> {
|
||||
export: None,
|
||||
pending_drop: None,
|
||||
pending_export: None,
|
||||
export_suggested_name: String::new(),
|
||||
plugin_progress_open: false,
|
||||
plugin_progress_rx: Mutex::new(plugin_progress_rx),
|
||||
focused_panel: None,
|
||||
@@ -2018,6 +2021,17 @@ impl<E: AppEngine> OakApp<E> {
|
||||
directories: false,
|
||||
multiple: action == FileAction::ImportFootage,
|
||||
prompt: Some(prompt.into()),
|
||||
allowed_extensions: if action == FileAction::Open {
|
||||
// Project files only: OVE / OTIO / FCPXML.
|
||||
vec![
|
||||
"ove".to_string(),
|
||||
"ovexml".to_string(),
|
||||
"otio".to_string(),
|
||||
"fcpxml".to_string(),
|
||||
]
|
||||
} else {
|
||||
Vec::new()
|
||||
},
|
||||
});
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Ok(Ok(Some(paths))) = receiver.await {
|
||||
@@ -2615,8 +2629,9 @@ impl<E: AppEngine> OakApp<E> {
|
||||
}
|
||||
|
||||
/// Opens the 导出工程文件 dialog: choose the project file format
|
||||
/// (OTIO / OVE / FCPXML) and the output path; the OK button runs the
|
||||
/// engine's export_project_path with the picked extension.
|
||||
/// (OTIO / OVE / FCPXML); the OK button then asks the SYSTEM save
|
||||
/// dialog for the output path (the suggested file name carries the
|
||||
/// chosen extension).
|
||||
fn open_export_project_dfd(&mut self, cx: &mut Context<Self>) {
|
||||
if !matches!(self.modal, ModalState::None) {
|
||||
return;
|
||||
@@ -2633,15 +2648,11 @@ impl<E: AppEngine> OakApp<E> {
|
||||
.map(|name| name.to_string_lossy().into_owned())
|
||||
})
|
||||
.unwrap_or_else(|| "untitled".to_string());
|
||||
self.export_suggested_name = suggested;
|
||||
self.spawn_modal(cx, move |window, app| {
|
||||
let content = app.new(|cx| {
|
||||
crate::dialogs::ExportProjectDialogContent::new(window, cx)
|
||||
});
|
||||
// Default selection is OTIO: pre-fill the pathway with the
|
||||
// correct extension, the OK handler applies the chosen one.
|
||||
content.update(app, |content, cx| {
|
||||
content.set_path(format!("{suggested}.otio"), cx)
|
||||
});
|
||||
let modal = app.new(|cx| {
|
||||
Modal::new(
|
||||
modal_ids::EXPORT_PROJECT_DFD,
|
||||
@@ -3128,35 +3139,33 @@ impl<E: AppEngine> OakApp<E> {
|
||||
modal_ids::EXPORT_PROJECT_DFD => {
|
||||
if let ModalState::ExportProjectDfd { content, .. } = &self.modal {
|
||||
if *button == 0 {
|
||||
// OK: export with the chosen format — the path
|
||||
// gets the format's extension appended.
|
||||
// OK: keep the chosen format; the SYSTEM save
|
||||
// dialog then picks the output path (the
|
||||
// suggested name carries the format's
|
||||
// extension).
|
||||
let format = content.read(cx).format(cx);
|
||||
let ext = match format {
|
||||
crate::dialogs::PROJECT_FORMAT_OVE => "ove",
|
||||
crate::dialogs::PROJECT_FORMAT_FCPXML => "fcpxml",
|
||||
_ => "otio",
|
||||
};
|
||||
let path = content.read(cx).path(cx).to_string();
|
||||
let path = if path.to_ascii_lowercase().ends_with(".otio")
|
||||
|| path.to_ascii_lowercase().ends_with(".ove")
|
||||
|| path.to_ascii_lowercase().ends_with(".fcpxml")
|
||||
{
|
||||
// Stem swap: the entered name already has
|
||||
// an extension — replace it.
|
||||
let stem = path
|
||||
.split('.')
|
||||
.next()
|
||||
.unwrap_or(&path)
|
||||
.to_string();
|
||||
format!("{stem}.{ext}")
|
||||
} else {
|
||||
format!("{path}.{ext}")
|
||||
};
|
||||
let engine = self.engine.clone();
|
||||
engine.update(cx, |engine, cx| {
|
||||
engine.export_project_path(PathBuf::from(path), cx)
|
||||
});
|
||||
let suggested = self.export_suggested_name.clone();
|
||||
let receiver = cx.prompt_for_new_path(
|
||||
std::path::Path::new("."),
|
||||
Some(&format!("{suggested}.{ext}")),
|
||||
);
|
||||
self.close_modal(cx);
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Ok(Ok(Some(path))) = receiver.await {
|
||||
this.update(cx, |this, cx| {
|
||||
let engine = this.engine.clone();
|
||||
engine.update(cx, |engine, cx| {
|
||||
engine.export_project_path(path, cx)
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
} else {
|
||||
self.close_modal(cx);
|
||||
}
|
||||
|
||||
@@ -585,6 +585,7 @@ impl PreferencesContent {
|
||||
directories: false,
|
||||
multiple: false,
|
||||
prompt: Some(i18n::tr("preferences.color.browse").into()),
|
||||
allowed_extensions: Vec::new(),
|
||||
});
|
||||
cx.spawn(async move |this, cx| {
|
||||
let Ok(Ok(Some(paths))) = receiver.await else {
|
||||
@@ -623,6 +624,7 @@ impl PreferencesContent {
|
||||
directories: true,
|
||||
multiple: false,
|
||||
prompt: Some(i18n::tr("preferences.cache.browse").into()),
|
||||
allowed_extensions: Vec::new(),
|
||||
});
|
||||
cx.spawn(async move |this, cx| {
|
||||
let Ok(Ok(Some(paths))) = receiver.await else {
|
||||
@@ -2095,6 +2097,7 @@ impl<E: crate::oakui::engine::AppEngine> Render for ProjectPropertiesContent<E>
|
||||
directories: false,
|
||||
multiple: false,
|
||||
prompt: None,
|
||||
allowed_extensions: Vec::new(),
|
||||
});
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Ok(Ok(Some(paths))) = receiver.await {
|
||||
@@ -2569,6 +2572,7 @@ impl KeyboardTabContent {
|
||||
directories: false,
|
||||
multiple: false,
|
||||
prompt: Some(i18n::tr("preferences.keyboard.import").into()),
|
||||
allowed_extensions: Vec::new(),
|
||||
});
|
||||
cx.spawn(async move |this, cx| {
|
||||
let Ok(Ok(Some(paths))) = receiver.await else {
|
||||
|
||||
@@ -142,6 +142,7 @@ impl<E: AppEngine> ProjectExplorerPanel<E> {
|
||||
directories: false,
|
||||
multiple: false,
|
||||
prompt: Some(crate::i18n::tr("project.context.replace_footage").into()),
|
||||
allowed_extensions: Vec::new(),
|
||||
});
|
||||
cx.spawn(async move |this, cx| {
|
||||
if let Ok(Ok(Some(paths))) = receiver.await {
|
||||
|
||||
+1
-1
Submodule gpui updated: 209c593da6...a934be5bc6
Reference in New Issue
Block a user