mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-07-12 18:27:34 +00:00
When loading a workflow by dragging and dropping an output from the assets sidebar, the very long and unhelpful url would be used as the workflow name. This is fixed by instead using the asset display name | Before | After | | ------ | ----- | | <img width="360" alt="before" src="https://github.com/user-attachments/assets/5c68ae48-1fa6-40e1-b2fb-6188ccd60391"/> | <img width="360" alt="after" src="https://github.com/user-attachments/assets/29770c35-da48-4be9-943e-8ee69eb25e6a" />| Additionally, a max width is added to the breadcrumb items to avoid extremely long names. | Before | After | | ------ | ----- | | <img width="360" alt="before" src="https://github.com/user-attachments/assets/508155ec-81d7-4ca5-8910-f42a70c9cb4b"/> | <img width="360" alt="after" src="https://github.com/user-attachments/assets/d335ceb7-bfeb-481f-a132-c700e017ee0c" />|
95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
import { useChainCallback } from '@/composables/functional/useChainCallback'
|
|
import type { LGraphNode } from '@/lib/litegraph/src/litegraph'
|
|
import { parseAssetInfo } from '@/platform/assets/schemas/mediaAssetSchema'
|
|
import type { ResultItem } from '@/schemas/apiSchema'
|
|
|
|
type DragHandler = (e: DragEvent) => boolean
|
|
type DropHandler<T> = (files: File[]) => Promise<T[]>
|
|
|
|
interface DragAndDropOptions<T> {
|
|
onDragOver?: DragHandler
|
|
onDrop: DropHandler<T>
|
|
onResultItemDrop?: (item: ResultItem) => void
|
|
fileFilter?: (file: File) => boolean
|
|
}
|
|
|
|
/**
|
|
* Adds drag and drop file handling to a node
|
|
* Will also resolve 'text/uri-list' to a file before passing
|
|
*/
|
|
export const useNodeDragAndDrop = <T>(
|
|
node: LGraphNode,
|
|
options: DragAndDropOptions<T>
|
|
) => {
|
|
const { onDragOver, onDrop, fileFilter = () => true } = options
|
|
|
|
const hasFiles = (items: DataTransferItemList) =>
|
|
!!Array.from(items).find((f) => f.kind === 'file')
|
|
|
|
const filterFiles = (files: FileList | File[]) =>
|
|
Array.from(files).filter(fileFilter)
|
|
|
|
const hasValidFiles = (files: FileList) => filterFiles(files).length > 0
|
|
|
|
const isDraggingFiles = (e: DragEvent | undefined) => {
|
|
if (!e?.dataTransfer?.items) return false
|
|
return (
|
|
onDragOver?.(e) ??
|
|
(hasFiles(e.dataTransfer.items) ||
|
|
e?.dataTransfer?.types?.includes('text/uri-list'))
|
|
)
|
|
}
|
|
|
|
const isDraggingValidFiles = (e: DragEvent | undefined) => {
|
|
if (e?.dataTransfer?.files?.length)
|
|
return hasValidFiles(e.dataTransfer.files)
|
|
|
|
return !!e?.dataTransfer?.getData('text/uri-list')
|
|
}
|
|
|
|
const installedDragOver = isDraggingFiles
|
|
node.onDragOver = installedDragOver
|
|
|
|
const installedDragDrop = async function (e: DragEvent) {
|
|
if (!isDraggingValidFiles(e)) return false
|
|
|
|
const files = filterFiles(e.dataTransfer!.files)
|
|
if (files.length) {
|
|
await onDrop(files)
|
|
return true
|
|
}
|
|
const asset = parseAssetInfo(e.dataTransfer!)
|
|
if (asset?.filename && options.onResultItemDrop) {
|
|
await options.onResultItemDrop(asset)
|
|
return true
|
|
}
|
|
|
|
const baseUri = e?.dataTransfer?.getData('text/uri-list') ?? ''
|
|
const uri = URL.parse(baseUri, location.href)
|
|
if (!uri || uri.origin !== location.origin) return false
|
|
|
|
try {
|
|
const resp = await fetch(uri)
|
|
const fileName =
|
|
uri?.searchParams?.get('filename') ?? baseUri.split('/').at(-1)
|
|
if (!fileName || !resp.ok) return false
|
|
|
|
const blob = await resp.blob()
|
|
const file = new File([blob], fileName, { type: blob.type })
|
|
const uriFiles = filterFiles([file])
|
|
if (!uriFiles.length) return false
|
|
|
|
await onDrop(uriFiles)
|
|
} catch {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
node.onDragDrop = installedDragDrop
|
|
|
|
node.onRemoved = useChainCallback(node.onRemoved, () => {
|
|
if (node.onDragOver === installedDragOver) node.onDragOver = undefined
|
|
if (node.onDragDrop === installedDragDrop) node.onDragDrop = undefined
|
|
})
|
|
}
|