diff --git a/app/package.json b/app/package.json index d0e8204..411975d 100644 --- a/app/package.json +++ b/app/package.json @@ -18,6 +18,7 @@ "@types/three": "^0.164.0", "@unocss/reset": "^0.59.4", "comlink": "^4.4.1", + "file-saver": "^2.0.5", "jsondiffpatch": "^0.6.0", "three": "^0.164.1" }, @@ -27,6 +28,7 @@ "@sveltejs/adapter-static": "^3.0.1", "@sveltejs/vite-plugin-svelte": "next", "@tsconfig/svelte": "^5.0.4", + "@types/file-saver": "^2.0.7", "@unocss/preset-icons": "^0.59.4", "svelte": "5.0.0-next.118", "svelte-check": "^3.7.0", diff --git a/app/src/lib/graph-interface/graph/Graph.svelte b/app/src/lib/graph-interface/graph/Graph.svelte index 9291036..643b299 100644 --- a/app/src/lib/graph-interface/graph/Graph.svelte +++ b/app/src/lib/graph-interface/graph/Graph.svelte @@ -12,7 +12,7 @@ import Camera from "../Camera.svelte"; import GraphView from "./GraphView.svelte"; import type { Node, NodeId, Node as NodeType, Socket } from "@nodes/types"; - import { NodeDefinitionSchema } from "@nodes/types"; + import { GraphSchema, NodeDefinitionSchema } from "@nodes/types"; import FloatingEdge from "../edges/FloatingEdge.svelte"; import { activeNodeId, @@ -28,6 +28,7 @@ import { createWasmWrapper } from "@nodes/utils"; import HelpView from "../HelpView.svelte"; + import FileSaver from "file-saver"; export let manager: GraphManager; @@ -612,6 +613,7 @@ keymap.addShortcut({ key: "a", ctrl: true, + preventDefault: true, description: "Select all nodes", callback: () => { if (!isBodyFocused()) return; @@ -637,7 +639,6 @@ ctrl: true, description: "Redo", callback: () => { - if (!isBodyFocused()) return; manager.redo(); for (const node of $nodes.values()) { updateNodePosition(node); @@ -645,6 +646,20 @@ }, }); + keymap.addShortcut({ + key: "s", + ctrl: true, + description: "Save", + preventDefault: true, + callback: () => { + const state = manager.serialize(); + const blob = new Blob([JSON.stringify(state)], { + type: "application/json;charset=utf-8", + }); + FileSaver.saveAs(blob, "nodarium-graph.json"); + }, + }); + keymap.addShortcut({ key: ["Delete", "Backspace", "x"], description: "Delete selected nodes", @@ -833,17 +848,31 @@ }); }); } else if (event.dataTransfer.files.length) { - const files = event.dataTransfer.files; - const reader = new FileReader(); - reader.onload = (e) => { - const buffer = e.target?.result as Buffer; - if (buffer) { - const wrapper = createWasmWrapper(buffer); - const definition = wrapper.get_definition(); - const res = NodeDefinitionSchema.parse(definition); - } - }; - reader.readAsArrayBuffer(files[0]); + const file = event.dataTransfer.files[0]; + + if (file.type === "application/wasm") { + const reader = new FileReader(); + reader.onload = (e) => { + const buffer = e.target?.result as Buffer; + if (buffer) { + const wrapper = createWasmWrapper(buffer); + const definition = wrapper.get_definition(); + const res = NodeDefinitionSchema.parse(definition); + console.log(res); + } + }; + reader.readAsArrayBuffer(file); + } else if (file.type === "application/json") { + const reader = new FileReader(); + reader.onload = (e) => { + const buffer = e.target?.result as Buffer; + if (buffer) { + const state = GraphSchema.parse(JSON.parse(buffer.toString())); + manager.load(state); + } + }; + reader.readAsText(file); + } } } @@ -893,13 +922,13 @@ > -