From 93f07e88771f8283f8ccfed119b27feeb5f5adf2 Mon Sep 17 00:00:00 2001 From: pa Date: Tue, 17 Mar 2026 21:22:01 +0900 Subject: [PATCH] fix: Override Command filter for all queries so Worker results are not hidden, maybe --- src/components/QuickSearchSync.vue | 45 ++++++++++++++----- .../__tests__/QuickSearchSync.test.js | 14 ++++++ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/components/QuickSearchSync.vue b/src/components/QuickSearchSync.vue index 26fe8acc..48368e9e 100644 --- a/src/components/QuickSearchSync.vue +++ b/src/components/QuickSearchSync.vue @@ -9,8 +9,9 @@ * Renderless bridge component — must live inside the Command context. * Watches filterState.search (set by CommandInput) and syncs it * to the global search store's query ref. - * Also overrides the built-in filter when query < 2 chars so that - * hint category items remain visible. + * Overrides the built-in Command filter so that visibility is fully + * controlled by the Worker search results (which handle confusable + * characters, diacritics, and locale-aware matching). */ import { nextTick, watch } from 'vue'; import { useCommand } from '@/components/ui/command'; @@ -20,23 +21,43 @@ const { filterState, allItems, allGroups } = useCommand(); const quickSearchStore = useQuickSearchStore(); + function overrideFilter() { + for (const id of allItems.value.keys()) { + filterState.filtered.items.set(id, 1); + } + filterState.filtered.count = allItems.value.size; + for (const groupId of allGroups.value.keys()) { + filterState.filtered.groups.add(groupId); + } + } + watch( () => filterState.search, async (value) => { quickSearchStore.setQuery(value); - // When query < 2 chars, override the built-in filter - // so all items (hint categories) stay visible - if (value && value.length < 2) { + // Override the built-in Command filter for all queries. + // The Worker already handles confusable-character normalization + // and locale-aware matching; the Command's built-in useFilter + // (which uses a plain Intl.Collator) would otherwise hide + // results that the Worker correctly matched via confusables. + if (value) { await nextTick(); - for (const id of allItems.value.keys()) { - filterState.filtered.items.set(id, 1); - } - filterState.filtered.count = allItems.value.size; - for (const groupId of allGroups.value.keys()) { - filterState.filtered.groups.add(groupId); - } + overrideFilter(); } + + // [OLD] Only override when query < 2 chars (hint categories). + // If above approach causes issues, revert to this: + // if (value && value.length < 2) { + // await nextTick(); + // for (const id of allItems.value.keys()) { + // filterState.filtered.items.set(id, 1); + // } + // filterState.filtered.count = allItems.value.size; + // for (const groupId of allGroups.value.keys()) { + // filterState.filtered.groups.add(groupId); + // } + // } } ); diff --git a/src/components/__tests__/QuickSearchSync.test.js b/src/components/__tests__/QuickSearchSync.test.js index d9f60ee0..89d0c64d 100644 --- a/src/components/__tests__/QuickSearchSync.test.js +++ b/src/components/__tests__/QuickSearchSync.test.js @@ -55,4 +55,18 @@ describe('QuickSearchSync.vue', () => { expect(mocks.filterState.filtered.items.get('a')).toBe(1); expect(mocks.filterState.filtered.groups.has('g1')).toBe(true); }); + + it('overrides Command filter for longer queries so Worker results are not hidden', async () => { + mount(QuickSearchSync); + + mocks.filterState.search = 'rene'; + await Promise.resolve(); + await Promise.resolve(); + + expect(mocks.setQuery).toHaveBeenCalledWith('rene'); + expect(mocks.filterState.filtered.count).toBe(2); + expect(mocks.filterState.filtered.items.get('a')).toBe(1); + expect(mocks.filterState.filtered.items.get('b')).toBe(1); + expect(mocks.filterState.filtered.groups.has('g1')).toBe(true); + }); });