From 55c42ee484255e8c4e93a048fc5624c7e1e48b50 Mon Sep 17 00:00:00 2001 From: jaeone94 <89377375+jaeone94@users.noreply.github.com> Date: Thu, 12 Mar 2026 20:40:44 +0900 Subject: [PATCH] [bugfix] Asset widget search matches display label (#9774) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Asset widget dropdown search only matched against `item.name` (filename), but users see `item.label` (display name). Now searches both fields so filtering matches what is visually displayed. ## Changes - **What**: `defaultSearcher` in `FormDropdown` now matches against both `name` and `label` fields - Added 3 unit tests covering label-based search scenarios ## Review Focus - The change only affects cloud asset mode where `name` (filename) and `label` (display name) differ. In local mode, `label` is either `undefined` or identical to `name`, so behavior is unchanged. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9774-bugfix-Asset-widget-search-matches-display-label-3216d73d365081ca8befdf7260c66a26) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action --- .../components/form/dropdown/shared.test.ts | 25 +++++++++++++++++++ .../components/form/dropdown/shared.ts | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.test.ts b/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.test.ts index d3bb88f3ad..5ad5911b33 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.test.ts +++ b/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.test.ts @@ -51,6 +51,31 @@ describe('defaultSearcher', () => { const result = await defaultSearcher('xyz', items) expect(result).toHaveLength(0) }) + + it('matches against label when provided', async () => { + const itemsWithLabels = [ + createItem('model_v1.safetensors', 'My Cool Model'), + createItem('lora_v2.safetensors', 'Style Transfer LoRA'), + createItem('checkpoint.ckpt', 'Realistic Vision') + ] + const result = await defaultSearcher('cool', itemsWithLabels) + expect(result).toHaveLength(1) + expect(result[0].name).toBe('model_v1.safetensors') + }) + + it('matches by label case-insensitively', async () => { + const itemsWithLabels = [createItem('file.safetensors', 'My Cool Model')] + const result = await defaultSearcher('MY COOL', itemsWithLabels) + expect(result).toHaveLength(1) + }) + + it('matches when word is in name or label', async () => { + const itemsWithLabels = [ + createItem('sd_v15.safetensors', 'Stable Diffusion 1.5') + ] + const result = await defaultSearcher('stable', itemsWithLabels) + expect(result).toHaveLength(1) + }) }) describe('getDefaultSortOptions', () => { diff --git a/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.ts b/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.ts index 4717b8870c..b65a6aeb74 100644 --- a/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.ts +++ b/src/renderer/extensions/vueNodes/widgets/components/form/dropdown/shared.ts @@ -12,7 +12,8 @@ export async function defaultSearcher( const words = query.trim().toLowerCase().split(' ') return items.filter((item) => { const name = item.name.toLowerCase() - return words.every((word) => name.includes(word)) + const label = item.label?.toLowerCase() ?? '' + return words.every((word) => name.includes(word) || label.includes(word)) }) }