From 8f07468fdde00f910116f4925249e075c8dc96a4 Mon Sep 17 00:00:00 2001 From: Rizumu Ayaka Date: Fri, 13 Mar 2026 04:43:33 +0800 Subject: [PATCH] fix: dropdown widget fetching output files (#6734) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../components/WidgetSelectDropdown.vue | 60 ++++++++++--------- .../components/form/dropdown/FormDropdown.vue | 2 +- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue index 5930b0f37d..e26aa7d086 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/WidgetSelectDropdown.vue @@ -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({ const { t } = useI18n() const toastStore = useToastStore() -const queueStore = useQueueStore() + +const outputMediaAssets = useMediaAssets('output') const transformCompatProps = useTransformCompatOverlayProps() @@ -147,36 +149,28 @@ const inputItems = computed(() => { label: getDisplayLabel(String(value)) })) }) +function assetKindToMediaType(kind: AssetKind): string { + return kind === 'mesh' ? '3D' : kind +} + const outputItems = computed(() => { - if (!['image', 'video', 'mesh'].includes(props.assetKind ?? '')) return [] + if (!['image', 'video', 'audio', 'mesh'].includes(props.assetKind ?? '')) + return [] - const outputs = new Set() + 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() + } +} diff --git a/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue b/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue index a9574e566f..37d8b24352 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/FormDropdown.vue @@ -90,11 +90,11 @@ const ownershipSelected = defineModel('ownershipSelected', { const baseModelSelected = defineModel>('baseModelSelected', { default: () => new Set() }) +const isOpen = defineModel('isOpen', { default: false }) const toastStore = useToastStore() const popoverRef = ref>() const triggerRef = useTemplateRef('triggerRef') -const isOpen = ref(false) const maxSelectable = computed(() => { if (multiple === true) return Infinity