From 65b436daa9de8157162b442f5602ebd6cb4e9968 Mon Sep 17 00:00:00 2001 From: Glary-Bot Date: Sun, 17 May 2026 15:53:13 +0000 Subject: [PATCH] fix(widgets): fall back to id when item name is empty string Some remote assets (e.g. /proxy/seedance/assets) return name='' for items the user never titled. Trigger and list rows rendered blank because nullish coalescing (??) only catches null/undefined, not empty strings. Add displayName(item) helper in base/remote/itemSchema.ts using logical-or fallback (matches the FormDropdownInput pattern in PR #11310) and use it in Trigger.vue's selected-label computed and Item.vue's name span, img alt, and video aria-label so the accessibility names also fall back instead of going empty. --- src/base/remote/itemSchema.test.ts | 11 +++++++++++ src/base/remote/itemSchema.ts | 8 ++++++++ .../vueNodes/widgets/components/RemoteCombo/Item.vue | 8 +++++--- .../widgets/components/RemoteCombo/Trigger.vue | 4 +++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/base/remote/itemSchema.test.ts b/src/base/remote/itemSchema.test.ts index 4686c171ab..fd5d9cfff8 100644 --- a/src/base/remote/itemSchema.test.ts +++ b/src/base/remote/itemSchema.test.ts @@ -2,6 +2,7 @@ import { describe, expect, it } from 'vitest' import { buildSearchText, + displayName, extractItems, getByPath, mapToDropdownItem, @@ -341,3 +342,13 @@ describe('mapToDropdownItem preview_url normalization', () => { expect(item.preview_url).toBeUndefined() }) }) + +describe('displayName', () => { + it('returns name when present', () => { + expect(displayName({ id: 'abc', name: 'Cool Asset' })).toBe('Cool Asset') + }) + + it('falls back to id when name is empty string', () => { + expect(displayName({ id: 'abc-123', name: '' })).toBe('abc-123') + }) +}) diff --git a/src/base/remote/itemSchema.ts b/src/base/remote/itemSchema.ts index 68e8daa99c..8ad9966081 100644 --- a/src/base/remote/itemSchema.ts +++ b/src/base/remote/itemSchema.ts @@ -7,6 +7,14 @@ export interface DropdownItemShape { preview_url?: string } +/** + * User-facing label for a dropdown item. Falls back to id when name + * is missing or empty, so trigger/list rows never render blank. + */ +export function displayName(item: DropdownItemShape): string { + return item.name || item.id +} + export function getByPath(obj: unknown, path: string): unknown { return path.split('.').reduce((acc: unknown, key: string) => { if (acc == null) return undefined diff --git a/src/renderer/extensions/vueNodes/widgets/components/RemoteCombo/Item.vue b/src/renderer/extensions/vueNodes/widgets/components/RemoteCombo/Item.vue index 0bbf58ed24..eccafc9219 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/RemoteCombo/Item.vue +++ b/src/renderer/extensions/vueNodes/widgets/components/RemoteCombo/Item.vue @@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n' import { cn } from '@comfyorg/tailwind-utils' +import { displayName } from '@/base/remote/itemSchema' import type { DropdownItemShape } from '@/base/remote/itemSchema' import { itemVariants } from './remoteCombo.variants' @@ -27,6 +28,7 @@ const { t } = useI18n() const isSelected = computed(() => ctx.selectedValue.value === props.item.id) const hasPreview = computed(() => !!props.item.preview_url) +const label = computed(() => displayName(props.item)) const audioEl = useTemplateRef('audioEl') const isPlaying = ref(false) @@ -60,7 +62,7 @@ function handleAudioEnded() {
- {{ item.name }} + {{ label }} { const id = ctx.selectedValue.value if (!id) return props.placeholder ?? t('widgets.uploadSelect.placeholder') const item = ctx.items.value.find((i) => i.id === id) - return item?.name ?? id + return item ? displayName(item) : id }) const computedBorder = computed(() => {