fix: Override Command filter for all queries so Worker results are not hidden, maybe

This commit is contained in:
pa
2026-03-17 21:22:01 +09:00
parent 62a76330ca
commit 93f07e8877
2 changed files with 47 additions and 12 deletions

View File

@@ -9,8 +9,9 @@
* Renderless bridge component — must live inside the Command context. * Renderless bridge component — must live inside the Command context.
* Watches filterState.search (set by CommandInput) and syncs it * Watches filterState.search (set by CommandInput) and syncs it
* to the global search store's query ref. * to the global search store's query ref.
* Also overrides the built-in filter when query < 2 chars so that * Overrides the built-in Command filter so that visibility is fully
* hint category items remain visible. * controlled by the Worker search results (which handle confusable
* characters, diacritics, and locale-aware matching).
*/ */
import { nextTick, watch } from 'vue'; import { nextTick, watch } from 'vue';
import { useCommand } from '@/components/ui/command'; import { useCommand } from '@/components/ui/command';
@@ -20,23 +21,43 @@
const { filterState, allItems, allGroups } = useCommand(); const { filterState, allItems, allGroups } = useCommand();
const quickSearchStore = useQuickSearchStore(); 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( watch(
() => filterState.search, () => filterState.search,
async (value) => { async (value) => {
quickSearchStore.setQuery(value); quickSearchStore.setQuery(value);
// When query < 2 chars, override the built-in filter // Override the built-in Command filter for all queries.
// so all items (hint categories) stay visible // The Worker already handles confusable-character normalization
if (value && value.length < 2) { // 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(); await nextTick();
for (const id of allItems.value.keys()) { overrideFilter();
filterState.filtered.items.set(id, 1);
}
filterState.filtered.count = allItems.value.size;
for (const groupId of allGroups.value.keys()) {
filterState.filtered.groups.add(groupId);
}
} }
// [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);
// }
// }
} }
); );
</script> </script>

View File

@@ -55,4 +55,18 @@ describe('QuickSearchSync.vue', () => {
expect(mocks.filterState.filtered.items.get('a')).toBe(1); expect(mocks.filterState.filtered.items.get('a')).toBe(1);
expect(mocks.filterState.filtered.groups.has('g1')).toBe(true); 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);
});
}); });