-
Notifications
You must be signed in to change notification settings - Fork 491
Batch drag and drop #8246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Batch drag and drop #8246
Changes from all commits
4101fea
4caeaaa
65725a5
ca4fabe
2ab91d8
1dcbad1
1072c0d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -6,9 +6,42 @@ import type { ComfyWorkflowJSON } from '@/platform/workflow/validation/schemas/w | |||||||||||||||||||||||||||||||||||||||||||||||
| import { useCanvasStore } from '@/renderer/core/canvas/canvasStore' | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { app } from '@/scripts/app' | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { useWorkspaceStore } from '@/stores/workspaceStore' | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { isAudioNode, isImageNode, isVideoNode } from '@/utils/litegraphUtil' | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { createNode, isAudioNode, isImageNode, isVideoNode } from '@/utils/litegraphUtil' | ||||||||||||||||||||||||||||||||||||||||||||||||
| import { shouldIgnoreCopyPaste } from '@/workbench/eventHelpers' | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| export function cloneDataTransfer(original: DataTransfer): DataTransfer { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const persistent = new DataTransfer(); | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Copy string data | ||||||||||||||||||||||||||||||||||||||||||||||||
| for (const type of original.types) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const data = original.getData(type); | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (data) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| persistent.setData(type, data); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Copy files | ||||||||||||||||||||||||||||||||||||||||||||||||
| for (const file of original.files) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| persistent.items.add(file); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Also handle any file-kind items that might not be in .files | ||||||||||||||||||||||||||||||||||||||||||||||||
| for (const item of original.items) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (item.kind === 'file') { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const file = item.getAsFile(); | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (file) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| persistent.items.add(file); | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+36
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate files added when cloning DataTransfer. The function copies files from 🐛 Proposed fix: Remove the redundant files loop- // Copy files
- for (const file of original.files) {
- persistent.items.add(file);
- }
-
- // Also handle any file-kind items that might not be in .files
+ // Copy file-kind items
for (const item of original.items) {
if (item.kind === 'file') {
const file = item.getAsFile();
if (file) {
persistent.items.add(file);
}
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| // Preserve dropEffect and effectAllowed | ||||||||||||||||||||||||||||||||||||||||||||||||
| persistent.dropEffect = original.dropEffect; | ||||||||||||||||||||||||||||||||||||||||||||||||
| persistent.effectAllowed = original.effectAllowed; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return persistent; | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| function pasteClipboardItems(data: DataTransfer): boolean { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const rawData = data.getData('text/html') | ||||||||||||||||||||||||||||||||||||||||||||||||
| const match = rawData.match(/data-metadata="([A-Za-z0-9+/=]+)"/)?.[1] | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -48,27 +81,37 @@ function pasteItemsOnNode( | |||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| export function pasteImageNode( | ||||||||||||||||||||||||||||||||||||||||||||||||
| export async function pasteImageNode( | ||||||||||||||||||||||||||||||||||||||||||||||||
| canvas: LGraphCanvas, | ||||||||||||||||||||||||||||||||||||||||||||||||
| items: DataTransferItemList, | ||||||||||||||||||||||||||||||||||||||||||||||||
| imageNode: LGraphNode | null = null | ||||||||||||||||||||||||||||||||||||||||||||||||
| ): void { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const { | ||||||||||||||||||||||||||||||||||||||||||||||||
| graph, | ||||||||||||||||||||||||||||||||||||||||||||||||
| graph_mouse: [posX, posY] | ||||||||||||||||||||||||||||||||||||||||||||||||
| } = canvas | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<LGraphNode | null> { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!imageNode) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| // No image node selected: add a new one | ||||||||||||||||||||||||||||||||||||||||||||||||
| const newNode = LiteGraph.createNode('LoadImage') | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (newNode) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| newNode.pos = [posX, posY] | ||||||||||||||||||||||||||||||||||||||||||||||||
| imageNode = graph?.add(newNode) ?? null | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| graph?.change() | ||||||||||||||||||||||||||||||||||||||||||||||||
| imageNode = await createNode(canvas, 'LoadImage') | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| pasteItemsOnNode(items, imageNode, 'image') | ||||||||||||||||||||||||||||||||||||||||||||||||
| return imageNode | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| export async function pasteImageNodes( | ||||||||||||||||||||||||||||||||||||||||||||||||
| canvas: LGraphCanvas, | ||||||||||||||||||||||||||||||||||||||||||||||||
| fileList: FileList | ||||||||||||||||||||||||||||||||||||||||||||||||
| ): Promise<LGraphNode[]> { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const nodes: LGraphNode[] = []; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| for (const file of fileList) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| const transfer = new DataTransfer() | ||||||||||||||||||||||||||||||||||||||||||||||||
| transfer.items.add(file) | ||||||||||||||||||||||||||||||||||||||||||||||||
| const imageNode = await pasteImageNode(canvas, transfer.items) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| if (imageNode) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| nodes.push(imageNode) | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| return nodes | ||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -93,6 +136,7 @@ export const usePaste = () => { | |||||||||||||||||||||||||||||||||||||||||||||||
| const { graph } = canvas | ||||||||||||||||||||||||||||||||||||||||||||||||
| let data: DataTransfer | string | null = e.clipboardData | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!data) throw new Error('No clipboard data on clipboard event') | ||||||||||||||||||||||||||||||||||||||||||||||||
| data = cloneDataTransfer(data) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| const { items } = data | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -114,7 +158,7 @@ export const usePaste = () => { | |||||||||||||||||||||||||||||||||||||||||||||||
| // Look for image paste data | ||||||||||||||||||||||||||||||||||||||||||||||||
| for (const item of items) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (item.type.startsWith('image/')) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| pasteImageNode(canvas as LGraphCanvas, items, imageNode) | ||||||||||||||||||||||||||||||||||||||||||||||||
| await pasteImageNode(canvas as LGraphCanvas, items, imageNode) | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle errors from async Line 127 now awaits an async path that can throw (e.g., node creation failure). Wrap the await in a try/catch and route errors through your existing UI error reporting mechanism; ensure any user-visible message uses i18n. 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (item.type.startsWith('video/')) { | ||||||||||||||||||||||||||||||||||||||||||||||||
| if (!videoNode) { | ||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -77,6 +77,7 @@ import { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from '@/utils/graphTraversalUtil' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| executeWidgetsCallback, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| createNode, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fixLinkInputSlots, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isImageNode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } from '@/utils/litegraphUtil' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -97,7 +98,7 @@ import { type ComfyWidgetConstructor } from './widgets' | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ensureCorrectLayoutScale } from '@/renderer/extensions/vueNodes/layout/ensureCorrectLayoutScale' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { extractFileFromDragEvent } from '@/utils/eventUtils' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { getWorkflowDataFromFile } from '@/scripts/metadata/parser' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { pasteImageNode } from '@/composables/usePaste' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { pasteImageNode, pasteImageNodes } from '@/composables/usePaste' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const ANIM_PREVIEW_WIDGET = '$$comfy_animation_preview' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -542,7 +543,13 @@ export class ComfyApp { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const workspace = useWorkspaceStore() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspace.spinner = true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await this.handleFile(fileMaybe, 'file_drop') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (fileMaybe instanceof File) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await this.handleFile(fileMaybe, 'file_drop') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (fileMaybe instanceof FileList) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await this.handleFileList(fileMaybe) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| workspace.spinner = false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1437,7 +1444,9 @@ export class ComfyApp { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (file.type.startsWith('image')) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const transfer = new DataTransfer() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| transfer.items.add(file) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pasteImageNode(this.canvas, transfer.items) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log('transfer items', transfer.items) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const imageNode = await createNode(this.canvas, 'LoadImage') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await pasteImageNode(this.canvas, transfer.items, imageNode) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -1516,6 +1525,42 @@ export class ComfyApp { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.showErrorOnFileLoad(file) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Loads multiple files and connects to a batch node | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {FileList} fileList | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async handleFileList(fileList: FileList) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (fileList[0].type.startsWith('image')) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const imageNodes = await pasteImageNodes(this.canvas, fileList) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const batchImagesNode = await createNode(this.canvas, 'BatchImagesNode') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!batchImagesNode) return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.positionNodes(imageNodes, batchImagesNode) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Array.from(imageNodes).forEach((imageNode, index) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageNode.connect(0, batchImagesNode, index) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Positions batched nodes in drag and drop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param nodes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param batchNode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| positionNodes(nodes: LGraphNode[], batchNode: LGraphNode) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [x, y, width, height] = nodes[0].getBounding() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| batchNode.pos = [ x + width + 100, y + 30 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1533
to
+1554
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard against empty
🐛 Proposed fix async handleFileList(fileList: FileList) {
- if (fileList[0].type.startsWith('image')) {
+ if (!fileList.length) return
+ if (fileList[0].type.startsWith('image')) {
const imageNodes = await pasteImageNodes(this.canvas, fileList)
+ if (!imageNodes.length) return
const batchImagesNode = await createNode(this.canvas, 'BatchImagesNode')
if (!batchImagesNode) return📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do that in the method that calls this.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: Length of output: 2381 🏁 Script executed: Length of output: 1028
Drop handler (line 550-551): if (fileMaybe instanceof FileList) {
await this.handleFileList(fileMaybe)
}This only checks the type, not the length. The actual issue is in
While The suggested guards are needed to prevent runtime errors when 🧬 Code Graph Analysis ResultsFile:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| nodes.forEach((node, index) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (index > 0) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| node.pos = [ x, y + (height * index) + (25 * (index + 1))]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.canvas.graph?.change() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
JemiloII marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // @deprecated | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isApiJson(data: unknown): data is ComfyApiWorkflow { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!_.isObject(data) || Array.isArray(data)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick | 🔵 Trivial
Prefer
Partial<LGraphNode>casts for mock nodes.Several tests cast mock objects via
as unknown as LGraphNode. UsePartial<LGraphNode> as LGraphNodeto make incomplete mocks explicit and safer. Based on learnings, preferPartial<Interface> as Interfacefor partial mocks in tests.♻️ Proposed refactor
Also applies to: 190-212, 237-250, 302-309
🤖 Prompt for AI Agents