mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-11 16:10:05 +00:00
Feat: Loading state while loading dropped workflows (#6464)
## Summary Indicate to the user that we're hard at work parsing their JSON behind the scenes. ## Changes - **What**: Turn on the loading spinner while processing a workflow - **What else**: Refactored the code around figuring out how to grab the data from the file to make this easier ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6464-WIP-Loading-state-for-dropped-workflows-29c6d73d3650812dba66f2a7d27a777c) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
68
src/utils/__tests__/eventUtils.test.ts
Normal file
68
src/utils/__tests__/eventUtils.test.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { extractFileFromDragEvent } from '@/utils/eventUtils'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
describe('eventUtils', () => {
|
||||
describe('extractFileFromDragEvent', () => {
|
||||
it('should handle drops with no data', async () => {
|
||||
const actual = await extractFileFromDragEvent(new FakeDragEvent('drop'))
|
||||
expect(actual).toBe(undefined)
|
||||
})
|
||||
|
||||
it('should handle drops with dataTransfer but no files', async () => {
|
||||
const actual = await extractFileFromDragEvent(
|
||||
new FakeDragEvent('drop', { dataTransfer: new DataTransfer() })
|
||||
)
|
||||
expect(actual).toBe(undefined)
|
||||
})
|
||||
|
||||
it('should handle drops with dataTransfer with files', async () => {
|
||||
const fileWithWorkflowMaybeWhoKnows = new File(
|
||||
[new Uint8Array()],
|
||||
'fake_workflow.json',
|
||||
{
|
||||
type: 'application/json'
|
||||
}
|
||||
)
|
||||
|
||||
const dataTransfer = new DataTransfer()
|
||||
dataTransfer.items.add(fileWithWorkflowMaybeWhoKnows)
|
||||
|
||||
const event = new FakeDragEvent('drop', { dataTransfer })
|
||||
|
||||
const actual = await extractFileFromDragEvent(event)
|
||||
expect(actual).toBe(fileWithWorkflowMaybeWhoKnows)
|
||||
})
|
||||
|
||||
// Skip until we can setup MSW
|
||||
it.skip('should handle drops with URLs', async () => {
|
||||
const urlWithWorkflow = 'https://fakewebsite.notreal/fake_workflow.json'
|
||||
|
||||
const dataTransfer = new DataTransfer()
|
||||
|
||||
dataTransfer.setData('text/uri-list', urlWithWorkflow)
|
||||
dataTransfer.setData('text/x-moz-url', urlWithWorkflow)
|
||||
|
||||
const event = new FakeDragEvent('drop', { dataTransfer })
|
||||
|
||||
const actual = await extractFileFromDragEvent(event)
|
||||
expect(actual).toBeInstanceOf(File)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Needed to keep the dataTransfer defined
|
||||
class FakeDragEvent extends DragEvent {
|
||||
override dataTransfer: DataTransfer | null
|
||||
override clientX: number
|
||||
override clientY: number
|
||||
|
||||
constructor(
|
||||
type: string,
|
||||
{ dataTransfer, clientX, clientY }: DragEventInit = {}
|
||||
) {
|
||||
super(type)
|
||||
this.dataTransfer = dataTransfer ?? null
|
||||
this.clientX = clientX ?? 0
|
||||
this.clientY = clientY ?? 0
|
||||
}
|
||||
}
|
||||
27
src/utils/eventUtils.ts
Normal file
27
src/utils/eventUtils.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
export async function extractFileFromDragEvent(
|
||||
event: DragEvent
|
||||
): Promise<File | undefined> {
|
||||
if (!event.dataTransfer) return
|
||||
|
||||
// Dragging from Chrome->Firefox there is a file but its a bmp, so ignore that
|
||||
if (
|
||||
event.dataTransfer.files.length &&
|
||||
event.dataTransfer.files[0].type !== 'image/bmp'
|
||||
) {
|
||||
return event.dataTransfer.files[0]
|
||||
}
|
||||
|
||||
// Try loading the first URI in the transfer list
|
||||
const validTypes = ['text/uri-list', 'text/x-moz-url']
|
||||
const match = [...event.dataTransfer.types].find((t) =>
|
||||
validTypes.includes(t)
|
||||
)
|
||||
if (!match) return
|
||||
|
||||
const uri = event.dataTransfer.getData(match)?.split('\n')?.[0]
|
||||
if (!uri) return
|
||||
|
||||
const response = await fetch(uri)
|
||||
const blob = await response.blob()
|
||||
return new File([blob], uri, { type: blob.type })
|
||||
}
|
||||
Reference in New Issue
Block a user