mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-08 09:00:05 +00:00
127 lines
3.7 KiB
TypeScript
127 lines
3.7 KiB
TypeScript
import { LGraphNode } from '@comfyorg/litegraph'
|
|
import { defineStore } from 'pinia'
|
|
|
|
import {
|
|
ExecutedWsMessage,
|
|
ResultItem,
|
|
ResultItemType
|
|
} from '@/schemas/apiSchema'
|
|
import { api } from '@/scripts/api'
|
|
import { app } from '@/scripts/app'
|
|
import type { NodeExecutionId } from '@/types'
|
|
import { parseFilePath } from '@/utils/formatUtil'
|
|
import { isVideoNode } from '@/utils/litegraphUtil'
|
|
|
|
import { useExecutionStore } from './executionStore'
|
|
|
|
const createOutputs = (
|
|
filenames: string[],
|
|
type: ResultItemType,
|
|
isAnimated: boolean
|
|
): ExecutedWsMessage['output'] => {
|
|
return {
|
|
images: filenames.map((image) => ({ type, ...parseFilePath(image) })),
|
|
animated: filenames.map((image) => isAnimated && image.endsWith('.webp'))
|
|
}
|
|
}
|
|
|
|
export const useNodeOutputStore = defineStore('nodeOutput', () => {
|
|
const executionStore = useExecutionStore()
|
|
const getMostRecentExecutionId = (node: LGraphNode): NodeExecutionId =>
|
|
executionStore.locatorIdToExecutionIdMap.get(
|
|
executionStore.getNodeLocatorId(node)
|
|
) ?? node.id.toString()
|
|
|
|
function getNodeOutputs(
|
|
node: LGraphNode
|
|
): ExecutedWsMessage['output'] | undefined {
|
|
return app.nodeOutputs[getMostRecentExecutionId(node)]
|
|
}
|
|
|
|
function getNodePreviews(node: LGraphNode): string[] | undefined {
|
|
return app.nodePreviewImages[getMostRecentExecutionId(node)]
|
|
}
|
|
|
|
/**
|
|
* Check if a node's outputs includes images that should/can be loaded normally
|
|
* by PIL.
|
|
*/
|
|
const isImageOutputs = (
|
|
node: LGraphNode,
|
|
outputs: ExecutedWsMessage['output']
|
|
): boolean => {
|
|
// If animated webp/png or video outputs, return false
|
|
if (node.animatedImages || isVideoNode(node)) return false
|
|
|
|
// If no images, return false
|
|
if (!outputs?.images?.length) return false
|
|
|
|
// If svg images, return false
|
|
if (outputs.images.some((image) => image.filename?.endsWith('svg')))
|
|
return false
|
|
|
|
return true
|
|
}
|
|
|
|
/**
|
|
* Get the preview param for the node's outputs.
|
|
*
|
|
* If the output is an image, use the user's preferred format (from settings).
|
|
* For non-image outputs, return an empty string, as including the preview param
|
|
* will force the server to load the output file as an image.
|
|
*/
|
|
function getPreviewParam(
|
|
node: LGraphNode,
|
|
outputs: ExecutedWsMessage['output']
|
|
): string {
|
|
return isImageOutputs(node, outputs) ? app.getPreviewFormatParam() : ''
|
|
}
|
|
|
|
function getNodeImageUrls(node: LGraphNode): string[] | undefined {
|
|
const previews = getNodePreviews(node)
|
|
if (previews?.length) return previews
|
|
|
|
const outputs = getNodeOutputs(node)
|
|
if (!outputs?.images?.length) return
|
|
|
|
const rand = app.getRandParam()
|
|
const previewParam = getPreviewParam(node, outputs)
|
|
|
|
return outputs.images.map((image) => {
|
|
const imgUrlPart = new URLSearchParams(image)
|
|
return api.apiURL(`/view?${imgUrlPart}${previewParam}${rand}`)
|
|
})
|
|
}
|
|
|
|
function setNodeOutputs(
|
|
node: LGraphNode,
|
|
filenames: string | string[] | ResultItem,
|
|
{
|
|
folder = 'input',
|
|
isAnimated = false
|
|
}: { folder?: ResultItemType; isAnimated?: boolean } = {}
|
|
) {
|
|
if (!filenames || !node) return
|
|
|
|
const nodeId = getMostRecentExecutionId(node)
|
|
|
|
if (typeof filenames === 'string') {
|
|
app.nodeOutputs[nodeId] = createOutputs([filenames], folder, isAnimated)
|
|
} else if (!Array.isArray(filenames)) {
|
|
app.nodeOutputs[nodeId] = filenames
|
|
} else {
|
|
const resultItems = createOutputs(filenames, folder, isAnimated)
|
|
if (!resultItems?.images?.length) return
|
|
app.nodeOutputs[nodeId] = resultItems
|
|
}
|
|
}
|
|
|
|
return {
|
|
getNodeOutputs,
|
|
getNodeImageUrls,
|
|
getNodePreviews,
|
|
setNodeOutputs,
|
|
getPreviewParam
|
|
}
|
|
})
|