import { GraphSchema, type NodeId } from '@nodarium/types'; import type { GraphManager } from '../graph-manager.svelte'; import type { GraphState } from '../graph-state.svelte'; export class FileDropEventManager { constructor( private graph: GraphManager, private state: GraphState ) { } handleFileDrop(event: DragEvent) { event.preventDefault(); this.state.isDragging = false; if (!event.dataTransfer) return; const nodeId = event.dataTransfer.getData('data/node-id') as NodeId; let mx = event.clientX - this.state.rect.x; let my = event.clientY - this.state.rect.y; if (nodeId) { let nodeOffsetX = event.dataTransfer.getData('data/node-offset-x'); let nodeOffsetY = event.dataTransfer.getData('data/node-offset-y'); if (nodeOffsetX && nodeOffsetY) { mx += parseInt(nodeOffsetX); my += parseInt(nodeOffsetY); } let props = {}; let rawNodeProps = event.dataTransfer.getData('data/node-props'); if (rawNodeProps) { try { props = JSON.parse(rawNodeProps); } catch (e) { } } const pos = this.state.projectScreenToWorld(mx, my); this.graph.registry.load([nodeId]).then(() => { this.graph.createNode({ type: nodeId, props, position: pos }); }); } else if (event.dataTransfer.files.length) { const file = event.dataTransfer.files[0]; if (file.type === 'application/wasm') { const reader = new FileReader(); reader.onload = async (e) => { const buffer = e.target?.result; if (buffer?.constructor === ArrayBuffer) { const nodeType = await this.graph.registry.register(buffer); this.graph.createNode({ type: nodeType.id, props: {}, position: this.state.projectScreenToWorld(mx, my) }); } }; reader.readAsArrayBuffer(file); } else if (file.type === 'application/json') { const reader = new FileReader(); reader.onload = (e) => { const buffer = e.target?.result as ArrayBuffer; if (buffer) { const state = GraphSchema.parse(JSON.parse(buffer.toString())); this.graph.load(state); } }; reader.readAsText(file); } } } handleMouseLeave() { this.state.isDragging = false; this.state.isPanning = false; } handleDragEnter(e: DragEvent) { e.preventDefault(); this.state.isDragging = true; this.state.isPanning = false; } handleDragOver(e: DragEvent) { e.preventDefault(); this.state.isDragging = true; this.state.isPanning = false; } handleDragEnd(e: DragEvent) { e.preventDefault(); this.state.isDragging = true; this.state.isPanning = false; } getEventListenerProps() { return { ondragenter: (ev: DragEvent) => this.handleDragEnter(ev), ondragover: (ev: DragEvent) => this.handleDragOver(ev), ondragexit: (ev: DragEvent) => this.handleDragEnd(ev), ondrop: (ev: DragEvent) => this.handleFileDrop(ev), onmouseleave: () => this.handleMouseLeave() }; } }