Skip to content

Commit 363d1b0

Browse files
Maybe bad idea
1 parent 9860fd6 commit 363d1b0

7 files changed

Lines changed: 76 additions & 25 deletions

File tree

editor/src/messages/frontend/frontend_message.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::IconName;
22
use super::utility_types::{MouseCursorIcon, PersistedState};
33
use crate::messages::app_window::app_window_message_handler::AppWindowPlatform;
4-
use crate::messages::frontend::utility_types::{DocumentInfo, EyedropperPreviewImage};
4+
use crate::messages::frontend::utility_types::{DocumentInfo, EyedropperPreviewImage, FrontendMessageFuture};
55
use crate::messages::input_mapper::utility_types::misc::ActionShortcut;
66
use crate::messages::layout::utility_types::widget_prelude::*;
77
use crate::messages::portfolio::document::node_graph::utility_types::{
@@ -27,6 +27,13 @@ use crate::messages::portfolio::document::overlays::utility_types::OverlayContex
2727
#[derive(derivative::Derivative, Clone, serde::Serialize, serde::Deserialize)]
2828
#[derivative(Debug, PartialEq)]
2929
pub enum FrontendMessage {
30+
Await {
31+
#[serde(skip, default)]
32+
#[derivative(Debug = "ignore", PartialEq = "ignore")]
33+
#[cfg_attr(feature = "wasm", tsify(type = "unknown"))]
34+
future: FrontendMessageFuture,
35+
},
36+
3037
// Display prefix: make the frontend show something, like a dialog
3138
DisplayDialog {
3239
title: String,

editor/src/messages/frontend/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod utility_types;
44

55
#[doc(inline)]
66
pub use frontend_message::{FrontendMessage, FrontendMessageDiscriminant};
7+
pub use utility_types::FrontendMessageFuture;
78

89
// TODO: Make this an enum with the actual icon names, somehow derived from or tied to the frontend icon set.
910
// TODO: Then remove `#[widget_builder(string)]` from all icon fields.

editor/src/messages/frontend/utility_types.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
use std::future::{Future, IntoFuture};
12
use std::path::PathBuf;
3+
use std::pin::Pin;
4+
use std::sync::{Arc, Mutex};
25

36
use graph_craft::application_io::ResourceHash;
47

@@ -82,3 +85,31 @@ pub struct EyedropperPreviewImage {
8285
pub width: u32,
8386
pub height: u32,
8487
}
88+
89+
#[derive(Clone, Default)]
90+
pub struct FrontendMessageFuture {
91+
inner: Arc<Mutex<Option<InnerFrontendMessageFuture>>>,
92+
}
93+
94+
impl FrontendMessageFuture {
95+
pub fn new(future: impl Future<Output = FrontendMessage> + Send + 'static) -> Self {
96+
Self {
97+
inner: Arc::new(Mutex::new(Some(Box::pin(future)))),
98+
}
99+
}
100+
}
101+
102+
type InnerFrontendMessageFuture = Pin<Box<dyn Future<Output = FrontendMessage> + Send + 'static>>;
103+
104+
impl IntoFuture for FrontendMessageFuture {
105+
type Output = FrontendMessage;
106+
type IntoFuture = InnerFrontendMessageFuture;
107+
108+
fn into_future(self) -> Self::IntoFuture {
109+
self.inner
110+
.lock()
111+
.unwrap_or_else(|poisoned| poisoned.into_inner())
112+
.take()
113+
.expect("FrontendMessageFuture can only be awaited once")
114+
}
115+
}

editor/src/messages/portfolio/document/document_message_handler.rs

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -925,19 +925,32 @@ impl MessageHandler<DocumentMessage, DocumentMessageContext<'_>> for DocumentMes
925925
}
926926
let folder = self.path.as_ref().and_then(|path| path.parent()).map(|parent| parent.to_path_buf());
927927

928-
let exported = resources.export(&Vec::from_iter(self.used_resources()));
929-
self.embedded_resources = EmbeddedResources::from_iter(exported);
930-
let content = self.serialize_document();
931-
932-
// Clear embedded resources after serialization to free memory.
933-
let _ = std::mem::take(&mut self.embedded_resources);
934-
935-
responses.add(FrontendMessage::TriggerSaveDocument {
936-
document_id,
937-
name: format!("{}.{}", self.name.clone(), FILE_EXTENSION),
938-
path,
939-
folder,
940-
content: content.into_bytes().into(),
928+
let resource_hashes = Vec::from_iter(self.used_resources()).into_boxed_slice();
929+
let resources = resources.resources();
930+
let mut document = self.clone();
931+
let name = format!("{}.{}", self.name.clone(), FILE_EXTENSION);
932+
933+
responses.add(FrontendMessage::Await {
934+
future: FrontendMessageFuture::new(async move {
935+
let loads = resource_hashes
936+
.into_iter()
937+
.map(|hash| {
938+
let resource = resources.load(hash);
939+
async move { resource.await.map(|resource| (hash, resource)) }
940+
})
941+
.collect::<Vec<_>>();
942+
943+
document.embedded_resources = EmbeddedResources::from_iter(futures::future::join_all(loads).await.into_iter().flatten());
944+
let content = document.serialize_document();
945+
946+
FrontendMessage::TriggerSaveDocument {
947+
document_id,
948+
name,
949+
path,
950+
folder,
951+
content: content.into_bytes().into(),
952+
}
953+
}),
941954
});
942955
}
943956
DocumentMessage::SavedDocument { path } => {

editor/src/messages/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use crate::messages::dialog::export_dialog::{ExportDialogMessage, ExportDial
1515
pub use crate::messages::dialog::new_document_dialog::{NewDocumentDialogMessage, NewDocumentDialogMessageDiscriminant, NewDocumentDialogMessageHandler};
1616
pub use crate::messages::dialog::preferences_dialog::{PreferencesDialogMessage, PreferencesDialogMessageContext, PreferencesDialogMessageDiscriminant, PreferencesDialogMessageHandler};
1717
pub use crate::messages::dialog::{DialogMessage, DialogMessageContext, DialogMessageDiscriminant, DialogMessageHandler};
18-
pub use crate::messages::frontend::{FrontendMessage, FrontendMessageDiscriminant};
18+
pub use crate::messages::frontend::{FrontendMessage, FrontendMessageDiscriminant, FrontendMessageFuture};
1919
pub use crate::messages::input_mapper::key_mapping::{KeyMappingMessage, KeyMappingMessageContext, KeyMappingMessageDiscriminant, KeyMappingMessageHandler};
2020
pub use crate::messages::input_mapper::{InputMapperMessage, InputMapperMessageContext, InputMapperMessageDiscriminant, InputMapperMessageHandler};
2121
pub use crate::messages::input_preprocessor::{InputPreprocessorMessage, InputPreprocessorMessageContext, InputPreprocessorMessageDiscriminant, InputPreprocessorMessageHandler};

editor/src/messages/resource/resource_message_handler.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::messages::prelude::*;
2-
use graph_craft::application_io::{Resource, ResourceFuture, ResourceHash, ResourceStorage, Resources};
2+
use graph_craft::application_io::{ResourceFuture, ResourceHash, ResourceStorage, Resources};
33
use std::sync::{Arc, RwLock};
44

55
#[derive(Clone)]
@@ -26,15 +26,6 @@ impl ResourceMessageHandler {
2626
}
2727
}
2828

29-
pub fn export(&self, resources: &[ResourceHash]) -> Box<[(ResourceHash, Resource)]> {
30-
let Some(storage) = &self.storage else {
31-
log::error!("Attempted to export resources but storage is not initialized");
32-
return Box::new([]);
33-
};
34-
let mut storage = storage.write().unwrap();
35-
resources.iter().filter_map(|hash| storage.read(hash).map(|resource| (*hash, resource))).collect()
36-
}
37-
3829
pub fn resources(&self) -> Box<dyn Resources> {
3930
Box::new(ResourcesHandle {
4031
inner: self.storage.clone().expect("Resource storage not initialized"),

frontend/wrapper/src/editor_wrapper.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ impl EditorWrapper {
143143

144144
// Sends a FrontendMessage to JavaScript
145145
pub(crate) fn send_frontend_message_to_js(&self, message: FrontendMessage) {
146+
if let FrontendMessage::Await { future } = message {
147+
let wrapper = self.clone();
148+
wasm_bindgen_futures::spawn_local(async move {
149+
wrapper.send_frontend_message_to_js(future.await);
150+
});
151+
return;
152+
}
153+
146154
if let FrontendMessage::UpdateImageData { ref image_data } = message {
147155
let new_hash = calculate_hash(&CacheHashWrapper(image_data));
148156
let prev_hash = IMAGE_DATA_HASH.load(Ordering::Relaxed);

0 commit comments

Comments
 (0)