From ce46f19de977397c5c864eb208bffdb49ce984ef Mon Sep 17 00:00:00 2001 From: filtered <176114999+webfiltered@users.noreply.github.com> Date: Fri, 18 Apr 2025 20:50:33 +1000 Subject: [PATCH] Fix LinkConnector methods cannot be cancelled via API (#934) - Checks if `e.preventDefault()` has been called for all cancellable LinkConnector callbacks - Sets `cancelable: true` on dispatched events - Dedupes canvas pointer calls --- src/LGraphCanvas.ts | 33 ++++++++++--------- src/canvas/LinkConnector.ts | 7 ++-- .../LinkConnectorEventTarget.ts | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/LGraphCanvas.ts b/src/LGraphCanvas.ts index 585cd20cc..9201bf13b 100644 --- a/src/LGraphCanvas.ts +++ b/src/LGraphCanvas.ts @@ -1712,6 +1712,17 @@ export class LGraphCanvas implements ConnectionColorContext { this.dirty_bgcanvas = true } + #linkConnectorDrop(): void { + const { graph, linkConnector, pointer } = this + if (!graph) throw new NullGraphError() + + pointer.onDragEnd = upEvent => linkConnector.dropLinks(graph, upEvent) + pointer.finally = () => { + this.linkConnector.reset(true) + this.#dirty() + } + } + /** * Used to attach the canvas in a popup * @returns returns the window where the canvas is attached (the DOM root node) @@ -1993,9 +2004,7 @@ export class LGraphCanvas implements ConnectionColorContext { if (reroute) { if (e.shiftKey) { linkConnector.dragFromReroute(graph, reroute) - - pointer.onDragEnd = upEvent => linkConnector.dropLinks(graph, upEvent) - pointer.finally = () => linkConnector.reset(true) + this.#linkConnectorDrop() this.dirty_bgcanvas = true } @@ -2029,9 +2038,7 @@ export class LGraphCanvas implements ConnectionColorContext { if (e.shiftKey && !e.altKey) { linkConnector.dragFromLinkSegment(graph, linkSegment) - - pointer.onDragEnd = upEvent => linkConnector.dropLinks(graph, upEvent) - pointer.finally = () => linkConnector.reset(true) + this.#linkConnectorDrop() return } else if (e.altKey && !e.shiftKey) { @@ -2220,18 +2227,13 @@ export class LGraphCanvas implements ConnectionColorContext { // Drag multiple output links if (e.shiftKey && (output.links?.length || output._floatingLinks?.size)) { linkConnector.moveOutputLink(graph, output) - - pointer.onDragEnd = upEvent => linkConnector.dropLinks(graph, upEvent) - pointer.finally = () => linkConnector.reset(true) - + this.#linkConnectorDrop() return } // New output link linkConnector.dragNewFromOutput(graph, node, output) - - pointer.onDragEnd = upEvent => linkConnector.dropLinks(graph, upEvent) - pointer.finally = () => linkConnector.reset(true) + this.#linkConnectorDrop() if (LiteGraph.shift_click_do_break_link_from) { if (e.shiftKey) { @@ -2277,8 +2279,8 @@ export class LGraphCanvas implements ConnectionColorContext { if (!linkConnector.isConnecting) { linkConnector.dragNewFromInput(graph, node, input) } - pointer.onDragEnd = upEvent => linkConnector.dropLinks(graph, upEvent) - pointer.finally = () => linkConnector.reset(true) + + this.#linkConnectorDrop() this.dirty_bgcanvas = true return @@ -2918,6 +2920,7 @@ export class LGraphCanvas implements ConnectionColorContext { // esc if (this.linkConnector.isConnecting) { this.linkConnector.reset() + this.#dirty() e.preventDefault() return } diff --git a/src/canvas/LinkConnector.ts b/src/canvas/LinkConnector.ts index 2e43122ac..1f20b54d8 100644 --- a/src/canvas/LinkConnector.ts +++ b/src/canvas/LinkConnector.ts @@ -435,6 +435,9 @@ export class LinkConnector { dropOnNothing(event: CanvasPointerEvent): void { // For external event only. + const mayContinue = this.events.dispatch("dropped-on-canvas", event) + if (mayContinue === false) return + if (this.state.connectingTo === "input") { for (const link of this.renderLinks) { if (link instanceof MovingInputLink) { @@ -442,7 +445,6 @@ export class LinkConnector { } } } - this.events.dispatch("dropped-on-canvas", event) } /** @@ -608,7 +610,8 @@ export class LinkConnector { * Effectively cancels moving or connecting links. */ reset(force = false): void { - this.events.dispatch("reset", force) + const mayContinue = this.events.dispatch("reset", force) + if (mayContinue === false) return const { state, outputLinks, inputLinks, hiddenReroutes, renderLinks, floatingLinks } = this diff --git a/src/infrastructure/LinkConnectorEventTarget.ts b/src/infrastructure/LinkConnectorEventTarget.ts index 913c53933..d5a91061c 100644 --- a/src/infrastructure/LinkConnectorEventTarget.ts +++ b/src/infrastructure/LinkConnectorEventTarget.ts @@ -77,7 +77,7 @@ export class LinkConnectorEventTarget extends EventTarget { dispatch(type: T, detail: LinkConnectorEventMap[T]): boolean dispatch(type: T): boolean dispatch(type: T, detail?: LinkConnectorEventMap[T]) { - const event = new CustomEvent(type, { detail }) + const event = new CustomEvent(type, { detail, cancelable: true }) return super.dispatchEvent(event) }