diff --git a/desktop/src/app.rs b/desktop/src/app.rs index da055ff5b5..0c08ce9564 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -10,7 +10,6 @@ use graph_craft::wasm_application_io::WasmApplicationIo; use graphene_std::Color; use graphene_std::raster::Image; use graphite_editor::application::Editor; -use graphite_editor::consts::DEFAULT_DOCUMENT_NAME; use graphite_editor::messages::prelude::*; use std::fs; use std::sync::Arc; @@ -79,7 +78,8 @@ impl WinitApp { String::new() }); let message = PortfolioMessage::OpenDocumentFile { - document_name: path.file_stem().and_then(|s| s.to_str()).unwrap_or("unknown").to_string(), + document_name: None, + document_path: Some(path), document_serialized_content: content, }; let _ = event_loop_proxy.send_event(CustomEvent::DispatchMessage(message.into())); @@ -294,7 +294,8 @@ impl ApplicationHandler for WinitApp { let Some(content) = load_string(&path) else { return }; let message = PortfolioMessage::OpenDocumentFile { - document_name: name.unwrap_or(DEFAULT_DOCUMENT_NAME.to_string()), + document_name: None, + document_path: Some(path), document_serialized_content: content, }; self.dispatch_message(message.into()); diff --git a/editor/src/consts.rs b/editor/src/consts.rs index 44a5b1d210..0fc75466f7 100644 --- a/editor/src/consts.rs +++ b/editor/src/consts.rs @@ -150,8 +150,8 @@ pub const COLOR_OVERLAY_WHITE: &str = "#ffffff"; pub const COLOR_OVERLAY_BLACK_75: &str = "#000000bf"; // DOCUMENT +pub const FILE_EXTENSION: &str = "graphite"; pub const DEFAULT_DOCUMENT_NAME: &str = "Untitled Document"; -pub const FILE_SAVE_SUFFIX: &str = ".graphite"; pub const MAX_UNDO_HISTORY_LEN: usize = 100; // TODO: Add this to user preferences pub const AUTO_SAVE_TIMEOUT_SECONDS: u64 = 1; diff --git a/editor/src/dispatcher.rs b/editor/src/dispatcher.rs index 44bea9ff4c..79bda1b3f5 100644 --- a/editor/src/dispatcher.rs +++ b/editor/src/dispatcher.rs @@ -497,7 +497,8 @@ mod test { ); let responses = editor.editor.handle_message(PortfolioMessage::OpenDocumentFile { - document_name: document_name.into(), + document_name: Some(document_name.to_string()), + document_path: None, document_serialized_content, }); diff --git a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs index 684a240fe6..4753279c8b 100644 --- a/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs +++ b/editor/src/messages/dialog/export_dialog/export_dialog_message_handler.rs @@ -44,7 +44,7 @@ impl MessageHandler> for Exp ExportDialogMessage::ExportBounds { bounds } => self.bounds = bounds, ExportDialogMessage::Submit => responses.add_front(PortfolioMessage::SubmitDocumentExport { - file_name: portfolio.active_document().map(|document| document.name.clone()).unwrap_or_default(), + name: portfolio.active_document().map(|document| document.name.clone()).unwrap_or_default(), file_type: self.file_type, scale_factor: self.scale_factor, bounds: self.bounds, diff --git a/editor/src/messages/input_mapper/input_mappings.rs b/editor/src/messages/input_mapper/input_mappings.rs index 71f68acc9b..211104bc21 100644 --- a/editor/src/messages/input_mapper/input_mappings.rs +++ b/editor/src/messages/input_mapper/input_mappings.rs @@ -340,6 +340,7 @@ pub fn input_mappings() -> Mapping { entry!(KeyDown(KeyA); modifiers=[Accel, Shift], canonical, action_dispatch=DocumentMessage::DeselectAllLayers), entry!(KeyDown(KeyA); modifiers=[Alt], action_dispatch=DocumentMessage::DeselectAllLayers), entry!(KeyDown(KeyS); modifiers=[Accel], action_dispatch=DocumentMessage::SaveDocument), + entry!(KeyDown(KeyS); modifiers=[Accel, Shift], action_dispatch=DocumentMessage::SaveDocumentAs), entry!(KeyDown(KeyD); modifiers=[Accel], canonical, action_dispatch=DocumentMessage::DuplicateSelectedLayers), entry!(KeyDown(KeyJ); modifiers=[Accel], action_dispatch=DocumentMessage::DuplicateSelectedLayers), entry!(KeyDown(KeyG); modifiers=[Accel], action_dispatch=DocumentMessage::GroupSelectedLayers { group_folder_type: GroupFolderType::Layer }), diff --git a/editor/src/messages/portfolio/document/document_message.rs b/editor/src/messages/portfolio/document/document_message.rs index 17e131f5f3..88c2159c6c 100644 --- a/editor/src/messages/portfolio/document/document_message.rs +++ b/editor/src/messages/portfolio/document/document_message.rs @@ -118,6 +118,7 @@ pub enum DocumentMessage { RenderRulers, RenderScrollbars, SaveDocument, + SaveDocumentAs, SavedDocument { path: Option, }, diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 91135299ad..0fa4d70386 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -6,7 +6,7 @@ use super::utility_types::misc::{GroupFolderType, SNAP_FUNCTIONS_FOR_BOUNDING_BO use super::utility_types::network_interface::{self, NodeNetworkInterface, TransactionStatus}; use super::utility_types::nodes::{CollapsedLayers, SelectedNodes}; use crate::application::{GRAPHITE_GIT_COMMIT_HASH, generate_uuid}; -use crate::consts::{ASYMPTOTIC_EFFECT, COLOR_OVERLAY_GRAY, DEFAULT_DOCUMENT_NAME, FILE_SAVE_SUFFIX, SCALE_EFFECT, SCROLLBAR_SPACING, VIEWPORT_ROTATE_SNAP_INTERVAL}; +use crate::consts::{ASYMPTOTIC_EFFECT, COLOR_OVERLAY_GRAY, DEFAULT_DOCUMENT_NAME, FILE_EXTENSION, SCALE_EFFECT, SCROLLBAR_SPACING, VIEWPORT_ROTATE_SNAP_INTERVAL}; use crate::messages::input_mapper::utility_types::macros::action_keys; use crate::messages::layout::utility_types::widget_prelude::*; use crate::messages::portfolio::document::data_panel::{DataPanelMessageContext, DataPanelMessageHandler}; @@ -85,8 +85,6 @@ pub struct DocumentMessageHandler { /// List of the [`LayerNodeIdentifier`]s that are currently collapsed by the user in the Layers panel. /// Collapsed means that the expansion arrow isn't set to show the children of these layers. pub collapsed: CollapsedLayers, - /// The name of the document, which is displayed in the tab and title bar of the editor. - pub name: String, /// The full Git commit hash of the Graphite repository that was used to build the editor. /// We save this to provide a hint about which version of the editor was used to create the document. pub commit_hash: String, @@ -113,6 +111,12 @@ pub struct DocumentMessageHandler { // Fields omitted from the saved document format // ============================================= // + /// The name of the document, which is displayed in the tab and title bar of the editor. + #[serde(skip)] + pub name: String, + /// The path of the to the document file. + #[serde(skip)] + pub(crate) path: Option, /// Path to network currently viewed in the node graph overlay. This will eventually be stored in each panel, so that multiple panels can refer to different networks #[serde(skip)] breadcrumb_network_path: Vec, @@ -125,9 +129,6 @@ pub struct DocumentMessageHandler { /// Stack of document network snapshots for future history states. #[serde(skip)] document_redo_history: VecDeque, - /// The path of the to the document file. - #[serde(skip)] - path: Option, /// Hash of the document snapshot that was most recently saved to disk by the user. #[serde(skip)] saved_hash: Option, @@ -159,7 +160,6 @@ impl Default for DocumentMessageHandler { // ============================================ network_interface: default_document_network_interface(), collapsed: CollapsedLayers::default(), - name: DEFAULT_DOCUMENT_NAME.to_string(), commit_hash: GRAPHITE_GIT_COMMIT_HASH.to_string(), document_ptz: PTZ::default(), document_mode: DocumentMode::DesignMode, @@ -172,11 +172,12 @@ impl Default for DocumentMessageHandler { // ============================================= // Fields omitted from the saved document format // ============================================= + name: DEFAULT_DOCUMENT_NAME.to_string(), + path: None, breadcrumb_network_path: Vec::new(), selection_network_path: Vec::new(), document_undo_history: VecDeque::new(), document_redo_history: VecDeque::new(), - path: None, saved_hash: None, auto_saved_hash: None, layer_range_selection_reference: None, @@ -947,7 +948,11 @@ impl MessageHandler> for DocumentMes responses.add(OverlaysMessage::Draw); } DocumentMessage::RenameDocument { new_name } => { - self.name = new_name; + self.name = new_name.clone(); + + self.path = None; + self.set_save_state(false); + responses.add(PortfolioMessage::UpdateOpenDocumentsList); responses.add(NodeGraphMessage::UpdateNewNodeGraph); } @@ -1020,25 +1025,40 @@ impl MessageHandler> for DocumentMes multiplier: scrollbar_multiplier.into(), }); } - DocumentMessage::SaveDocument => { + DocumentMessage::SaveDocument | DocumentMessage::SaveDocumentAs => { + if let DocumentMessage::SaveDocumentAs = message { + self.path = None; + } + self.set_save_state(true); responses.add(PortfolioMessage::AutoSaveActiveDocument); // Update the save status of the just saved document responses.add(PortfolioMessage::UpdateOpenDocumentsList); - let name = match self.name.ends_with(FILE_SAVE_SUFFIX) { - true => self.name.clone(), - false => self.name.clone() + FILE_SAVE_SUFFIX, - }; responses.add(FrontendMessage::TriggerSaveDocument { document_id, - name, + name: format!("{}.{}", self.name.clone(), FILE_EXTENSION), path: self.path.clone(), content: self.serialize_document().into_bytes(), }) } DocumentMessage::SavedDocument { path } => { self.path = path; + + // Update the name to match the file stem + let document_name_from_path = self.path.as_ref().and_then(|path| { + if path.extension().is_some_and(|e| e == FILE_EXTENSION) { + path.file_stem().map(|n| n.to_string_lossy().to_string()) + } else { + None + } + }); + if let Some(name) = document_name_from_path { + self.name = name; + + responses.add(PortfolioMessage::UpdateOpenDocumentsList); + responses.add(NodeGraphMessage::UpdateNewNodeGraph); + } } DocumentMessage::SelectParentLayer => { let selected_nodes = self.network_interface.selected_nodes(); @@ -1571,6 +1591,10 @@ impl MessageHandler> for DocumentMes ZoomCanvasToFitAll, ); + // Additional actions available on desktop + #[cfg(not(target_family = "wasm"))] + common.extend(actions!(DocumentMessageDiscriminant::SaveDocumentAs)); + // Additional actions if there are any selected layers if self.network_interface.selected_nodes().selected_layers(self.metadata()).next().is_some() { let mut select = actions!(DocumentMessageDiscriminant; diff --git a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs index 025b4b6b8f..9b86761d87 100644 --- a/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs +++ b/editor/src/messages/portfolio/menu_bar/menu_bar_message_handler.rs @@ -101,14 +101,25 @@ impl LayoutHolder for MenuBarMessageHandler { ..MenuBarEntry::default() }, ], - vec![MenuBarEntry { - label: "Save".into(), - icon: Some("Save".into()), - shortcut: action_keys!(DocumentMessageDiscriminant::SaveDocument), - action: MenuBarEntry::create_action(|_| DocumentMessage::SaveDocument.into()), - disabled: no_active_document, - ..MenuBarEntry::default() - }], + vec![ + MenuBarEntry { + label: "Save".into(), + icon: Some("Save".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::SaveDocument), + action: MenuBarEntry::create_action(|_| DocumentMessage::SaveDocument.into()), + disabled: no_active_document, + ..MenuBarEntry::default() + }, + #[cfg(not(target_family = "wasm"))] + MenuBarEntry { + label: "Save As…".into(), + icon: Some("Save".into()), + shortcut: action_keys!(DocumentMessageDiscriminant::SaveDocumentAs), + action: MenuBarEntry::create_action(|_| DocumentMessage::SaveDocumentAs.into()), + disabled: no_active_document, + ..MenuBarEntry::default() + }, + ], vec![ MenuBarEntry { label: "Import…".into(), diff --git a/editor/src/messages/portfolio/portfolio_message.rs b/editor/src/messages/portfolio/portfolio_message.rs index ac12eafb93..75717bac42 100644 --- a/editor/src/messages/portfolio/portfolio_message.rs +++ b/editor/src/messages/portfolio/portfolio_message.rs @@ -6,6 +6,7 @@ use crate::messages::prelude::*; use graphene_std::Color; use graphene_std::raster::Image; use graphene_std::text::Font; +use std::path::PathBuf; #[impl_message(Message, Portfolio)] #[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)] @@ -66,18 +67,20 @@ pub enum PortfolioMessage { NextDocument, OpenDocument, OpenDocumentFile { - document_name: String, + document_name: Option, + document_path: Option, document_serialized_content: String, }, - ToggleResetNodesToDefinitionsOnOpen, OpenDocumentFileWithId { document_id: DocumentId, - document_name: String, + document_name: Option, + document_path: Option, document_is_auto_saved: bool, document_is_saved: bool, document_serialized_content: String, to_front: bool, }, + ToggleResetNodesToDefinitionsOnOpen, PasteIntoFolder { clipboard: Clipboard, parent: LayerNodeIdentifier, @@ -115,7 +118,7 @@ pub enum PortfolioMessage { document_id: DocumentId, }, SubmitDocumentExport { - file_name: String, + name: String, file_type: FileType, scale_factor: f64, bounds: ExportBounds, diff --git a/editor/src/messages/portfolio/portfolio_message_handler.rs b/editor/src/messages/portfolio/portfolio_message_handler.rs index b299f64bce..3ff79007fa 100644 --- a/editor/src/messages/portfolio/portfolio_message_handler.rs +++ b/editor/src/messages/portfolio/portfolio_message_handler.rs @@ -2,7 +2,7 @@ use super::document::utility_types::document_metadata::LayerNodeIdentifier; use super::document::utility_types::network_interface; use super::utility_types::{PanelType, PersistentData}; use crate::application::generate_uuid; -use crate::consts::{DEFAULT_DOCUMENT_NAME, DEFAULT_STROKE_WIDTH}; +use crate::consts::{DEFAULT_DOCUMENT_NAME, DEFAULT_STROKE_WIDTH, FILE_EXTENSION}; use crate::messages::animation::TimingInformation; use crate::messages::debug::utility_types::MessageLoggingVerbosity; use crate::messages::dialog::simple_dialogs; @@ -419,12 +419,14 @@ impl MessageHandler> for Portfolio } PortfolioMessage::OpenDocumentFile { document_name, + document_path, document_serialized_content, } => { let document_id = DocumentId(generate_uuid()); responses.add(PortfolioMessage::OpenDocumentFileWithId { document_id, document_name, + document_path, document_is_auto_saved: false, document_is_saved: true, document_serialized_content, @@ -439,6 +441,7 @@ impl MessageHandler> for Portfolio PortfolioMessage::OpenDocumentFileWithId { document_id, document_name, + document_path, document_is_auto_saved, document_is_saved, document_serialized_content, @@ -450,10 +453,7 @@ impl MessageHandler> for Portfolio let document_serialized_content = document_migration_string_preprocessing(document_serialized_content); // Deserialize the document - let document = DocumentMessageHandler::deserialize_document(&document_serialized_content).map(|mut document| { - document.name.clone_from(&document_name); - document - }); + let document = DocumentMessageHandler::deserialize_document(&document_serialized_content); // Display an error to the user if the document could not be opened let mut document = match document { @@ -514,6 +514,30 @@ impl MessageHandler> for Portfolio document.set_auto_save_state(document_is_auto_saved); document.set_save_state(document_is_saved); + let document_name_from_path = document_path.as_ref().and_then(|path| { + if path.extension().is_some_and(|e| e == FILE_EXTENSION) { + path.file_stem().map(|n| n.to_string_lossy().to_string()) + } else { + None + } + }); + + match (document_name, document_path, document_name_from_path) { + (Some(name), _, None) => { + document.name = name; + } + (_, Some(path), Some(name)) => { + document.name = name; + document.path = Some(path); + } + (_, _, Some(name)) => { + document.name = name; + } + _ => { + document.name = DEFAULT_DOCUMENT_NAME.to_string(); + } + } + // Load the document into the portfolio so it opens in the editor self.load_document(document, document_id, self.layers_panel_open, responses, to_front); } @@ -899,7 +923,7 @@ impl MessageHandler> for Portfolio } } PortfolioMessage::SubmitDocumentExport { - file_name, + name, file_type, scale_factor, bounds, @@ -907,7 +931,7 @@ impl MessageHandler> for Portfolio } => { let document = self.active_document_id.and_then(|id| self.documents.get_mut(&id)).expect("Tried to render non-existent document"); let export_config = ExportConfig { - file_name, + name, file_type, scale_factor, bounds, diff --git a/editor/src/node_graph_executor.rs b/editor/src/node_graph_executor.rs index 36d01c6dc2..a5fb49b749 100644 --- a/editor/src/node_graph_executor.rs +++ b/editor/src/node_graph_executor.rs @@ -1,4 +1,3 @@ -use crate::consts::FILE_SAVE_SUFFIX; use crate::messages::frontend::utility_types::{ExportBounds, FileType}; use crate::messages::prelude::*; use glam::{DAffine2, DVec2, UVec2}; @@ -229,18 +228,11 @@ impl NodeGraphExecutor { }; let ExportConfig { - file_type, - file_name, - size, - scale_factor, - .. + file_type, name, size, scale_factor, .. } = export_config; let file_suffix = &format!(".{file_type:?}").to_lowercase(); - let name = match file_name.ends_with(FILE_SAVE_SUFFIX) { - true => file_name.replace(FILE_SAVE_SUFFIX, file_suffix), - false => file_name + file_suffix, - }; + let name = name + file_suffix; if file_type == FileType::Svg { responses.add(FrontendMessage::TriggerSaveFile { name, content: svg.into_bytes() }); diff --git a/editor/src/node_graph_executor/runtime.rs b/editor/src/node_graph_executor/runtime.rs index ce1f292c4e..6e09445faa 100644 --- a/editor/src/node_graph_executor/runtime.rs +++ b/editor/src/node_graph_executor/runtime.rs @@ -73,7 +73,7 @@ pub struct GraphUpdate { #[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct ExportConfig { - pub file_name: String, + pub name: String, pub file_type: FileType, pub scale_factor: f64, pub bounds: ExportBounds, diff --git a/frontend/src/components/panels/Document.svelte b/frontend/src/components/panels/Document.svelte index b907b51c85..22c7862438 100644 --- a/frontend/src/components/panels/Document.svelte +++ b/frontend/src/components/panels/Document.svelte @@ -151,9 +151,11 @@ return; } - if (file.name.endsWith(".graphite")) { + const graphiteFileSuffix = "." + editor.handle.fileExtension(); + if (file.name.endsWith(graphiteFileSuffix)) { const content = await file.text(); - editor.handle.openDocumentFile(file.name, content); + const documentName = file.name.slice(0, -graphiteFileSuffix.length); + editor.handle.openDocumentFile(documentName, content); return; } }); diff --git a/frontend/src/components/panels/Layers.svelte b/frontend/src/components/panels/Layers.svelte index 36159736a9..2f3626797b 100644 --- a/frontend/src/components/panels/Layers.svelte +++ b/frontend/src/components/panels/Layers.svelte @@ -438,9 +438,11 @@ } // When we eventually have sub-documents, this should be changed to import the document instead of opening it in a separate tab - if (file.name.endsWith(".graphite")) { + const graphiteFileSuffix = "." + editor.handle.fileExtension(); + if (file.name.endsWith(graphiteFileSuffix)) { const content = await file.text(); - editor.handle.openDocumentFile(file.name, content); + const documentName = file.name.slice(0, -graphiteFileSuffix.length); + editor.handle.openDocumentFile(documentName, content); return; } }); diff --git a/frontend/src/components/window/workspace/Panel.svelte b/frontend/src/components/window/workspace/Panel.svelte index f53b9ff399..958fe702fb 100644 --- a/frontend/src/components/window/workspace/Panel.svelte +++ b/frontend/src/components/window/workspace/Panel.svelte @@ -83,9 +83,11 @@ return; } - if (file.name.endsWith(".graphite")) { + const graphiteFileSuffix = "." + editor.handle.fileExtension(); + if (file.name.endsWith(graphiteFileSuffix)) { const content = await file.text(); - editor.handle.openDocumentFile(file.name, content); + const documentName = file.name.slice(0, -graphiteFileSuffix.length); + editor.handle.openDocumentFile(documentName, content); return; } }); diff --git a/frontend/src/io-managers/input.ts b/frontend/src/io-managers/input.ts index 711e039804..f0ac34db0c 100644 --- a/frontend/src/io-managers/input.ts +++ b/frontend/src/io-managers/input.ts @@ -334,8 +334,11 @@ export function createInputManager(editor: Editor, dialog: DialogState, portfoli editor.handle.pasteImage(file.name, new Uint8Array(imageData.data), imageData.width, imageData.height); } - if (file.name.endsWith(".graphite")) { - editor.handle.openDocumentFile(file.name, await file.text()); + const graphiteFileSuffix = "." + editor.handle.fileExtension(); + if (file.name.endsWith(graphiteFileSuffix)) { + const content = await file.text(); + const documentName = file.name.slice(0, -graphiteFileSuffix.length); + editor.handle.openDocumentFile(documentName, content); } }); } diff --git a/frontend/src/state-providers/portfolio.ts b/frontend/src/state-providers/portfolio.ts index 41ad207f02..0c3d5ad364 100644 --- a/frontend/src/state-providers/portfolio.ts +++ b/frontend/src/state-providers/portfolio.ts @@ -62,9 +62,16 @@ export function createPortfolioState(editor: Editor) { } }); editor.subscriptions.subscribeJsMessage(TriggerOpenDocument, async () => { - const extension = editor.handle.fileSaveSuffix(); - const data = await upload(extension, "text"); - editor.handle.openDocumentFile(data.filename, data.content); + const suffix = "." + editor.handle.fileExtension(); + const data = await upload(suffix, "text"); + + // Use filename as document name, removing the extension if it exists + let documentName = data.filename; + if (documentName.endsWith(suffix)) { + documentName = documentName.slice(0, -suffix.length); + } + + editor.handle.openDocumentFile(documentName, data.content); }); editor.subscriptions.subscribeJsMessage(TriggerImport, async () => { const data = await upload("image/*", "both"); @@ -76,8 +83,10 @@ export function createPortfolioState(editor: Editor) { } // In case the user accidentally uploads a Graphite file, open it instead of failing to import it - if (data.filename.endsWith(".graphite")) { - editor.handle.openDocumentFile(data.filename, data.content.text); + const graphiteFileSuffix = "." + editor.handle.fileExtension(); + if (data.filename.endsWith(graphiteFileSuffix)) { + const documentName = data.filename.slice(0, -graphiteFileSuffix.length); + editor.handle.openDocumentFile(documentName, data.content.text); return; } diff --git a/frontend/src/utility-functions/files.ts b/frontend/src/utility-functions/files.ts index 6d230433a1..08be7ccdf2 100644 --- a/frontend/src/utility-functions/files.ts +++ b/frontend/src/utility-functions/files.ts @@ -22,11 +22,12 @@ export function downloadFile(filename: string, content: ArrayBuffer) { downloadFileBlob(filename, blob); } -export async function upload(acceptedExtensions: string, textOrData: T): Promise> { +// See https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/file#accept for the `accept` string format +export async function upload(accept: string, textOrData: T): Promise> { return new Promise>((resolve, _) => { const element = document.createElement("input"); element.type = "file"; - element.accept = acceptedExtensions; + element.accept = accept; element.addEventListener( "change", diff --git a/frontend/wasm/src/editor_api.rs b/frontend/wasm/src/editor_api.rs index ddc4bc28db..34983bd24a 100644 --- a/frontend/wasm/src/editor_api.rs +++ b/frontend/wasm/src/editor_api.rs @@ -6,7 +6,7 @@ // use crate::helpers::translate_key; use crate::{EDITOR_HANDLE, EDITOR_HAS_CRASHED, Error, MESSAGE_BUFFER}; -use editor::consts::FILE_SAVE_SUFFIX; +use editor::consts::FILE_EXTENSION; use editor::messages::input_mapper::utility_types::input_keyboard::ModifierKeys; use editor::messages::input_mapper::utility_types::input_mouse::{EditorMouseState, ScrollDelta, ViewportBounds}; use editor::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier; @@ -344,10 +344,10 @@ impl EditorHandle { cfg!(debug_assertions) } - /// Get the constant `FILE_SAVE_SUFFIX` - #[wasm_bindgen(js_name = fileSaveSuffix)] - pub fn file_save_suffix(&self) -> String { - FILE_SAVE_SUFFIX.into() + /// Get the constant `FILE_EXTENSION` + #[wasm_bindgen(js_name = fileExtension)] + pub fn file_extension(&self) -> String { + FILE_EXTENSION.into() } /// Update the value of a given UI widget, but don't commit it to the history (unless `commit_layout()` is called, which handles that) @@ -421,7 +421,8 @@ impl EditorHandle { #[wasm_bindgen(js_name = openDocumentFile)] pub fn open_document_file(&self, document_name: String, document_serialized_content: String) { let message = PortfolioMessage::OpenDocumentFile { - document_name, + document_name: Some(document_name), + document_path: None, document_serialized_content, }; self.dispatch(message); @@ -432,7 +433,8 @@ impl EditorHandle { let document_id = DocumentId(document_id); let message = PortfolioMessage::OpenDocumentFileWithId { document_id, - document_name, + document_name: Some(document_name), + document_path: None, document_is_auto_saved: true, document_is_saved, document_serialized_content,