Skip to content

Commit add8054

Browse files
christian-byrnegithub-actions
andauthored
Fix drag and drop image with embedded workflow on Firefox (#3519)
Co-authored-by: github-actions <[email protected]>
1 parent 9621b8f commit add8054

File tree

4 files changed

+124
-66
lines changed

4 files changed

+124
-66
lines changed

browser_tests/fixtures/ComfyPage.ts

Lines changed: 101 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -463,87 +463,128 @@ export class ComfyPage {
463463
await this.nextFrame()
464464
}
465465

466-
async dragAndDropFile(
467-
fileName: string,
466+
async dragAndDropExternalResource(
468467
options: {
468+
fileName?: string
469+
url?: string
469470
dropPosition?: Position
470471
} = {}
471472
) {
472-
const { dropPosition = { x: 100, y: 100 } } = options
473-
474-
const filePath = this.assetPath(fileName)
475-
476-
// Read the file content
477-
const buffer = fs.readFileSync(filePath)
473+
const { dropPosition = { x: 100, y: 100 }, fileName, url } = options
474+
475+
if (!fileName && !url)
476+
throw new Error('Must provide either fileName or url')
477+
478+
const evaluateParams: {
479+
dropPosition: Position
480+
fileName?: string
481+
fileType?: string
482+
buffer?: Uint8Array | number[]
483+
url?: string
484+
} = { dropPosition }
485+
486+
// Dropping a file from the filesystem
487+
if (fileName) {
488+
const filePath = this.assetPath(fileName)
489+
const buffer = fs.readFileSync(filePath)
490+
491+
const getFileType = (fileName: string) => {
492+
if (fileName.endsWith('.png')) return 'image/png'
493+
if (fileName.endsWith('.webp')) return 'image/webp'
494+
if (fileName.endsWith('.webm')) return 'video/webm'
495+
if (fileName.endsWith('.json')) return 'application/json'
496+
if (fileName.endsWith('.glb')) return 'model/gltf-binary'
497+
return 'application/octet-stream'
498+
}
478499

479-
// Get file type
480-
const getFileType = (fileName: string) => {
481-
if (fileName.endsWith('.png')) return 'image/png'
482-
if (fileName.endsWith('.webp')) return 'image/webp'
483-
if (fileName.endsWith('.webm')) return 'video/webm'
484-
if (fileName.endsWith('.json')) return 'application/json'
485-
if (fileName.endsWith('.glb')) return 'model/gltf-binary'
486-
return 'application/octet-stream'
500+
evaluateParams.fileName = fileName
501+
evaluateParams.fileType = getFileType(fileName)
502+
evaluateParams.buffer = [...new Uint8Array(buffer)]
487503
}
488504

489-
const fileType = getFileType(fileName)
505+
// Dropping a URL (e.g., dropping image across browser tabs in Firefox)
506+
if (url) evaluateParams.url = url
490507

491-
await this.page.evaluate(
492-
async ({ buffer, fileName, fileType, dropPosition }) => {
493-
const file = new File([new Uint8Array(buffer)], fileName, {
494-
type: fileType
495-
})
496-
const dataTransfer = new DataTransfer()
497-
dataTransfer.items.add(file)
508+
// Execute the drag and drop in the browser
509+
await this.page.evaluate(async (params) => {
510+
const dataTransfer = new DataTransfer()
498511

499-
const targetElement = document.elementFromPoint(
500-
dropPosition.x,
501-
dropPosition.y
512+
// Add file if provided
513+
if (params.buffer && params.fileName && params.fileType) {
514+
const file = new File(
515+
[new Uint8Array(params.buffer)],
516+
params.fileName,
517+
{
518+
type: params.fileType
519+
}
502520
)
521+
dataTransfer.items.add(file)
522+
}
503523

504-
if (!targetElement) {
505-
console.error('No element found at drop position:', dropPosition)
506-
return { success: false, error: 'No element at position' }
507-
}
524+
// Add URL data if provided
525+
if (params.url) {
526+
dataTransfer.setData('text/uri-list', params.url)
527+
dataTransfer.setData('text/x-moz-url', params.url)
528+
}
508529

509-
const eventOptions = {
510-
bubbles: true,
511-
cancelable: true,
512-
dataTransfer,
513-
clientX: dropPosition.x,
514-
clientY: dropPosition.y
515-
}
530+
const targetElement = document.elementFromPoint(
531+
params.dropPosition.x,
532+
params.dropPosition.y
533+
)
516534

517-
const dragOverEvent = new DragEvent('dragover', eventOptions)
518-
const dropEvent = new DragEvent('drop', eventOptions)
535+
if (!targetElement) {
536+
console.error('No element found at drop position:', params.dropPosition)
537+
return { success: false, error: 'No element at position' }
538+
}
519539

520-
Object.defineProperty(dropEvent, 'preventDefault', {
521-
value: () => {},
522-
writable: false
523-
})
524-
Object.defineProperty(dropEvent, 'stopPropagation', {
525-
value: () => {},
526-
writable: false
527-
})
540+
const eventOptions = {
541+
bubbles: true,
542+
cancelable: true,
543+
dataTransfer,
544+
clientX: params.dropPosition.x,
545+
clientY: params.dropPosition.y
546+
}
528547

529-
targetElement.dispatchEvent(dragOverEvent)
530-
targetElement.dispatchEvent(dropEvent)
548+
const dragOverEvent = new DragEvent('dragover', eventOptions)
549+
const dropEvent = new DragEvent('drop', eventOptions)
531550

532-
return {
533-
success: true,
534-
targetInfo: {
535-
tagName: targetElement.tagName,
536-
id: targetElement.id,
537-
classList: Array.from(targetElement.classList)
538-
}
551+
Object.defineProperty(dropEvent, 'preventDefault', {
552+
value: () => {},
553+
writable: false
554+
})
555+
556+
Object.defineProperty(dropEvent, 'stopPropagation', {
557+
value: () => {},
558+
writable: false
559+
})
560+
561+
targetElement.dispatchEvent(dragOverEvent)
562+
targetElement.dispatchEvent(dropEvent)
563+
564+
return {
565+
success: true,
566+
targetInfo: {
567+
tagName: targetElement.tagName,
568+
id: targetElement.id,
569+
classList: Array.from(targetElement.classList)
539570
}
540-
},
541-
{ buffer: [...new Uint8Array(buffer)], fileName, fileType, dropPosition }
542-
)
571+
}
572+
}, evaluateParams)
543573

544574
await this.nextFrame()
545575
}
546576

577+
async dragAndDropFile(
578+
fileName: string,
579+
options: { dropPosition?: Position } = {}
580+
) {
581+
return this.dragAndDropExternalResource({ fileName, ...options })
582+
}
583+
584+
async dragAndDropURL(url: string, options: { dropPosition?: Position } = {}) {
585+
return this.dragAndDropExternalResource({ url, ...options })
586+
}
587+
547588
async dragNode2() {
548589
await this.dragAndDrop({ x: 622, y: 400 }, { x: 622, y: 300 })
549590
await this.nextFrame()

browser_tests/tests/loadWorkflowInMedia.spec.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,35 @@ import { expect } from '@playwright/test'
33
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
44

55
test.describe('Load Workflow in Media', () => {
6-
;[
6+
const fileNames = [
77
'workflow.webp',
88
'edited_workflow.webp',
99
'no_workflow.webp',
1010
'large_workflow.webp',
1111
'workflow.webm',
1212
'workflow.glb'
13-
].forEach(async (fileName) => {
14-
test(`Load workflow in ${fileName}`, async ({ comfyPage }) => {
13+
]
14+
fileNames.forEach(async (fileName) => {
15+
test(`Load workflow in ${fileName} (drop from filesystem)`, async ({
16+
comfyPage
17+
}) => {
1518
await comfyPage.dragAndDropFile(fileName)
1619
await expect(comfyPage.canvas).toHaveScreenshot(`${fileName}.png`)
1720
})
1821
})
22+
23+
const urls = [
24+
'https://comfyanonymous.github.io/ComfyUI_examples/hidream/hidream_dev_example.png'
25+
]
26+
urls.forEach(async (url) => {
27+
test(`Load workflow from URL${url} (drop from different browser tabs)`, async ({
28+
comfyPage
29+
}) => {
30+
await comfyPage.dragAndDropURL(url)
31+
const readableName = url.split('/').pop()
32+
await expect(comfyPage.canvas).toHaveScreenshot(
33+
`dropped_workflow_url_${readableName}.png`
34+
)
35+
})
36+
})
1937
})
141 KB
Loading

src/scripts/app.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,8 @@ export class ComfyApp {
481481
if (match) {
482482
const uri = event.dataTransfer.getData(match)?.split('\n')?.[0]
483483
if (uri) {
484-
await this.handleFile(
485-
new File([await (await fetch(uri)).blob()], uri)
486-
)
484+
const blob = await (await fetch(uri)).blob()
485+
await this.handleFile(new File([blob], uri, { type: blob.type }))
487486
}
488487
}
489488
}

0 commit comments

Comments
 (0)