diff --git a/desktop/wrapper/src/intercept_frontend_message.rs b/desktop/wrapper/src/intercept_frontend_message.rs index f9c2bd1df1..4d3b980a63 100644 --- a/desktop/wrapper/src/intercept_frontend_message.rs +++ b/desktop/wrapper/src/intercept_frontend_message.rs @@ -1,7 +1,6 @@ #[cfg(target_os = "macos")] use graphite_editor::messages::layout::utility_types::layout_widget::LayoutTarget; use graphite_editor::messages::prelude::FrontendMessage; -use std::path::PathBuf; use super::DesktopWrapperMessageDispatcher; use super::messages::{DesktopFrontendMessage, Document, FileFilter, OpenFileDialogContext, SaveFileDialogContext}; @@ -25,7 +24,13 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD context: OpenFileDialogContext::Import, }); } - FrontendMessage::TriggerSaveDocument { document_id, name, path, content } => { + FrontendMessage::TriggerSaveDocument { + document_id, + name, + path, + folder, + content, + } => { let content = content.into_vec(); if let Some(path) = path { dispatcher.respond(DesktopFrontendMessage::WriteFile { path, content }); @@ -33,7 +38,7 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD dispatcher.respond(DesktopFrontendMessage::SaveFileDialog { title: "Save Document".to_string(), default_filename: name, - default_folder: path.and_then(|p| p.parent().map(PathBuf::from)), + default_folder: folder, filters: vec![FileFilter { name: "Graphite".to_string(), extensions: vec!["graphite".to_string()], @@ -42,12 +47,12 @@ pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageD }); } } - FrontendMessage::TriggerSaveFile { name, content } => { + FrontendMessage::TriggerSaveFile { name, folder, content } => { let content = content.into_vec(); dispatcher.respond(DesktopFrontendMessage::SaveFileDialog { title: "Save File".to_string(), default_filename: name, - default_folder: None, + default_folder: folder, filters: Vec::new(), context: SaveFileDialogContext::File { content }, }); diff --git a/desktop/wrapper/src/messages.rs b/desktop/wrapper/src/messages.rs index 087c1fde8a..7b06ba260c 100644 --- a/desktop/wrapper/src/messages.rs +++ b/desktop/wrapper/src/messages.rs @@ -5,10 +5,10 @@ pub(crate) use graphite_editor::messages::prelude::Message as EditorMessage; pub use graphite_editor::messages::input_mapper::utility_types::input_keyboard::{Key, ModifierKeys}; pub use graphite_editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseState as MouseState, EditorPosition as Position, MouseKeys}; -pub use graphite_editor::messages::prelude::InputPreprocessorMessage as InputMessage; - pub use graphite_editor::messages::prelude::DocumentId; +pub use graphite_editor::messages::prelude::InputPreprocessorMessage as InputMessage; pub use graphite_editor::messages::prelude::PreferencesMessageHandler as Preferences; + pub enum DesktopFrontendMessage { ToWeb(Vec), OpenLaunchDocuments, diff --git a/editor/src/messages/frontend/frontend_message.rs b/editor/src/messages/frontend/frontend_message.rs index 743d6ed2c2..15aa9cb3b4 100644 --- a/editor/src/messages/frontend/frontend_message.rs +++ b/editor/src/messages/frontend/frontend_message.rs @@ -89,10 +89,12 @@ pub enum FrontendMessage { document_id: DocumentId, name: String, path: Option, + folder: Option, content: serde_bytes::ByteBuf, }, TriggerSaveFile { name: String, + folder: Option, content: serde_bytes::ByteBuf, }, TriggerExportImage { diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 8cdb18e959..8e8d5808e1 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -835,26 +835,28 @@ impl MessageHandler> for DocumentMes }); } DocumentMessage::SaveDocument | DocumentMessage::SaveDocumentAs => { - if let DocumentMessage::SaveDocumentAs = message { - self.path = None; + responses.add(PortfolioMessage::AutoSaveActiveDocument); + + let path = if let DocumentMessage::SaveDocumentAs = message { None } else { self.path.clone() }; + if path.is_some() { + responses.add(DocumentMessage::MarkAsSaved); } - self.set_save_state(true); - responses.add(PortfolioMessage::AutoSaveActiveDocument); - // Update the save status of the just saved document - responses.add(PortfolioMessage::UpdateOpenDocumentsList); + let folder = self.path.as_ref().and_then(|path| path.parent()).map(|parent| parent.to_path_buf()); responses.add(FrontendMessage::TriggerSaveDocument { document_id, name: format!("{}.{}", self.name.clone(), FILE_EXTENSION), - path: self.path.clone(), + path, + folder, content: self.serialize_document().into_bytes().into(), - }) + }); } DocumentMessage::SavedDocument { path } => { self.path = path; responses.add(PortfolioMessage::AutoSaveActiveDocument); + responses.add(DocumentMessage::MarkAsSaved); // Update the name to match the file stem let document_name_from_path = self.path.as_ref().and_then(|path| { diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index dbc9c2d182..69b91f0d95 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -485,9 +485,10 @@ impl MessageHandler> for Portfolio let name = path.file_stem().map(|n| n.to_string_lossy().to_string()); match Self::read_file(&path, content) { FileContent::Document(content) => { + let document_path = if path.is_absolute() { Some(path) } else { None }; responses.add(PortfolioMessage::OpenDocumentFile { document_name: name, - document_path: Some(path), + document_path, document_serialized_content: content, }); } diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index aa63da4076..fc7d18d091 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -332,7 +332,7 @@ impl NodeGraphExecutor { if let Some(export_config) = execution_context.export_config { // Special handling for exporting the artwork - self.process_export(node_graph_output, export_config, responses)?; + self.process_export(node_graph_output, export_config, document, responses)?; } else { self.process_node_graph_output(node_graph_output, responses)?; } @@ -435,7 +435,7 @@ impl NodeGraphExecutor { Ok(()) } - fn process_export(&self, node_graph_output: TaggedValue, export_config: ExportConfig, responses: &mut VecDeque) -> Result<(), String> { + fn process_export(&self, node_graph_output: TaggedValue, export_config: ExportConfig, document: &DocumentMessageHandler, responses: &mut VecDeque) -> Result<(), String> { let ExportConfig { file_type, name, @@ -457,6 +457,7 @@ impl NodeGraphExecutor { _ => name, }; let name = format!("{base_name}.{file_extension}"); + let folder = document.path.as_ref().and_then(|path| path.parent()).map(|parent| parent.to_path_buf()); match node_graph_output { TaggedValue::RenderOutput(RenderOutput { @@ -466,6 +467,7 @@ impl NodeGraphExecutor { if file_type == FileType::Svg { responses.add(FrontendMessage::TriggerSaveFile { name, + folder, content: svg.into_bytes().into(), }); } else { @@ -513,7 +515,11 @@ impl NodeGraphExecutor { } } - responses.add(FrontendMessage::TriggerSaveFile { name, content: encoded.into() }); + responses.add(FrontendMessage::TriggerSaveFile { + name, + folder, + content: encoded.into(), + }); } _ => { return Err(format!("Incorrect render type for exporting to an SVG ({file_type:?}, {node_graph_output})"));