Rework wasm initialization and reduce global state (#379)

* wasm: do the async initialization only once

This allows the rest of the app to access wasm synchronously.

This allows removing of a global.

* provide the wasm via vue provide/inject.

There's still code directly accessing the wasm. That will be changed later.

* MenuBarInput: use injected wasm instead of the global instance

* Let the App handle event listeners

* move stateful modules into state/

* state/fullscreen: create per instance

* App: load the initial document list on mount.
This got lost a few commits ago. Now it's back.

* state/dialog: create per instance

* util/input: remove dependency on global dialog instance

* state/documents: create per instance

* reponse-handler: move into EditorWasm

* comingSoon: move into dialog

* wasm: allow instantiating multiple editors

* input handlers: do not look at canvases outside the mounted App

* input: listen on the container instead of the window when possible

* - removed proxy from wasm-loader
- integrated with js-dispatcher
- state functions to classes
- integrated some upstream changes

* fix errors caused by merge

* Getting closer:
- added global state to track all instances
- fix fullscreen close trigger
- wasm-loader is statefull
- panic across instanes

* - fix outline while using editor
- removed circular import rule
- added editorInstance to js message constructor

* - changed input handler to a class
- still need a better way of handeling it in App.vue

* - fixed single instance of inputManager to weakmap

* - fix no-explicit-any in a few places
- removed global state from input.ts

* simplified two long lines

* removed global state

* removed $data from App

* add mut self to functions in api.rs

* Update Workspace.vue

remove outdated import

* fixed missing import

* Changes throughout code review; note this causes some bugs to be fixed in a later commit

* PR review round 1

* - fix coming soon bugs
- changed folder structure

* moved declaration to .d.ts

* - changed from classes to functions
- moved decs back to app.vue

* removed need to export js function to rust

* changed folder structure

* fixed indentation breaking multiline strings

* Fix eslint rule to whitelist @/../

* Simplify strip-indents implementation

* replace type assertions with better annotations or proper runtime checks

* Small tweaks and code rearranging improvements after second code review pass

* maybe fix mouse events

* Add back preventDefault for mouse scroll

* code review round 2

* Comment improvements

* -removed runtime checks
- fixed layers not showing

* - extened proxy to cover classes
- stopped multiple panics from logging
- Stop wasm-bindgen from mut ref counting our struct

* cleaned up messageConstructors exports

* Fix input and fullscreen regressions

Co-authored-by: Max Fisher <maxmfishernj@gmail.com>
Co-authored-by: mfish33 <32677537+mfish33@users.noreply.github.com>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Christian Authmann
2021-12-19 22:37:19 -08:00
committed by GitHub
co-authored by Max Fisher mfish33 Keavon Chambers
parent 37be856884
commit 448e72fe02
39 changed files with 1524 additions and 1412 deletions
+10 -13
View File
@@ -197,9 +197,7 @@
<script lang="ts">
import { defineComponent } from "vue";
import { subscribeJsMessage } from "@/utilities/js-message-dispatcher";
import { BlendMode, DisplayFolderTreeStructure, UpdateLayer, LayerPanelEntry, LayerTypeOptions } from "@/utilities/js-messages";
import { panicProxy } from "@/utilities/panic-proxy";
import { BlendMode, DisplayFolderTreeStructure, UpdateLayer, LayerPanelEntry, LayerTypeOptions } from "@/dispatcher/js-messages";
import { SeparatorType } from "@/components/widgets/widgets";
import LayoutRow from "@/components/layout/LayoutRow.vue";
@@ -213,8 +211,6 @@ import IconLabel from "@/components/widgets/labels/IconLabel.vue";
import DropdownInput from "@/components/widgets/inputs/DropdownInput.vue";
import { SectionsOfMenuListEntries } from "@/components/widgets/floating-menus/MenuList.vue";
const wasm = import("@/../wasm/pkg").then(panicProxy);
const blendModeEntries: SectionsOfMenuListEntries<BlendMode> = [
[{ label: "Normal", value: "Normal" }],
[
@@ -255,6 +251,7 @@ const blendModeEntries: SectionsOfMenuListEntries<BlendMode> = [
];
export default defineComponent({
inject: ["editor"],
data() {
return {
blendModeEntries,
@@ -278,19 +275,19 @@ export default defineComponent({
return `${(layer.path.length - 1) * 16}px`;
},
async toggleLayerVisibility(path: BigUint64Array) {
(await wasm).toggle_layer_visibility(path);
this.editor.instance.toggle_layer_visibility(path);
},
async handleNodeConnectorClick(path: BigUint64Array) {
(await wasm).toggle_layer_expansion(path);
this.editor.instance.toggle_layer_expansion(path);
},
async setLayerBlendMode() {
const blendMode = this.blendModeEntries.flat()[this.blendModeSelectedIndex].value;
if (blendMode) {
(await wasm).set_blend_mode_for_selected_layers(blendMode);
this.editor.instance.set_blend_mode_for_selected_layers(blendMode);
}
},
async setLayerOpacity() {
(await wasm).set_opacity_for_selected_layers(this.opacity);
this.editor.instance.set_opacity_for_selected_layers(this.opacity);
},
async handleControlClick(clickedLayer: LayerPanelEntry) {
const index = this.layers.indexOf(clickedLayer);
@@ -330,7 +327,7 @@ export default defineComponent({
this.selectionRangeStartLayer = undefined;
this.selectionRangeEndLayer = undefined;
(await wasm).deselect_all_layers();
this.editor.instance.deselect_all_layers();
},
async fillSelectionRange(start: LayerPanelEntry, end: LayerPanelEntry, selected = true) {
const startIndex = this.layers.findIndex((layer) => layer.path.join() === start.path.join());
@@ -363,7 +360,7 @@ export default defineComponent({
}
i += 1;
});
(await wasm).select_layers(output);
this.editor.instance.select_layers(output);
},
setBlendModeForSelectedLayers() {
const selected = this.layers.filter((layer) => layer.layer_data.selected);
@@ -407,7 +404,7 @@ export default defineComponent({
},
},
mounted() {
subscribeJsMessage(DisplayFolderTreeStructure, (displayFolderTreeStructure) => {
this.editor.dispatcher.subscribeJsMessage(DisplayFolderTreeStructure, (displayFolderTreeStructure) => {
const path = [] as bigint[];
this.layers = [] as LayerPanelEntry[];
function recurse(folder: DisplayFolderTreeStructure, layers: LayerPanelEntry[], cache: Map<string, LayerPanelEntry>) {
@@ -423,7 +420,7 @@ export default defineComponent({
recurse(displayFolderTreeStructure, this.layers, this.layerCache);
});
subscribeJsMessage(UpdateLayer, (updateLayer) => {
this.editor.dispatcher.subscribeJsMessage(UpdateLayer, (updateLayer) => {
const targetPath = updateLayer.data.path;
const targetLayer = updateLayer.data;