fix: dropdown widget fetching output files (#6734)

related
https://github.com/Comfy-Org/ComfyUI_frontend/issues/5827#issuecomment-3539629932

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6734-fix-dropdown-widget-fetching-output-files-2af6d73d365081988340f74694b7cee7)
by [Unito](https://www.unito.io)

Co-authored-by: bymyself <cbyrne@comfy.org>
This commit is contained in:
Rizumu Ayaka
2026-03-13 04:43:33 +08:00
committed by GitHub
parent 8b9eb5f60d
commit 8f07468fdd
2 changed files with 32 additions and 30 deletions

View File

@@ -7,6 +7,7 @@ import { useTransformCompatOverlayProps } from '@/composables/useTransformCompat
import { appendCloudResParam } from '@/platform/distribution/cloudPreviewUtil'
import { SUPPORTED_EXTENSIONS_ACCEPT } from '@/extensions/core/load3d/constants'
import { useAssetFilterOptions } from '@/platform/assets/composables/useAssetFilterOptions'
import { useMediaAssets } from '@/platform/assets/composables/media/useMediaAssets'
import {
filterItemByBaseModels,
filterItemByOwnership
@@ -33,9 +34,9 @@ import { useAssetWidgetData } from '@/renderer/extensions/vueNodes/widgets/compo
import type { ResultItemType } from '@/schemas/apiSchema'
import { api } from '@/scripts/api'
import { useAssetsStore } from '@/stores/assetsStore'
import { useQueueStore } from '@/stores/queueStore'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import type { AssetKind } from '@/types/widgetTypes'
import { getMediaTypeFromFilename } from '@/utils/formatUtil'
import {
PANEL_EXCLUDED_PROPS,
filterWidgetProps
@@ -68,7 +69,8 @@ const modelValue = defineModel<string | undefined>({
const { t } = useI18n()
const toastStore = useToastStore()
const queueStore = useQueueStore()
const outputMediaAssets = useMediaAssets('output')
const transformCompatProps = useTransformCompatOverlayProps()
@@ -147,36 +149,28 @@ const inputItems = computed<FormDropdownItem[]>(() => {
label: getDisplayLabel(String(value))
}))
})
function assetKindToMediaType(kind: AssetKind): string {
return kind === 'mesh' ? '3D' : kind
}
const outputItems = computed<FormDropdownItem[]>(() => {
if (!['image', 'video', 'mesh'].includes(props.assetKind ?? '')) return []
if (!['image', 'video', 'audio', 'mesh'].includes(props.assetKind ?? ''))
return []
const outputs = new Set<string>()
const targetMediaType = assetKindToMediaType(props.assetKind!)
const outputFiles = outputMediaAssets.media.value.filter(
(asset) => getMediaTypeFromFilename(asset.name) === targetMediaType
)
// Extract output images/videos from queue history
queueStore.historyTasks.forEach((task) => {
task.flatOutputs.forEach((output) => {
const isTargetType =
(props.assetKind === 'image' && output.mediaType === 'images') ||
(props.assetKind === 'video' && output.mediaType === 'video') ||
(props.assetKind === 'mesh' && output.is3D)
if (output.type === 'output' && isTargetType) {
const path = output.subfolder
? `${output.subfolder}/${output.filename}`
: output.filename
// Add [output] annotation so the preview component knows the type
const annotatedPath = `${path} [output]`
outputs.add(annotatedPath)
}
})
return outputFiles.map((asset) => {
const annotatedPath = `${asset.name} [output]`
return {
id: `output-${annotatedPath}`,
preview_url: asset.preview_url || getMediaUrl(asset.name, 'output'),
name: annotatedPath,
label: getDisplayLabel(annotatedPath)
}
})
return Array.from(outputs).map((output) => ({
id: `output-${output}`,
preview_url: getMediaUrl(output.replace(' [output]', ''), 'output'),
name: output,
label: getDisplayLabel(output)
}))
})
/**
@@ -465,11 +459,18 @@ function getMediaUrl(
filename: string,
type: 'input' | 'output' = 'input'
): string {
if (!['image', 'video'].includes(props.assetKind ?? '')) return ''
if (!['image', 'video', 'audio', 'mesh'].includes(props.assetKind ?? ''))
return ''
const params = new URLSearchParams({ filename, type })
appendCloudResParam(params, filename)
return `/api/view?${params}`
}
function handleIsOpenUpdate(isOpen: boolean) {
if (isOpen && !outputMediaAssets.loading.value) {
void outputMediaAssets.refresh()
}
}
</script>
<template>
@@ -495,6 +496,7 @@ function getMediaUrl(
class="w-full"
@update:selected="updateSelectedItems"
@update:files="handleFilesUpdate"
@update:is-open="handleIsOpenUpdate"
/>
</WidgetLayoutField>
</template>

View File

@@ -90,11 +90,11 @@ const ownershipSelected = defineModel<OwnershipOption>('ownershipSelected', {
const baseModelSelected = defineModel<Set<string>>('baseModelSelected', {
default: () => new Set()
})
const isOpen = defineModel<boolean>('isOpen', { default: false })
const toastStore = useToastStore()
const popoverRef = ref<InstanceType<typeof Popover>>()
const triggerRef = useTemplateRef('triggerRef')
const isOpen = ref(false)
const maxSelectable = computed(() => {
if (multiple === true) return Infinity