mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-28 02:34:10 +00:00
feat: show loading spinner and uploading filename during image upload (#9189)
## Summary - Show a canvas-based loading spinner on image upload nodes (LoadImage) during file upload via drag-drop, paste, or file picker - Display the uploading file's name immediately in the filename dropdown instead of showing the previous file's name - Show the uploading audio file's name immediately in the audio widget during upload ## Changes - **`useNodeImageUpload.ts`**: Add `isUploading` flag and `onUploadStart` callback to the upload lifecycle; clear `node.imgs` during upload to prevent stale previews - **`useImagePreviewWidget.ts`**: Add `renderUploadSpinner` that draws an animated arc spinner on the canvas when `node.isUploading` is true; guard against empty `imgs` array - **`useImageUploadWidget.ts`**: Set `fileComboWidget.value` to the new filename on upload start; clear `node.imgs` on combo widget change - **`uploadAudio.ts`**: Set `audioWidget.value` to the new filename on upload start - **`litegraph-augmentation.d.ts`**: Add `isUploading` property to `LGraphNode` https://github.com/user-attachments/assets/818ce529-cb83-428a-8c98-dd900a128343 ## Test plan - [x] Upload an image via file picker on LoadImage node — spinner shows during upload, filename updates immediately - [x] Drag-and-drop an image onto LoadImage node — same behavior - [x] Paste an image onto LoadImage node — same behavior - [x] Change the dropdown selection on LoadImage — old preview clears, new image loads - [x] Upload an audio file — filename updates immediately in the widget 🤖 Generated with [Claude Code](https://claude.com/claude-code) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9189-feat-show-loading-spinner-and-uploading-filename-during-image-upload-3126d73d365081e4af27cd7252f34298) by [Unito](https://www.unito.io) --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { useNodeDragAndDrop } from '@/composables/node/useNodeDragAndDrop'
|
||||
import { useNodeFileInput } from '@/composables/node/useNodeFileInput'
|
||||
import { useNodePaste } from '@/composables/node/useNodePaste'
|
||||
import { t } from '@/i18n'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import type { ResultItemType } from '@/schemas/apiSchema'
|
||||
@@ -62,6 +63,8 @@ interface ImageUploadOptions {
|
||||
* @example 'input', 'output', 'temp'
|
||||
*/
|
||||
folder?: ResultItemType
|
||||
onUploadStart?: (files: File[]) => void
|
||||
onUploadError?: () => void
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,10 +93,29 @@ export const useNodeImageUpload = (
|
||||
}
|
||||
|
||||
const handleUploadBatch = async (files: File[]) => {
|
||||
const paths = await Promise.all(files.map(handleUpload))
|
||||
const validPaths = paths.filter((p): p is string => !!p)
|
||||
if (validPaths.length) onUploadComplete(validPaths)
|
||||
return validPaths
|
||||
if (node.isUploading) {
|
||||
useToastStore().addAlert(t('g.uploadAlreadyInProgress'))
|
||||
return []
|
||||
}
|
||||
node.isUploading = true
|
||||
|
||||
try {
|
||||
node.imgs = undefined
|
||||
node.graph?.setDirtyCanvas(true)
|
||||
options.onUploadStart?.(files)
|
||||
|
||||
const paths = await Promise.all(files.map(handleUpload))
|
||||
const validPaths = paths.filter((p): p is string => !!p)
|
||||
if (validPaths.length) {
|
||||
onUploadComplete(validPaths)
|
||||
} else {
|
||||
options.onUploadError?.()
|
||||
}
|
||||
return validPaths
|
||||
} finally {
|
||||
node.isUploading = false
|
||||
node.graph?.setDirtyCanvas(true)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle drag & drop
|
||||
|
||||
Reference in New Issue
Block a user