Files
Graphite/desktop/wrapper/src/intercept_frontend_message.rs
Keavon Chambers 52d2b38a82 Refactor the TypeScript data flow for full type safety and auto-generation of Rust types (#3865)
* Migrate Specta to Tsify to auto-generate messages.ts, working except colors and widgets

* Adopt the generated FillColor/Color/GradientStops

* Fix widget typing

* Separate WidgetGroup enum variants into wrapper structs

* Small rename

* Simplify widgets further

* Clean up message type references

* Switch type imports to the auto-generated file

* Remove lowercase serde rename

* Fix FillChoice deserialization

* Fix small regression from #3837

* Improve type safety

* Make WidgetSpan type-safe

* More cleanup and type safety

* More type safety

* More type safety

* Get the rest to type-check without errors; improve widget builder macro to have optional icons; improve Svelte 5 configs

* Cargo fmt

* Fix imports

* Update outdated readme info

* Fix lint command rename references

* Fix typos

* One more typos fix

* Remove unnecessary dep: prefix from the edited Cargo.toml files

* Remove excess parts from Cargo.toml

* Fix compiling on desktop

* Revert "Remove excess parts from Cargo.toml"

This reverts commit 6b711117b3a5d5d8a3ee20f36a43bc74930b7c82.

* Update dev docs with simpler, more accurate instructions
2026-03-09 16:35:04 -07:00

170 lines
6.2 KiB
Rust

#[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};
pub(super) fn intercept_frontend_message(dispatcher: &mut DesktopWrapperMessageDispatcher, message: FrontendMessage) -> Option<FrontendMessage> {
match message {
FrontendMessage::RenderOverlays { context } => {
dispatcher.respond(DesktopFrontendMessage::UpdateOverlays(context.take_scene()));
}
FrontendMessage::TriggerOpen => {
dispatcher.respond(DesktopFrontendMessage::OpenFileDialog {
title: "Open Document".to_string(),
filters: vec![],
context: OpenFileDialogContext::Open,
});
}
FrontendMessage::TriggerImport => {
dispatcher.respond(DesktopFrontendMessage::OpenFileDialog {
title: "Import File".to_string(),
filters: vec![],
context: OpenFileDialogContext::Import,
});
}
FrontendMessage::TriggerSaveDocument { document_id, name, path, content } => {
let content = content.into_vec();
if let Some(path) = path {
dispatcher.respond(DesktopFrontendMessage::WriteFile { path, content });
} else {
dispatcher.respond(DesktopFrontendMessage::SaveFileDialog {
title: "Save Document".to_string(),
default_filename: name,
default_folder: path.and_then(|p| p.parent().map(PathBuf::from)),
filters: vec![FileFilter {
name: "Graphite".to_string(),
extensions: vec!["graphite".to_string()],
}],
context: SaveFileDialogContext::Document { document_id, content },
});
}
}
FrontendMessage::TriggerSaveFile { name, content } => {
let content = content.into_vec();
dispatcher.respond(DesktopFrontendMessage::SaveFileDialog {
title: "Save File".to_string(),
default_filename: name,
default_folder: None,
filters: Vec::new(),
context: SaveFileDialogContext::File { content },
});
}
FrontendMessage::TriggerVisitLink { url } => {
dispatcher.respond(DesktopFrontendMessage::OpenUrl(url));
}
FrontendMessage::UpdateViewportPhysicalBounds { x, y, width, height } => {
dispatcher.respond(DesktopFrontendMessage::UpdateViewportPhysicalBounds { x, y, width, height });
}
FrontendMessage::UpdateUIScale { scale } => {
dispatcher.respond(DesktopFrontendMessage::UpdateUIScale { scale });
return Some(FrontendMessage::UpdateUIScale { scale });
}
FrontendMessage::TriggerPersistenceWriteDocument { document_id, document, details } => {
dispatcher.respond(DesktopFrontendMessage::PersistenceWriteDocument {
id: document_id,
document: Document {
name: details.name,
path: details.path,
content: document,
is_saved: details.is_saved,
},
});
}
FrontendMessage::TriggerPersistenceRemoveDocument { document_id } => {
dispatcher.respond(DesktopFrontendMessage::PersistenceDeleteDocument { id: document_id });
}
FrontendMessage::UpdateActiveDocument { document_id } => {
dispatcher.respond(DesktopFrontendMessage::PersistenceUpdateCurrentDocument { id: document_id });
// Forward this to update the UI
return Some(FrontendMessage::UpdateActiveDocument { document_id });
}
FrontendMessage::UpdateOpenDocumentsList { open_documents } => {
dispatcher.respond(DesktopFrontendMessage::PersistenceUpdateDocumentsList {
ids: open_documents.iter().map(|document| document.id).collect(),
});
// Forward this to update the UI
return Some(FrontendMessage::UpdateOpenDocumentsList { open_documents });
}
FrontendMessage::TriggerLoadFirstAutoSaveDocument => {
dispatcher.respond(DesktopFrontendMessage::PersistenceLoadCurrentDocument);
}
FrontendMessage::TriggerLoadRestAutoSaveDocuments => {
dispatcher.respond(DesktopFrontendMessage::PersistenceLoadRemainingDocuments);
}
FrontendMessage::TriggerOpenLaunchDocuments => {
dispatcher.respond(DesktopFrontendMessage::OpenLaunchDocuments);
}
FrontendMessage::TriggerSavePreferences { preferences } => {
dispatcher.respond(DesktopFrontendMessage::PersistenceWritePreferences { preferences });
}
FrontendMessage::TriggerLoadPreferences => {
dispatcher.respond(DesktopFrontendMessage::PersistenceLoadPreferences);
}
#[cfg(target_os = "macos")]
FrontendMessage::UpdateLayout {
layout_target: LayoutTarget::MenuBar,
diff,
} => {
use graphite_editor::messages::tool::tool_messages::tool_prelude::{DiffUpdate, WidgetDiff};
match diff.as_slice() {
[
WidgetDiff {
widget_path,
new_value: DiffUpdate::Layout(layout),
},
] if widget_path.is_empty() => {
let entries = crate::utils::menu::convert_menu_bar_layout_to_menu_items(layout);
dispatcher.respond(DesktopFrontendMessage::UpdateMenu { entries });
}
_ => {}
}
}
FrontendMessage::TriggerClipboardRead => {
dispatcher.respond(DesktopFrontendMessage::ClipboardRead);
}
FrontendMessage::TriggerClipboardWrite { content } => {
dispatcher.respond(DesktopFrontendMessage::ClipboardWrite { content });
}
FrontendMessage::WindowPointerLock => {
dispatcher.respond(DesktopFrontendMessage::PointerLock);
}
FrontendMessage::WindowClose => {
dispatcher.respond(DesktopFrontendMessage::WindowClose);
}
FrontendMessage::WindowMinimize => {
dispatcher.respond(DesktopFrontendMessage::WindowMinimize);
}
FrontendMessage::WindowMaximize => {
dispatcher.respond(DesktopFrontendMessage::WindowMaximize);
}
FrontendMessage::WindowFullscreen => {
dispatcher.respond(DesktopFrontendMessage::WindowFullscreen);
}
FrontendMessage::WindowDrag => {
dispatcher.respond(DesktopFrontendMessage::WindowDrag);
}
FrontendMessage::WindowHide => {
dispatcher.respond(DesktopFrontendMessage::WindowHide);
}
FrontendMessage::WindowHideOthers => {
dispatcher.respond(DesktopFrontendMessage::WindowHideOthers);
}
FrontendMessage::WindowShowAll => {
dispatcher.respond(DesktopFrontendMessage::WindowShowAll);
}
FrontendMessage::WindowRestart => {
dispatcher.respond(DesktopFrontendMessage::Restart);
}
FrontendMessage::TriggerDisplayThirdPartyLicensesDialog => {
dispatcher.respond(DesktopFrontendMessage::LoadThirdPartyLicenses);
}
m => return Some(m),
}
None
}