mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-07 15:55:00 +00:00
Remove blob URL dead code and clean up more frontend code (#2199)
This commit is contained in:
parent
1e62af88cd
commit
9ad6c31483
56 changed files with 107 additions and 247 deletions
|
@ -58,17 +58,7 @@ pub enum FrontendMessage {
|
|||
#[serde(rename = "commitDate")]
|
||||
commit_date: String,
|
||||
},
|
||||
TriggerCopyToClipboardBlobUrl {
|
||||
#[serde(rename = "blobUrl")]
|
||||
blob_url: String,
|
||||
},
|
||||
TriggerDelayedZoomCanvasToFitAll,
|
||||
TriggerDownloadBlobUrl {
|
||||
#[serde(rename = "layerName")]
|
||||
layer_name: String,
|
||||
#[serde(rename = "blobUrl")]
|
||||
blob_url: String,
|
||||
},
|
||||
TriggerDownloadImage {
|
||||
svg: String,
|
||||
name: String,
|
||||
|
@ -99,9 +89,6 @@ pub enum FrontendMessage {
|
|||
TriggerLoadPreferences,
|
||||
TriggerOpenDocument,
|
||||
TriggerPaste,
|
||||
TriggerRevokeBlobUrl {
|
||||
url: String,
|
||||
},
|
||||
TriggerSavePreferences {
|
||||
preferences: PreferencesMessageHandler,
|
||||
},
|
||||
|
@ -294,8 +281,4 @@ pub enum FrontendMessage {
|
|||
layout_target: LayoutTarget,
|
||||
diff: Vec<WidgetDiff>,
|
||||
},
|
||||
UpdateZoomWithScroll {
|
||||
#[serde(rename = "zoomWithScroll")]
|
||||
zoom_with_scroll: bool,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1695,7 +1695,7 @@ impl DocumentMessageHandler {
|
|||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Loads layer resources such as creating the blob URLs for the images and loading all of the fonts in the document.
|
||||
/// Loads all of the fonts in the document.
|
||||
pub fn load_layer_resources(&self, responses: &mut VecDeque<Message>) {
|
||||
let mut fonts = HashSet::new();
|
||||
for (_node_id, node) in self.document_network().recursive_nodes() {
|
||||
|
|
|
@ -304,7 +304,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageData<'_>> for PortfolioMes
|
|||
let () = fut.await;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen(module = "/../frontend/src/wasm-communication/editor.ts")]
|
||||
#[wasm_bindgen(module = "/../frontend/src/editor.ts")]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(js_name = injectImaginatePollServerStatus)]
|
||||
fn inject();
|
||||
|
|
|
@ -96,7 +96,6 @@ impl MessageHandler<PreferencesMessage, ()> for PreferencesMessageHandler {
|
|||
true => MappingVariant::ZoomWithScroll,
|
||||
};
|
||||
responses.add(KeyMappingMessage::ModifyMapping(variant));
|
||||
responses.add(FrontendMessage::UpdateZoomWithScroll { zoom_with_scroll });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount, onDestroy } from "svelte";
|
||||
|
||||
import { type Editor as GraphiteEditor, initWasm, createEditor } from "@graphite/wasm-communication/editor";
|
||||
import { type Editor as GraphiteEditor, initWasm, createEditor } from "@graphite/editor";
|
||||
|
||||
import Editor from "@graphite/components/Editor.svelte";
|
||||
|
||||
|
|
|
@ -26,21 +26,17 @@ _Some state providers, similarly to I/O managers, may subscribe to backend event
|
|||
|
||||
TypeScript files which define and `export` individual helper functions for use elsewhere in the codebase. These files should not persist state outside each function.
|
||||
|
||||
## WASM communication: `wasm-communication/`
|
||||
|
||||
TypeScript files which serve as the JS interface to the WASM bindings for the editor backend.
|
||||
|
||||
### WASM editor: `editor.ts`
|
||||
## WASM editor: `editor.ts`
|
||||
|
||||
Instantiates the WASM and editor backend instances. The function `initWasm()` asynchronously constructs and initializes an instance of the WASM bindings JS module provided by wasm-bindgen/wasm-pack. The function `createEditor()` constructs an instance of the editor backend. In theory there could be multiple editor instances sharing the same WASM module instance. The function returns an object where `raw` is the WASM module, `instance` is the editor, and `subscriptions` is the subscription router (described below).
|
||||
|
||||
`initWasm()` occurs in `main.ts` right before the Svelte application exists, then `createEditor()` is run in `Editor.svelte` during the Svelte app's creation. Similarly to the state providers described above, the editor is given via `setContext()` so other components can get it via `getContext` and call functions on `editor.raw`, `editor.handle`, or `editor.subscriptions`.
|
||||
|
||||
### Message definitions: `messages.ts`
|
||||
## Message definitions: `messages.ts`
|
||||
|
||||
Defines the message formats and data types received from the backend. Since Rust and JS support different styles of data representation, this bridges the gap from Rust into JS land. Messages (and the data contained within) are serialized in Rust by `serde` into JSON, and these definitions are manually kept up-to-date to parallel the message structs and their data types. (However, directives like `#[serde(skip)]` or `#[serde(rename = "someOtherName")]` may cause the TypeScript format to look slightly different from the Rust structs.) These definitions are basically just for the sake of TypeScript to understand the format, although in some cases we may perform data conversion here using translation functions that we can provide.
|
||||
|
||||
### Subscription router: `subscription-router.ts`
|
||||
## Subscription router: `subscription-router.ts`
|
||||
|
||||
Associates messages from the backend with subscribers in the frontend, and routes messages to subscriber callbacks. This module provides a `subscribeJsMessage(messageType, callback)` function which JS code throughout the frontend can call to be registered as the exclusive handler for a chosen message type. This file's other exported function, `handleJsMessage(messageType, messageData, wasm, instance)`, is called in `editor.ts` by the associated editor instance when the backend sends a `FrontendMessage`. When this occurs, the subscription router delivers the message to the subscriber for given `messageType` by executing its registered `callback` function. As an argument to the function, it provides the `messageData` payload transformed into its TypeScript-friendly format defined in `messages.ts`.
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { onMount, onDestroy, setContext } from "svelte";
|
||||
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { createClipboardManager } from "@graphite/io-managers/clipboard";
|
||||
import { createDragManager } from "@graphite/io-managers/drag";
|
||||
import { createHyperlinkManager } from "@graphite/io-managers/hyperlinks";
|
||||
|
@ -15,7 +16,6 @@
|
|||
import { createNodeGraphState } from "@graphite/state-providers/node-graph";
|
||||
import { createPortfolioState } from "@graphite/state-providers/portfolio";
|
||||
import { operatingSystem } from "@graphite/utility-functions/platform";
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
|
||||
import MainWindow from "@graphite/components/window/MainWindow.svelte";
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { onDestroy, createEventDispatcher, getContext } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { HSV, RGB, FillChoice } from "@graphite/messages";
|
||||
import { Color, Gradient } from "@graphite/messages";
|
||||
import { clamp } from "@graphite/utility-functions/math";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import type { HSV, RGB, FillChoice } from "@graphite/wasm-communication/messages";
|
||||
import { Color, Gradient } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import FloatingMenu, { type MenuDirection } from "@graphite/components/layout/FloatingMenu.svelte";
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, tick, onDestroy, onMount } from "svelte";
|
||||
|
||||
import type { MenuListEntry } from "@graphite/wasm-communication/messages";
|
||||
import type { MenuListEntry } from "@graphite/messages";
|
||||
|
||||
import MenuList from "@graphite/components/floating-menus/MenuList.svelte";
|
||||
import FloatingMenu, { type MenuDirection } from "@graphite/components/layout/FloatingMenu.svelte";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, getContext, onMount } from "svelte";
|
||||
|
||||
import type { FrontendNodeType } from "@graphite/messages";
|
||||
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
|
||||
import type { FrontendNodeType } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import TextButton from "@graphite/components/widgets/buttons/TextButton.svelte";
|
||||
import TextInput from "@graphite/components/widgets/inputs/TextInput.svelte";
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { getContext, onMount, tick } from "svelte";
|
||||
|
||||
import type { DocumentState } from "@graphite/state-providers/document";
|
||||
import { textInputCleanup } from "@graphite/utility-functions/keyboard-entry";
|
||||
import { extractPixelData, rasterizeSVGCanvas } from "@graphite/utility-functions/rasterization";
|
||||
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import {
|
||||
type MouseCursorIcon,
|
||||
type XY,
|
||||
|
@ -19,7 +15,11 @@
|
|||
UpdateEyedropperSamplingState,
|
||||
UpdateMouseCursor,
|
||||
isWidgetSpanRow,
|
||||
} from "@graphite/wasm-communication/messages";
|
||||
} from "@graphite/messages";
|
||||
import type { DocumentState } from "@graphite/state-providers/document";
|
||||
import { textInputCleanup } from "@graphite/utility-functions/keyboard-entry";
|
||||
import { extractPixelData, rasterizeSVGCanvas } from "@graphite/utility-functions/rasterization";
|
||||
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
|
||||
|
||||
import EyedropperPreview, { ZOOM_WINDOW_DIMENSIONS } from "@graphite/components/floating-menus/EyedropperPreview.svelte";
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
|
@ -275,17 +275,17 @@
|
|||
// This isn't very clean but it's good enough for now until we need more icons, then we can build something more robust (consider blob URLs)
|
||||
if (cursor === "custom-rotate") {
|
||||
const svg = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20">
|
||||
<path transform="translate(2 2)" fill="black" stroke="black" stroke-width="2px" d="
|
||||
M8,15.2C4,15.2,0.8,12,0.8,8C0.8,4,4,0.8,8,0.8c2,0,3.9,0.8,5.3,2.3l-1,1C11.2,2.9,9.6,2.2,8,2.2C4.8,2.2,2.2,4.8,2.2,8s2.6,5.8,5.8,5.8s5.8-2.6,5.8-5.8h1.4C15.2,12,12,15.2,8,15.2z
|
||||
" />
|
||||
<polygon transform="translate(2 2)" fill="black" stroke="black" stroke-width="2px" points="12.6,0 15.5,5 9.7,5" />
|
||||
<path transform="translate(2 2)" fill="white" d="
|
||||
M8,15.2C4,15.2,0.8,12,0.8,8C0.8,4,4,0.8,8,0.8c2,0,3.9,0.8,5.3,2.3l-1,1C11.2,2.9,9.6,2.2,8,2.2C4.8,2.2,2.2,4.8,2.2,8s2.6,5.8,5.8,5.8s5.8-2.6,5.8-5.8h1.4C15.2,12,12,15.2,8,15.2z
|
||||
" />
|
||||
<polygon transform="translate(2 2)" fill="white" points="12.6,0 15.5,5 9.7,5" />
|
||||
</svg>
|
||||
`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" width="20" height="20">
|
||||
<path transform="translate(2 2)" fill="black" stroke="black" stroke-width="2px" d="
|
||||
M8,15.2C4,15.2,0.8,12,0.8,8C0.8,4,4,0.8,8,0.8c2,0,3.9,0.8,5.3,2.3l-1,1C11.2,2.9,9.6,2.2,8,2.2C4.8,2.2,2.2,4.8,2.2,8s2.6,5.8,5.8,5.8s5.8-2.6,5.8-5.8h1.4C15.2,12,12,15.2,8,15.2z
|
||||
" />
|
||||
<polygon transform="translate(2 2)" fill="black" stroke="black" stroke-width="2px" points="12.6,0 15.5,5 9.7,5" />
|
||||
<path transform="translate(2 2)" fill="white" d="
|
||||
M8,15.2C4,15.2,0.8,12,0.8,8C0.8,4,4,0.8,8,0.8c2,0,3.9,0.8,5.3,2.3l-1,1C11.2,2.9,9.6,2.2,8,2.2C4.8,2.2,2.2,4.8,2.2,8s2.6,5.8,5.8,5.8s5.8-2.6,5.8-5.8h1.4C15.2,12,12,15.2,8,15.2z
|
||||
" />
|
||||
<polygon transform="translate(2 2)" fill="white" points="12.6,0 15.5,5 9.7,5" />
|
||||
</svg>
|
||||
`
|
||||
.split("\n")
|
||||
.map((line) => line.trim())
|
||||
.join("");
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script lang="ts">
|
||||
import { getContext, onMount, tick } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import { beginDraggingElement } from "@graphite/io-managers/drag";
|
||||
import { defaultWidgetLayout, patchWidgetLayout, UpdateDocumentLayerDetails, UpdateDocumentLayerStructureJs, UpdateLayersPanelControlBarLayout } from "@graphite/messages";
|
||||
import type { DataBuffer, LayerPanelEntry } from "@graphite/messages";
|
||||
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
|
||||
import { platformIsMac } from "@graphite/utility-functions/platform";
|
||||
import { extractPixelData } from "@graphite/utility-functions/rasterization";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import { defaultWidgetLayout, patchWidgetLayout, UpdateDocumentLayerDetails, UpdateDocumentLayerStructureJs, UpdateLayersPanelControlBarLayout } from "@graphite/wasm-communication/messages";
|
||||
import type { DataBuffer, LayerPanelEntry } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { getContext, onMount } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import { defaultWidgetLayout, patchWidgetLayout, UpdatePropertyPanelSectionsLayout } from "@graphite/wasm-communication/messages";
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import { defaultWidgetLayout, patchWidgetLayout, UpdatePropertyPanelSectionsLayout } from "@graphite/messages";
|
||||
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
import WidgetLayout from "@graphite/components/widgets/WidgetLayout.svelte";
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
<script lang="ts">
|
||||
import { getContext, onMount, tick } from "svelte";
|
||||
import { cubicInOut } from "svelte/easing";
|
||||
import { fade } from "svelte/transition";
|
||||
|
||||
import { FADE_TRANSITION } from "@graphite/consts";
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { Node } from "@graphite/messages";
|
||||
import type { FrontendNodeWire, FrontendNode, FrontendGraphInput, FrontendGraphOutput, FrontendGraphDataType, WirePath } from "@graphite/messages";
|
||||
import type { NodeGraphState } from "@graphite/state-providers/node-graph";
|
||||
import type { IconName } from "@graphite/utility-functions/icons";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import type { Node } from "@graphite/wasm-communication/messages";
|
||||
import type { FrontendNodeWire, FrontendNode, FrontendGraphInput, FrontendGraphOutput, FrontendGraphDataType, WirePath } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import NodeCatalog from "@graphite/components/floating-menus/NodeCatalog.svelte";
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
|
@ -18,8 +18,10 @@
|
|||
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
|
||||
import Separator from "@graphite/components/widgets/labels/Separator.svelte";
|
||||
import TextLabel from "@graphite/components/widgets/labels/TextLabel.svelte";
|
||||
|
||||
const GRID_COLLAPSE_SPACING = 10;
|
||||
const GRID_SIZE = 24;
|
||||
const FADE_TRANSITION = { duration: 200, easing: cubicInOut };
|
||||
|
||||
const editor = getContext<Editor>("editor");
|
||||
const nodeGraph = getContext<NodeGraphState>("nodeGraph");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { isWidgetSpanColumn, isWidgetSpanRow, isWidgetSection, type WidgetLayout } from "@graphite/wasm-communication/messages";
|
||||
import { isWidgetSpanColumn, isWidgetSpanRow, isWidgetSection, type WidgetLayout } from "@graphite/messages";
|
||||
|
||||
import WidgetSection from "@graphite/components/widgets/WidgetSection.svelte";
|
||||
import WidgetSpan from "@graphite/components/widgets/WidgetSpan.svelte";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import { isWidgetSpanRow, isWidgetSpanColumn, isWidgetSection, type WidgetSection as WidgetSectionFromJsMessages } from "@graphite/wasm-communication/messages";
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import { isWidgetSpanRow, isWidgetSpanColumn, isWidgetSection, type WidgetSection as WidgetSectionFromJsMessages } from "@graphite/messages";
|
||||
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
import IconButton from "@graphite/components/widgets/buttons/IconButton.svelte";
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { Widget, WidgetSpanColumn, WidgetSpanRow } from "@graphite/messages";
|
||||
import { narrowWidgetProps, isWidgetSpanColumn, isWidgetSpanRow } from "@graphite/messages";
|
||||
import { debouncer } from "@graphite/utility-functions/debounce";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import type { Widget, WidgetSpanColumn, WidgetSpanRow } from "@graphite/wasm-communication/messages";
|
||||
import { narrowWidgetProps, isWidgetSpanColumn, isWidgetSpanRow } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import NodeCatalog from "@graphite/components/floating-menus/NodeCatalog.svelte";
|
||||
import BreadcrumbTrailButtons from "@graphite/components/widgets/buttons/BreadcrumbTrailButtons.svelte";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import type { FillChoice } from "@graphite/wasm-communication/messages";
|
||||
import { Color, Gradient } from "@graphite/wasm-communication/messages";
|
||||
import type { FillChoice } from "@graphite/messages";
|
||||
import { Color, Gradient } from "@graphite/messages";
|
||||
|
||||
import ColorPicker from "@graphite/components/floating-menus/ColorPicker.svelte";
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { FrontendGraphDataType } from "@graphite/wasm-communication/messages";
|
||||
import type { FrontendGraphDataType } from "@graphite/messages";
|
||||
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts">
|
||||
import type { MenuListEntry } from "@graphite/messages";
|
||||
import type { IconName } from "@graphite/utility-functions/icons";
|
||||
import type { MenuListEntry } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import MenuList from "@graphite/components/floating-menus/MenuList.svelte";
|
||||
import ConditionalWrapper from "@graphite/components/layout/ConditionalWrapper.svelte";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import type { Curve, CurveManipulatorGroup } from "@graphite/messages";
|
||||
import { clamp } from "@graphite/utility-functions/math";
|
||||
import type { Curve, CurveManipulatorGroup } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import type { MenuListEntry } from "@graphite/wasm-communication/messages";
|
||||
import type { MenuListEntry } from "@graphite/messages";
|
||||
|
||||
import MenuList from "@graphite/components/floating-menus/MenuList.svelte";
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, getContext, onMount, tick } from "svelte";
|
||||
|
||||
import type { MenuListEntry } from "@graphite/messages";
|
||||
import type { FontsState } from "@graphite/state-providers/fonts";
|
||||
import type { MenuListEntry } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import MenuList from "@graphite/components/floating-menus/MenuList.svelte";
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount, onDestroy } from "svelte";
|
||||
|
||||
import { type NumberInputMode, type NumberInputIncrementBehavior } from "@graphite/wasm-communication/messages";
|
||||
import { type NumberInputMode, type NumberInputIncrementBehavior } from "@graphite/messages";
|
||||
import { evaluateMathExpression } from "@graphite-frontend/wasm/pkg/graphite_wasm.js";
|
||||
|
||||
import FieldInput from "@graphite/components/widgets/inputs/FieldInput.svelte";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import type { PivotPosition } from "@graphite/wasm-communication/messages";
|
||||
import type { PivotPosition } from "@graphite/messages";
|
||||
|
||||
const dispatch = createEventDispatcher<{ position: PivotPosition }>();
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
|
||||
import { type RadioEntries, type RadioEntryData } from "@graphite/wasm-communication/messages";
|
||||
import { type RadioEntries, type RadioEntryData } from "@graphite/messages";
|
||||
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { createEventDispatcher, onDestroy } from "svelte";
|
||||
|
||||
import { Color, type Gradient } from "@graphite/wasm-communication/messages";
|
||||
import { Color, type Gradient } from "@graphite/messages";
|
||||
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import { Color } from "@graphite/wasm-communication/messages";
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import { Color } from "@graphite/messages";
|
||||
|
||||
import ColorPicker from "@graphite/components/floating-menus/ColorPicker.svelte";
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script lang="ts">
|
||||
import { type SeparatorDirection, type SeparatorType } from "@graphite/wasm-communication/messages";
|
||||
import { type SeparatorDirection, type SeparatorType } from "@graphite/messages";
|
||||
|
||||
export let direction: SeparatorDirection = "Horizontal";
|
||||
export let type: SeparatorType = "Unrelated";
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import { type KeyRaw, type LayoutKeysGroup, type Key, type MouseMotion } from "@graphite/messages";
|
||||
import type { FullscreenState } from "@graphite/state-providers/fullscreen";
|
||||
import type { IconName } from "@graphite/utility-functions/icons";
|
||||
import { platformIsMac } from "@graphite/utility-functions/platform";
|
||||
import { type KeyRaw, type LayoutKeysGroup, type Key, type MouseMotion } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
import IconLabel from "@graphite/components/widgets/labels/IconLabel.svelte";
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<script lang="ts">
|
||||
import { getContext, onMount } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import { type HintData, type HintInfo, type LayoutKeysGroup, UpdateInputHints } from "@graphite/messages";
|
||||
import { platformIsMac } from "@graphite/utility-functions/platform";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import { type HintData, type HintInfo, type LayoutKeysGroup, UpdateInputHints } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
import Separator from "@graphite/components/widgets/labels/Separator.svelte";
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
<script lang="ts">
|
||||
import { getContext, onMount } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import { type KeyRaw, type LayoutKeysGroup, type MenuBarEntry, type MenuListEntry, UpdateMenuBarLayout } from "@graphite/messages";
|
||||
import type { PortfolioState } from "@graphite/state-providers/portfolio";
|
||||
import { platformIsMac } from "@graphite/utility-functions/platform";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import { type KeyRaw, type LayoutKeysGroup, type MenuBarEntry, type MenuListEntry, UpdateMenuBarLayout } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
import TextButton from "@graphite/components/widgets/buttons/TextButton.svelte";
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
<script lang="ts">
|
||||
import { getContext, tick } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import { type LayoutKeysGroup, type Key } from "@graphite/messages";
|
||||
import { platformIsMac, isEventSupported } from "@graphite/utility-functions/platform";
|
||||
|
||||
import { extractPixelData } from "@graphite/utility-functions/rasterization";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
import { type LayoutKeysGroup, type Key } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
import LayoutRow from "@graphite/components/layout/LayoutRow.svelte";
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
<script lang="ts">
|
||||
import { getContext } from "svelte";
|
||||
|
||||
import type { Editor } from "@graphite/editor";
|
||||
import type { FrontendDocumentDetails } from "@graphite/messages";
|
||||
import type { DialogState } from "@graphite/state-providers/dialog";
|
||||
import type { PortfolioState } from "@graphite/state-providers/portfolio";
|
||||
import type { Editor } from "@graphite/wasm-communication/editor";
|
||||
|
||||
import type { FrontendDocumentDetails } from "@graphite/wasm-communication/messages";
|
||||
|
||||
import Dialog from "@graphite/components/floating-menus/Dialog.svelte";
|
||||
import LayoutCol from "@graphite/components/layout/LayoutCol.svelte";
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
import { cubicInOut } from "svelte/easing";
|
||||
export const FADE_TRANSITION = { duration: 200, easing: cubicInOut };
|
|
@ -1,6 +1,6 @@
|
|||
// import { panicProxy } from "@graphite/utility-functions/panic-proxy";
|
||||
import { type JsMessageType } from "@graphite/wasm-communication/messages";
|
||||
import { createSubscriptionRouter, type SubscriptionRouter } from "@graphite/wasm-communication/subscription-router";
|
||||
import { type JsMessageType } from "@graphite/messages";
|
||||
import { createSubscriptionRouter, type SubscriptionRouter } from "@graphite/subscription-router";
|
||||
import init, { setRandomSeed, wasmMemory, EditorHandle } from "@graphite-frontend/wasm/pkg/graphite_wasm.js";
|
||||
|
||||
export type Editor = {
|
||||
|
@ -47,7 +47,6 @@ export function createEditor(): Editor {
|
|||
subscriptions.handleJsMessage(messageType, messageData, raw, handle);
|
||||
});
|
||||
|
||||
// TODO: Remove?
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).editorHandle = handle;
|
||||
|
||||
|
@ -78,6 +77,10 @@ export function createEditor(): Editor {
|
|||
return { raw, handle, subscriptions };
|
||||
}
|
||||
|
||||
// TODO: Find a better way to do this, since no other code takes this approach.
|
||||
// TODO: Then, delete the `(window as any).editorHandle = handle;` line above.
|
||||
// This function is called by an FFI binding within the Rust code directly, rather than using the FrontendMessage system.
|
||||
// Then, this directly calls the `injectImaginatePollServerStatus` function on the `EditorHandle` object which is a JS binding generated by wasm-bindgen, going straight back into the Rust code.
|
||||
export function injectImaginatePollServerStatus() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(window as any).editorHandle?.injectImaginatePollServerStatus();
|
|
@ -1,6 +1,5 @@
|
|||
import { imageToPNG } from "@graphite/utility-functions/rasterization";
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { TriggerTextCopy } from "@graphite/wasm-communication/messages";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { TriggerTextCopy } from "@graphite/messages";
|
||||
|
||||
export function createClipboardManager(editor: Editor) {
|
||||
// Subscribe to process backend event
|
||||
|
@ -9,20 +8,3 @@ export function createClipboardManager(editor: Editor) {
|
|||
navigator.clipboard?.writeText?.(triggerTextCopy.copyText);
|
||||
});
|
||||
}
|
||||
|
||||
export async function copyToClipboardFileURL(url: string) {
|
||||
const response = await fetch(url);
|
||||
const blob = await response.blob();
|
||||
|
||||
// TODO: Remove this if/when we end up returning PNG directly from the backend
|
||||
const pngBlob = await imageToPNG(blob);
|
||||
|
||||
const clipboardItem: Record<string, Blob> = {};
|
||||
clipboardItem[pngBlob.type] = pngBlob;
|
||||
const data = [new ClipboardItem(clipboardItem)];
|
||||
|
||||
// Note: if this image has transparency, it will be lost and appear as black due to limitations of the way browsers handle copying transparent images
|
||||
// This even happens if you just open a regular transparent PNG file in a browser tab, right click > copy, and paste it somewhere (the transparency will show up as black)
|
||||
// This is true, at least, on Windows (it's worth checking on other OSs though)
|
||||
navigator.clipboard.write(data);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { TriggerVisitLink } from "@graphite/wasm-communication/messages";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { TriggerVisitLink } from "@graphite/messages";
|
||||
|
||||
export function createHyperlinkManager(editor: Editor) {
|
||||
// Subscribe to process backend event
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { get } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { TriggerPaste } from "@graphite/messages";
|
||||
import { type DialogState } from "@graphite/state-providers/dialog";
|
||||
import { type DocumentState } from "@graphite/state-providers/document";
|
||||
import { type FullscreenState } from "@graphite/state-providers/fullscreen";
|
||||
|
@ -9,8 +11,6 @@ import { platformIsMac } from "@graphite/utility-functions/platform";
|
|||
import { extractPixelData } from "@graphite/utility-functions/rasterization";
|
||||
import { stripIndents } from "@graphite/utility-functions/strip-indents";
|
||||
import { updateBoundsOfViewports } from "@graphite/utility-functions/viewports";
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { TriggerPaste } from "@graphite/wasm-communication/messages";
|
||||
|
||||
type EventName = keyof HTMLElementEventMap | keyof WindowEventHandlersEventMap | "modifyinputfield";
|
||||
type EventListenerTarget = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { TriggerAboutGraphiteLocalizedCommitDate } from "@graphite/wasm-communication/messages";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { TriggerAboutGraphiteLocalizedCommitDate } from "@graphite/messages";
|
||||
|
||||
export function createLocalizationManager(editor: Editor) {
|
||||
// Subscribe to process backend event
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { type Editor } from "@graphite/editor";
|
||||
import { DisplayDialogPanic } from "@graphite/messages";
|
||||
import { type DialogState } from "@graphite/state-providers/dialog";
|
||||
import { browserVersion, operatingSystem } from "@graphite/utility-functions/platform";
|
||||
import { stripIndents } from "@graphite/utility-functions/strip-indents";
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { DisplayDialogPanic } from "@graphite/wasm-communication/messages";
|
||||
|
||||
export function createPanicManager(editor: Editor, dialogState: DialogState) {
|
||||
// Code panic dialog and console error
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { createStore, del, get, set, update } from "idb-keyval";
|
||||
import { get as getFromStore } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { TriggerIndexedDbWriteDocument, TriggerIndexedDbRemoveDocument, TriggerSavePreferences, TriggerLoadAutoSaveDocuments, TriggerLoadPreferences } from "@graphite/messages";
|
||||
import { type PortfolioState } from "@graphite/state-providers/portfolio";
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { TriggerIndexedDbWriteDocument, TriggerIndexedDbRemoveDocument, TriggerSavePreferences, TriggerLoadAutoSaveDocuments, TriggerLoadPreferences } from "@graphite/wasm-communication/messages";
|
||||
|
||||
const graphiteStore = createStore("graphite", "store");
|
||||
|
||||
|
|
|
@ -130,10 +130,6 @@ export class UpdateWirePathInProgress extends JsMessage {
|
|||
readonly wirePath!: WirePath | undefined;
|
||||
}
|
||||
|
||||
export class UpdateZoomWithScroll extends JsMessage {
|
||||
readonly zoomWithScroll!: boolean;
|
||||
}
|
||||
|
||||
// Allows the auto save system to use a string for the id rather than a BigInt.
|
||||
// IndexedDb does not allow for BigInts as primary keys.
|
||||
// TypeScript does not allow subclasses to change the type of class variables in subclasses.
|
||||
|
@ -777,18 +773,8 @@ export class TriggerImport extends JsMessage {}
|
|||
|
||||
export class TriggerPaste extends JsMessage {}
|
||||
|
||||
export class TriggerCopyToClipboardBlobUrl extends JsMessage {
|
||||
readonly blobUrl!: string;
|
||||
}
|
||||
|
||||
export class TriggerDelayedZoomCanvasToFitAll extends JsMessage {}
|
||||
|
||||
export class TriggerDownloadBlobUrl extends JsMessage {
|
||||
readonly layerName!: string;
|
||||
|
||||
readonly blobUrl!: string;
|
||||
}
|
||||
|
||||
export class TriggerDownloadImage extends JsMessage {
|
||||
readonly svg!: string;
|
||||
|
||||
|
@ -806,10 +792,6 @@ export class TriggerDownloadTextFile extends JsMessage {
|
|||
readonly name!: string;
|
||||
}
|
||||
|
||||
export class TriggerRevokeBlobUrl extends JsMessage {
|
||||
readonly url!: string;
|
||||
}
|
||||
|
||||
export class TriggerSavePreferences extends JsMessage {
|
||||
readonly preferences!: Record<string, unknown>;
|
||||
}
|
||||
|
@ -1573,9 +1555,7 @@ export const messageMakers: Record<string, MessageMaker> = {
|
|||
DisplayRemoveEditableTextbox,
|
||||
SendUIMetadata,
|
||||
TriggerAboutGraphiteLocalizedCommitDate,
|
||||
TriggerCopyToClipboardBlobUrl,
|
||||
TriggerDelayedZoomCanvasToFitAll,
|
||||
TriggerDownloadBlobUrl,
|
||||
TriggerDownloadImage,
|
||||
TriggerDownloadTextFile,
|
||||
TriggerFetchAndOpenDocument,
|
||||
|
@ -1587,7 +1567,6 @@ export const messageMakers: Record<string, MessageMaker> = {
|
|||
TriggerLoadPreferences,
|
||||
TriggerOpenDocument,
|
||||
TriggerPaste,
|
||||
TriggerRevokeBlobUrl,
|
||||
TriggerSavePreferences,
|
||||
TriggerTextCommit,
|
||||
TriggerTextCopy,
|
||||
|
@ -1628,6 +1607,5 @@ export const messageMakers: Record<string, MessageMaker> = {
|
|||
UpdateToolShelfLayout,
|
||||
UpdateWirePathInProgress,
|
||||
UpdateWorkingColorsLayout,
|
||||
UpdateZoomWithScroll,
|
||||
} as const;
|
||||
export type JsMessageType = keyof typeof messageMakers;
|
|
@ -1,8 +1,8 @@
|
|||
import { writable } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { defaultWidgetLayout, DisplayDialog, DisplayDialogDismiss, UpdateDialogButtons, UpdateDialogColumn1, UpdateDialogColumn2, patchWidgetLayout } from "@graphite/messages";
|
||||
import { type IconName } from "@graphite/utility-functions/icons";
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { defaultWidgetLayout, DisplayDialog, DisplayDialogDismiss, UpdateDialogButtons, UpdateDialogColumn1, UpdateDialogColumn2, patchWidgetLayout } from "@graphite/wasm-communication/messages";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function createDialogState(editor: Editor) {
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { tick } from "svelte";
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
|
||||
import {
|
||||
defaultWidgetLayout,
|
||||
patchWidgetLayout,
|
||||
|
@ -14,7 +15,7 @@ import {
|
|||
UpdateGraphViewOverlay,
|
||||
TriggerDelayedZoomCanvasToFitAll,
|
||||
UpdateGraphFadeArtwork,
|
||||
} from "@graphite/wasm-communication/messages";
|
||||
} from "@graphite/messages";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function createDocumentState(editor: Editor) {
|
||||
|
@ -43,7 +44,6 @@ export function createDocumentState(editor: Editor) {
|
|||
await tick();
|
||||
|
||||
update((state) => {
|
||||
// `state.documentModeLayout` is mutated in the function
|
||||
patchWidgetLayout(state.documentModeLayout, updateDocumentModeLayout);
|
||||
return state;
|
||||
});
|
||||
|
@ -52,7 +52,6 @@ export function createDocumentState(editor: Editor) {
|
|||
await tick();
|
||||
|
||||
update((state) => {
|
||||
// `state.documentModeLayout` is mutated in the function
|
||||
patchWidgetLayout(state.toolOptionsLayout, updateToolOptionsLayout);
|
||||
return state;
|
||||
});
|
||||
|
@ -61,7 +60,6 @@ export function createDocumentState(editor: Editor) {
|
|||
await tick();
|
||||
|
||||
update((state) => {
|
||||
// `state.documentModeLayout` is mutated in the function
|
||||
patchWidgetLayout(state.documentBarLayout, updateDocumentBarLayout);
|
||||
return state;
|
||||
});
|
||||
|
@ -70,7 +68,6 @@ export function createDocumentState(editor: Editor) {
|
|||
await tick();
|
||||
|
||||
update((state) => {
|
||||
// `state.documentModeLayout` is mutated in the function
|
||||
patchWidgetLayout(state.toolShelfLayout, updateToolShelfLayout);
|
||||
return state;
|
||||
});
|
||||
|
@ -79,7 +76,6 @@ export function createDocumentState(editor: Editor) {
|
|||
await tick();
|
||||
|
||||
update((state) => {
|
||||
// `state.documentModeLayout` is mutated in the function
|
||||
patchWidgetLayout(state.workingColorsLayout, updateWorkingColorsLayout);
|
||||
return state;
|
||||
});
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { writable } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { TriggerFontLoad } from "@graphite/wasm-communication/messages";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import { TriggerFontLoad } from "@graphite/messages";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function createFontsState(editor: Editor) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { writable } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function createFullscreenState(_: Editor) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { writable } from "svelte/store";
|
||||
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import type { FrontendGraphOutput, FrontendGraphInput } from "@graphite/wasm-communication/messages";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import type { FrontendGraphOutput, FrontendGraphInput } from "@graphite/messages";
|
||||
import {
|
||||
type Box,
|
||||
type FrontendClickTargets,
|
||||
|
@ -22,8 +22,7 @@ import {
|
|||
UpdateNodeGraphTransform,
|
||||
UpdateNodeThumbnail,
|
||||
UpdateWirePathInProgress,
|
||||
UpdateZoomWithScroll,
|
||||
} from "@graphite/wasm-communication/messages";
|
||||
} from "@graphite/messages";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function createNodeGraphState(editor: Editor) {
|
||||
|
@ -44,7 +43,6 @@ export function createNodeGraphState(editor: Editor) {
|
|||
inputTypeDescriptions: new Map<string, string>(),
|
||||
nodeDescriptions: new Map<string, string>(),
|
||||
nodeTypes: [] as FrontendNodeType[],
|
||||
zoomWithScroll: false as boolean,
|
||||
thumbnails: new Map<bigint, string>(),
|
||||
selected: [] as bigint[],
|
||||
transform: { scale: 1, x: 0, y: 0 },
|
||||
|
@ -136,12 +134,6 @@ export function createNodeGraphState(editor: Editor) {
|
|||
return state;
|
||||
});
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(UpdateZoomWithScroll, (updateZoomWithScroll) => {
|
||||
update((state) => {
|
||||
state.zoomWithScroll = updateZoomWithScroll.zoomWithScroll;
|
||||
return state;
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
|
|
|
@ -2,24 +2,20 @@
|
|||
|
||||
import { writable } from "svelte/store";
|
||||
|
||||
import { copyToClipboardFileURL } from "@graphite/io-managers/clipboard";
|
||||
import { downloadFileText, downloadFileBlob, upload } from "@graphite/utility-functions/files";
|
||||
import { extractPixelData, imageToPNG, rasterizeSVG } from "@graphite/utility-functions/rasterization";
|
||||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
import {
|
||||
type FrontendDocumentDetails,
|
||||
TriggerCopyToClipboardBlobUrl,
|
||||
TriggerFetchAndOpenDocument,
|
||||
TriggerDownloadBlobUrl,
|
||||
TriggerDownloadImage,
|
||||
TriggerDownloadTextFile,
|
||||
TriggerImport,
|
||||
TriggerOpenDocument,
|
||||
TriggerRevokeBlobUrl,
|
||||
TriggerUpgradeDocumentToVectorManipulationFormat,
|
||||
UpdateActiveDocument,
|
||||
UpdateOpenDocumentsList,
|
||||
} from "@graphite/wasm-communication/messages";
|
||||
} from "@graphite/messages";
|
||||
import { downloadFileText, downloadFileBlob, upload } from "@graphite/utility-functions/files";
|
||||
import { extractPixelData, rasterizeSVG } from "@graphite/utility-functions/rasterization";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function createPortfolioState(editor: Editor) {
|
||||
|
@ -85,18 +81,6 @@ export function createPortfolioState(editor: Editor) {
|
|||
editor.subscriptions.subscribeJsMessage(TriggerDownloadTextFile, (triggerFileDownload) => {
|
||||
downloadFileText(triggerFileDownload.name, triggerFileDownload.document);
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(TriggerDownloadBlobUrl, async (triggerDownloadBlobUrl) => {
|
||||
const data = await fetch(triggerDownloadBlobUrl.blobUrl);
|
||||
const blob = await data.blob();
|
||||
|
||||
// TODO: Remove this if/when we end up returning PNG directly from the backend
|
||||
const pngBlob = await imageToPNG(blob);
|
||||
|
||||
downloadFileBlob(triggerDownloadBlobUrl.layerName, pngBlob);
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(TriggerCopyToClipboardBlobUrl, (triggerDownloadBlobUrl) => {
|
||||
copyToClipboardFileURL(triggerDownloadBlobUrl.blobUrl);
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(TriggerDownloadImage, async (triggerDownloadImage) => {
|
||||
const { svg, name, mime, size } = triggerDownloadImage;
|
||||
|
||||
|
@ -113,9 +97,6 @@ export function createPortfolioState(editor: Editor) {
|
|||
// Fail silently if there's an error rasterizing the SVG, such as a zero-sized image
|
||||
}
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(TriggerRevokeBlobUrl, async (triggerRevokeBlobUrl) => {
|
||||
URL.revokeObjectURL(triggerRevokeBlobUrl.url);
|
||||
});
|
||||
editor.subscriptions.subscribeJsMessage(TriggerUpgradeDocumentToVectorManipulationFormat, async (triggerUpgradeDocumentToVectorManipulationFormat) => {
|
||||
// TODO: Eventually remove this document upgrade code
|
||||
const { documentId, documentName, documentIsAutoSaved, documentIsSaved, documentSerializedContent } = triggerUpgradeDocumentToVectorManipulationFormat;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { plainToInstance } from "class-transformer";
|
||||
|
||||
import { type JsMessageType, messageMakers, type JsMessage } from "@graphite/wasm-communication/messages";
|
||||
import { type JsMessageType, messageMakers, type JsMessage } from "@graphite/messages";
|
||||
import { type EditorHandle } from "@graphite-frontend/wasm/pkg/graphite_wasm.js";
|
||||
|
||||
type JsMessageCallback<T extends JsMessage> = (messageData: T) => void;
|
|
@ -59,32 +59,3 @@ export async function upload<T extends "text" | "data" | "both">(acceptedExtensi
|
|||
}
|
||||
export type UploadResult<T> = { filename: string; type: string; content: UploadResultType<T> };
|
||||
type UploadResultType<T> = T extends "text" ? string : T extends "data" ? Uint8Array : T extends "both" ? { text: string; data: Uint8Array } : never;
|
||||
|
||||
export function blobToBase64(blob: Blob): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
const reader = new FileReader();
|
||||
reader.onloadend = () => resolve(typeof reader.result === "string" ? reader.result : "");
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
}
|
||||
|
||||
export async function replaceBlobURLsWithBase64(svg: string): Promise<string> {
|
||||
const splitByBlobs = svg.split(/("blob:.*?")/);
|
||||
const onlyBlobs = splitByBlobs.filter((_, i) => i % 2 === 1);
|
||||
|
||||
const onlyBlobsConverted = onlyBlobs.map(async (blobURL) => {
|
||||
const urlWithoutQuotes = blobURL.slice(1, -1);
|
||||
const data = await fetch(urlWithoutQuotes);
|
||||
const dataBlob = await data.blob();
|
||||
return blobToBase64(dataBlob);
|
||||
});
|
||||
const base64Images = await Promise.all(onlyBlobsConverted);
|
||||
|
||||
const substituted = splitByBlobs.map((segment, i) => {
|
||||
if (i % 2 === 0) return segment;
|
||||
|
||||
const blobsIndex = Math.floor(i / 2);
|
||||
return `"${base64Images[blobsIndex]}"`;
|
||||
});
|
||||
return substituted.join("");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { replaceBlobURLsWithBase64 } from "@graphite/utility-functions/files";
|
||||
|
||||
// Rasterize the string of an SVG document at a given width and height and return the canvas it was drawn onto during the rasterization process
|
||||
export async function rasterizeSVGCanvas(svg: string, width: number, height: number, backgroundColor?: string): Promise<HTMLCanvasElement> {
|
||||
// A canvas to render our SVG to in order to get a raster image
|
||||
|
@ -15,11 +13,8 @@ export async function rasterizeSVGCanvas(svg: string, width: number, height: num
|
|||
context.fillRect(0, 0, width, height);
|
||||
}
|
||||
|
||||
// This SVG rasterization scheme has the limitation that it cannot access blob URLs, so they must be inlined to base64 URLs
|
||||
const svgWithBase64Images = await replaceBlobURLsWithBase64(svg);
|
||||
|
||||
// Create a blob URL for our SVG
|
||||
const svgBlob = new Blob([svgWithBase64Images], { type: "image/svg+xml;charset=utf-8" });
|
||||
const svgBlob = new Blob([svg], { type: "image/svg+xml;charset=utf-8" });
|
||||
const url = URL.createObjectURL(svgBlob);
|
||||
|
||||
// Load the Image from the URL and wait until it's done
|
||||
|
@ -65,18 +60,6 @@ export async function extractPixelData(imageData: ImageBitmapSource): Promise<Im
|
|||
return canvasContext.getImageData(0, 0, width, height);
|
||||
}
|
||||
|
||||
/// Convert an image source (e.g. BMP document) into a PNG blob
|
||||
export async function imageToPNG(imageData: ImageBitmapSource): Promise<Blob> {
|
||||
const canvasContext = await imageToCanvasContext(imageData);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
canvasContext.canvas.toBlob((pngBlob) => {
|
||||
if (pngBlob) resolve(pngBlob);
|
||||
else reject("Converting canvas to blob data failed in imageToPNG()");
|
||||
}, "image/png");
|
||||
});
|
||||
}
|
||||
|
||||
export async function imageToCanvasContext(imageData: ImageBitmapSource): Promise<CanvasRenderingContext2D> {
|
||||
// Special handling to rasterize an SVG file
|
||||
let svgImageData;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { type Editor } from "@graphite/wasm-communication/editor";
|
||||
import { type Editor } from "@graphite/editor";
|
||||
|
||||
export function updateBoundsOfViewports(editor: Editor, container: HTMLElement) {
|
||||
const viewports = Array.from(container.querySelectorAll("[data-viewport]"));
|
||||
|
|
|
@ -28,7 +28,7 @@ use wasm_bindgen::prelude::*;
|
|||
|
||||
// /// We directly interface with the updateImage JS function for massively increased performance over serializing and deserializing.
|
||||
// /// This avoids creating a json with a list millions of numbers long.
|
||||
// #[wasm_bindgen(module = "/../src/wasm-communication/editor.ts")]
|
||||
// #[wasm_bindgen(module = "/../src/editor.ts")]
|
||||
// extern "C" {
|
||||
// // fn dispatchTauri(message: String) -> String;
|
||||
// fn dispatchTauri(message: String);
|
||||
|
|
|
@ -1063,12 +1063,10 @@ impl GraphicElementRendered for Vec<Color> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A segment of an svg string to allow for embedding blob urls
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum SvgSegment {
|
||||
Slice(&'static str),
|
||||
String(String),
|
||||
BlobUrl(u64),
|
||||
}
|
||||
|
||||
impl From<String> for SvgSegment {
|
||||
|
@ -1094,7 +1092,6 @@ impl RenderSvgSegmentList for Vec<SvgSegment> {
|
|||
result.push_str(match segment {
|
||||
SvgSegment::Slice(x) => x,
|
||||
SvgSegment::String(x) => x,
|
||||
SvgSegment::BlobUrl(_) => "<!-- Blob url not yet loaded -->",
|
||||
});
|
||||
}
|
||||
result
|
||||
|
|
|
@ -52,7 +52,7 @@ The editor is the core of the Graphite application, and it's where all the busin
|
|||
|
||||
Frontend-to-backend communication is achieved through a thin Rust translation layer in `/frontend/wasm/src/editor_api.rs` which wraps the editor backend's Rust-based message system API and provides the TypeScript-compatible API of callable functions. These wrapper functions are compiled by [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen) into autogenerated TS functions that serve as an entry point from TS into the Wasm binary.
|
||||
|
||||
Backend-to-frontend communication happens by sending a queue of messages to the frontend message dispatcher. After the TS has called any wrapper API function to get into backend code execution, the editor's business logic runs and queues up `FrontendMessage`s (defined in `/editor/src/messages/frontend/frontend_message.rs`) which get mapped from Rust to TS-friendly data types in `/frontend/src/wasm-communication/messages.ts`. Various TS code subscribes to these messages by calling `subscribeJsMessage(MessageName, (messageData) => { /* callback code */ });`.
|
||||
Backend-to-frontend communication happens by sending a queue of messages to the frontend message dispatcher. After the TS has called any wrapper API function to get into backend code execution, the editor's business logic runs and queues up `FrontendMessage`s (defined in `/editor/src/messages/frontend/frontend_message.rs`) which get mapped from Rust to TS-friendly data types in `/frontend/src/messages.ts`. Various TS code subscribes to these messages by calling `subscribeJsMessage(MessageName, (messageData) => { /* callback code */ });`.
|
||||
|
||||
## The message system
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue