diff --git a/Cargo.lock b/Cargo.lock index 1314a830a..bd92c6cff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "arrayvec" version = "0.5.2" @@ -50,6 +52,7 @@ version = "0.1.0" dependencies = [ "kurbo", "log", + "serde", ] [[package]] @@ -60,6 +63,7 @@ dependencies = [ "graphite-document-core", "graphite-proc-macros", "log", + "serde", "thiserror", ] @@ -84,10 +88,17 @@ dependencies = [ "console_error_panic_hook", "graphite-editor-core", "log", + "serde", "wasm-bindgen", "wasm-bindgen-test", ] +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" + [[package]] name = "js-sys" version = "0.3.50" @@ -139,12 +150,49 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "ryu" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" + [[package]] name = "scoped-tls" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +[[package]] +name = "serde" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +dependencies = [ + "itoa", + "ryu", + "serde", +] + [[package]] name = "syn" version = "1.0.68" @@ -189,6 +237,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" dependencies = [ "cfg-if 1.0.0", + "serde", + "serde_json", "wasm-bindgen-macro", ] diff --git a/client/web/src/components/panels/Document.vue b/client/web/src/components/panels/Document.vue index 5087b5523..626621074 100644 --- a/client/web/src/components/panels/Document.vue +++ b/client/web/src/components/panels/Document.vue @@ -328,12 +328,13 @@ export default defineComponent({ }, }, mounted() { - registerResponseHandler(ResponseType["Tool::UpdateCanvas"], (responseData) => { - this.viewportSvg = responseData; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + registerResponseHandler(ResponseType["Tool::UpdateCanvas"], (responseData: any) => { + this.viewportSvg = responseData.Tool.UpdateCanvas.document; }); - registerResponseHandler(ResponseType["Tool::SetActiveTool"], (responseData) => { - const [activeTool] = responseData; - this.activeTool = activeTool; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + registerResponseHandler(ResponseType["Tool::SetActiveTool"], (responseData: any) => { + this.activeTool = responseData.Tool.SetActiveTool.tool_name; }); window.addEventListener("keyup", (e: KeyboardEvent) => this.keyUp(e)); diff --git a/client/web/src/response-handler.ts b/client/web/src/response-handler.ts index 84e0c1ea0..45be02395 100644 --- a/client/web/src/response-handler.ts +++ b/client/web/src/response-handler.ts @@ -23,7 +23,8 @@ export function registerResponseHandler(responseType: ResponseType, callback: Re window.responseMap[responseType] = callback; } -export function handleResponse(responseType: ResponseType, responseData: string) { +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function handleResponse(responseType: ResponseType, responseData: any) { const callback = window.responseMap[responseType]; if (callback) { diff --git a/client/web/wasm/Cargo.toml b/client/web/wasm/Cargo.toml index cc351e1d3..e5bbf923a 100644 --- a/client/web/wasm/Cargo.toml +++ b/client/web/wasm/Cargo.toml @@ -18,8 +18,9 @@ default = ["console_error_panic_hook"] [dependencies] console_error_panic_hook = { version = "0.1.6", optional = true } editor-core = { path = "../../../core/editor", package = "graphite-editor-core" } -wasm-bindgen = "0.2.73" log = "0.4" +serde = { version = "1.0", features = ["derive"] } +wasm-bindgen = { version = "0.2.73", features = ["serde-serialize"] } [dev-dependencies] wasm-bindgen-test = "0.3.22" diff --git a/client/web/wasm/src/lib.rs b/client/web/wasm/src/lib.rs index b56451315..bcb3c4501 100644 --- a/client/web/wasm/src/lib.rs +++ b/client/web/wasm/src/lib.rs @@ -4,13 +4,11 @@ pub mod utils; pub mod window; pub mod wrappers; -use editor_core::{ - events::{DocumentResponse, Response, ToolResponse}, - Editor, LayerId, -}; +use editor_core::{events::Response, Editor}; use std::cell::RefCell; use utils::WasmLog; use wasm_bindgen::prelude::*; +use wrappers::WasmResponse; // the thread_local macro provides a way to initialize static variables with non-constant functions thread_local! { pub static EDITOR_STATE: RefCell = RefCell::new(Editor::new(Box::new(handle_response))) } @@ -23,37 +21,19 @@ pub fn init() { log::set_max_level(log::LevelFilter::Debug); } -fn path_to_string(path: Vec) -> String { - path.iter().map(|x| x.to_string()).collect::>().join(",") -} - fn handle_response(response: Response) { let response_type = response.to_string(); - match response { - Response::Document(doc) => match doc { - DocumentResponse::ExpandFolder { path, children } => { - let children = children - .iter() - .map(|c| format!("name:{},visible:{},type:{}", c.name, c.visible, c.layer_type)) - .collect::>() - .join(";"); - send_response(response_type, &[path_to_string(path), children]) - } - DocumentResponse::CollapseFolder { path } => send_response(response_type, &[path_to_string(path)]), - DocumentResponse::DocumentChanged => log::error!("Wasm wrapper got request to update the document"), - }, - Response::Tool(ToolResponse::UpdateCanvas { document }) => send_response(response_type, &[document]), - Response::Tool(ToolResponse::SetActiveTool { tool_name }) => send_response(response_type, &[tool_name]), - } + send_response(response_type, response); } -fn send_response(response_type: String, response_data: &[String]) { - let data = response_data.iter().map(JsValue::from).collect(); - handleResponse(response_type, data); + +fn send_response(response_type: String, response_data: Response) { + let response_data = JsValue::from_serde(&WasmResponse::new(response_data)).expect("Failed to serialize response"); + handleResponse(response_type, response_data); } #[wasm_bindgen(module = "/../src/response-handler.ts")] extern "C" { - fn handleResponse(responseType: String, responseData: Vec); + fn handleResponse(responseType: String, responseData: JsValue); } #[wasm_bindgen] diff --git a/client/web/wasm/src/wrappers.rs b/client/web/wasm/src/wrappers.rs index 1930a035a..8bcce120a 100644 --- a/client/web/wasm/src/wrappers.rs +++ b/client/web/wasm/src/wrappers.rs @@ -2,6 +2,8 @@ use crate::shims::Error; use editor_core::events; use editor_core::tools::{SelectAppendMode, ToolType}; use editor_core::Color as InnerColor; +use events::Response; +use serde::{Deserialize, Serialize}; use wasm_bindgen::prelude::*; #[wasm_bindgen] @@ -24,6 +26,15 @@ impl Color { } } +#[derive(Serialize, Deserialize)] +pub struct WasmResponse(Response); + +impl WasmResponse { + pub fn new(response: Response) -> Self { + Self(response) + } +} + macro_rules! match_string_to_enum { (match ($e:expr) {$($var:ident),* $(,)?}) => { match $e { diff --git a/core/document/Cargo.toml b/core/document/Cargo.toml index dd9fc8a1b..74f5e1ecd 100644 --- a/core/document/Cargo.toml +++ b/core/document/Cargo.toml @@ -11,3 +11,4 @@ license = "Apache-2.0" [dependencies] log = "0.4" kurbo = "0.8.0" +serde = { version = "1.0", features = ["derive"] } diff --git a/core/document/src/color.rs b/core/document/src/color.rs index 797d6dc23..42ea1ba9a 100644 --- a/core/document/src/color.rs +++ b/core/document/src/color.rs @@ -1,5 +1,7 @@ +use serde::{Deserialize, Serialize}; + #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] pub struct Color { red: f32, green: f32, diff --git a/core/document/src/layers/style/mod.rs b/core/document/src/layers/style/mod.rs index 958bc219f..86ae55ed2 100644 --- a/core/document/src/layers/style/mod.rs +++ b/core/document/src/layers/style/mod.rs @@ -1,7 +1,8 @@ use crate::color::Color; +use serde::{Deserialize, Serialize}; #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] pub struct Fill { color: Option, } @@ -21,7 +22,7 @@ impl Fill { } #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] pub struct Stroke { color: Color, width: f32, @@ -37,7 +38,7 @@ impl Stroke { } #[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq, Default)] +#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)] pub struct PathStyle { stroke: Option, fill: Option, diff --git a/core/document/src/operation.rs b/core/document/src/operation.rs index 7af1f7404..0938808c7 100644 --- a/core/document/src/operation.rs +++ b/core/document/src/operation.rs @@ -1,6 +1,8 @@ use crate::{layers::style, LayerId}; -#[derive(Debug, Clone, PartialEq)] +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] pub enum Operation { AddCircle { path: Vec, diff --git a/core/document/src/response.rs b/core/document/src/response.rs index 3ca625e4b..2aa0a5917 100644 --- a/core/document/src/response.rs +++ b/core/document/src/response.rs @@ -1,14 +1,15 @@ use crate::LayerId; +use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct LayerPanelEntry { pub name: String, pub visible: bool, pub layer_type: LayerType, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub enum LayerType { Folder, Shape, @@ -25,7 +26,7 @@ impl fmt::Display for LayerType { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[repr(C)] // TODO - Make Copy when possible pub enum DocumentResponse { diff --git a/core/editor/Cargo.toml b/core/editor/Cargo.toml index d3d9a06b6..9a14cbc57 100644 --- a/core/editor/Cargo.toml +++ b/core/editor/Cargo.toml @@ -12,6 +12,7 @@ license = "Apache-2.0" log = "0.4" bitflags = "1.2.1" thiserror = "1.0.24" +serde = { version = "1.0", features = ["derive"] } [dependencies.document-core] path = "../document" diff --git a/core/editor/src/dispatcher/events.rs b/core/editor/src/dispatcher/events.rs index 2879d95e8..2c4be0607 100644 --- a/core/editor/src/dispatcher/events.rs +++ b/core/editor/src/dispatcher/events.rs @@ -2,6 +2,8 @@ use crate::tools::ToolType; use crate::Color; use bitflags::bitflags; +use serde::{Deserialize, Serialize}; + #[doc(inline)] pub use document_core::DocumentResponse; @@ -29,7 +31,7 @@ pub enum Event { KeyDown(Key), } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[repr(C)] pub enum ToolResponse { SetActiveTool { tool_name: String }, @@ -49,7 +51,7 @@ impl fmt::Display for ToolResponse { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[repr(C)] // TODO - Make Copy when possible pub enum Response {