Skip to content

Commit 76cf6d5

Browse files
committed
Resend layouts from Rust when editor is re-mounted on HMR
1 parent 39fbc6c commit 76cf6d5

5 files changed

Lines changed: 49 additions & 10 deletions

File tree

editor/src/messages/layout/layout_message.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub enum LayoutMessage {
88
layout_target: LayoutTarget,
99
widget_id: WidgetId,
1010
},
11+
ResendAllLayouts,
1112
SendLayout {
1213
layout: Layout,
1314
layout_target: LayoutTarget,

editor/src/messages/layout/layout_message_handler.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ impl MessageHandler<LayoutMessage, LayoutMessageContext<'_>> for LayoutMessageHa
3333
// Resend that diff
3434
self.send_diff(vec![diff], layout_target, responses, action_input_mapping);
3535
}
36+
LayoutMessage::ResendAllLayouts => {
37+
// Collect non-empty layouts and their indices, then clear the stored copies so diffs compute as full re-sends
38+
let layouts_to_resend: Vec<_> = self
39+
.layouts
40+
.iter_mut()
41+
.enumerate()
42+
.filter(|(_, layout)| !layout.0.is_empty())
43+
.map(|(i, layout)| (LayoutTarget::from(i as u8), std::mem::take(layout)))
44+
.collect();
45+
46+
for (layout_target, layout) in layouts_to_resend {
47+
self.diff_and_send_layout_to_frontend(layout_target, layout, responses, action_input_mapping);
48+
}
49+
}
3650
LayoutMessage::SendLayout { layout, layout_target } => {
3751
self.diff_and_send_layout_to_frontend(layout_target, layout, responses, action_input_mapping);
3852
}

editor/src/messages/layout/utility_types/layout_widget.rs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,30 @@ impl core::fmt::Display for WidgetId {
2020
}
2121
}
2222

23-
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
24-
#[derive(PartialEq, Clone, Debug, Hash, Eq, Copy, serde::Serialize, serde::Deserialize)]
25-
#[repr(u8)]
26-
pub enum LayoutTarget {
23+
macro_rules! define_layout_target {
24+
($($(#[$attr:meta])* $variant:ident),* $(,)?) => {
25+
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
26+
#[derive(PartialEq, Clone, Debug, Hash, Eq, Copy, serde::Serialize, serde::Deserialize)]
27+
#[repr(u8)]
28+
pub enum LayoutTarget {
29+
$($(#[$attr])* $variant,)*
30+
// KEEP THIS ENUM LAST
31+
// This is a marker that is used to define an array that is used to hold widgets
32+
#[serde(skip)]
33+
_LayoutTargetLength,
34+
}
35+
36+
impl From<u8> for LayoutTarget {
37+
fn from(value: u8) -> Self {
38+
match value {
39+
$(x if x == Self::$variant as u8 => Self::$variant,)*
40+
_ => panic!("Invalid LayoutTarget discriminant: {value}"),
41+
}
42+
}
43+
}
44+
};
45+
}
46+
define_layout_target!(
2747
/// The spreadsheet panel allows for the visualisation of data in the graph.
2848
DataPanel,
2949
/// Contains the action buttons at the bottom of the dialog. Must be shown with the `FrontendMessage::DisplayDialog` message.
@@ -58,12 +78,7 @@ pub enum LayoutTarget {
5878
WelcomeScreenButtons,
5979
/// The color swatch for the working colors and a flip and reset button found at the bottom of the tool shelf.
6080
WorkingColors,
61-
62-
// KEEP THIS ENUM LAST
63-
// This is a marker that is used to define an array that is used to hold widgets
64-
#[serde(skip)]
65-
_LayoutTargetLength,
66-
}
81+
);
6782

6883
/// For use by structs that define a UI widget layout by implementing the layout() function belonging to this trait.
6984
/// The send_layout() function can then be called by other code which is a part of the same struct so as to send the layout to the frontend.

frontend/src/components/Editor.svelte

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
// Initialize certain setup tasks required by the editor backend to be ready for the user now that the frontend is ready.
4747
// The backend handles idempotency, so this is safe to call again during HMR re-mounts.
4848
editor.handle.initAfterFrontendReady();
49+
50+
// Re-send all UI layouts from Rust so the frontend has them after an HMR re-mount
51+
editor.handle.resendAllLayouts();
4952
});
5053
5154
onDestroy(() => {

frontend/wasm/src/editor_api.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,12 @@ impl EditorHandle {
187187
// the backend from the web frontend.
188188
// ========================================================================
189189

190+
/// Re-sends all UI layouts to the frontend. Called during HMR re-mounts when the frontend has lost its layout state.
191+
#[wasm_bindgen(js_name = resendAllLayouts)]
192+
pub fn resend_all_layouts(&self) {
193+
self.dispatch(LayoutMessage::ResendAllLayouts);
194+
}
195+
190196
#[wasm_bindgen(js_name = initAfterFrontendReady)]
191197
pub fn init_after_frontend_ready(&self) {
192198
// Enforce idempotency, so if this is called again during an HMR re-mount, we don't initialize the editor backend twice

0 commit comments

Comments
 (0)