Skip to content

Commit 8db4429

Browse files
committed
refactor: don't use setTimeout, but watch results
1 parent e1c5f04 commit 8db4429

1 file changed

Lines changed: 43 additions & 32 deletions

File tree

app/pages/search.vue

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -541,46 +541,57 @@ function focusElement(el: HTMLElement) {
541541
el.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
542542
}
543543
544-
// Find latest package name
545-
function findLatestPackageName() {
546-
const packageName = displayResults.value?.[0]?.package.name
547-
if (packageName === query.value) {
548-
return packageName.split('/')
549-
}
550-
}
551-
552544
// Navigate to package page
553-
const navigateToPackage = debounce((packageName?: string[]) => {
554-
router.push({
545+
async function navigateToPackage(packageName: string) {
546+
await navigateTo({
555547
name: 'package',
556-
params: { package: packageName },
548+
params: { package: packageName.split('/') },
557549
})
558-
}, 500)
550+
}
551+
552+
// Track the input value when user pressed Enter (for navigating when results arrive)
553+
const pendingEnterQuery = shallowRef<string | null>(null)
554+
555+
// Watch for results to navigate when Enter was pressed before results arrived
556+
watch(displayResults, results => {
557+
if (!pendingEnterQuery.value) return
558+
559+
// Check if input is still focused (user hasn't started navigating or clicked elsewhere)
560+
if (document.activeElement?.tagName !== 'INPUT') {
561+
pendingEnterQuery.value = null
562+
return
563+
}
564+
565+
// Navigate if first result matches the query that was entered
566+
const firstResult = results[0]
567+
// eslint-disable-next-line no-console
568+
console.log('[search] watcher fired', {
569+
pending: pendingEnterQuery.value,
570+
firstResult: firstResult?.package.name,
571+
})
572+
if (firstResult?.package.name === pendingEnterQuery.value) {
573+
pendingEnterQuery.value = null
574+
navigateToPackage(firstResult.package.name)
575+
}
576+
})
559577
560578
function handleResultsKeydown(e: KeyboardEvent) {
561-
// If the active element is an input and there are results, navigate to the first result
579+
// If the active element is an input, navigate to exact match or wait for results
562580
if (e.key === 'Enter' && document.activeElement?.tagName === 'INPUT') {
563-
// After entering quickly and pressing Enter, find the latest packages
564-
const latestPackageName = findLatestPackageName()
565-
// Find successful . navigate to package page
566-
if (latestPackageName) return navigateToPackage(latestPackageName)
567-
// Waiting for the latest search results (maximum 1.5 seconds)
568-
let waitSearchResultInterval: ReturnType<typeof setInterval> | null
569-
function clearSearchResultInterval() {
570-
if (waitSearchResultInterval) clearInterval(waitSearchResultInterval)
571-
waitSearchResultInterval = null
581+
// Get value directly from input (not from route query, which may be debounced)
582+
const inputValue = (document.activeElement as HTMLInputElement).value.trim()
583+
if (!inputValue) return
584+
585+
// Check if first result matches the input value exactly
586+
const firstResult = displayResults.value[0]
587+
if (firstResult?.package.name === inputValue) {
588+
pendingEnterQuery.value = null
589+
return navigateToPackage(firstResult.package.name)
572590
}
573-
waitSearchResultInterval = setInterval(() => {
574-
const latestPackageName = findLatestPackageName()
575-
if (latestPackageName) {
576-
clearSearchResultInterval()
577-
return navigateToPackage(latestPackageName)
578-
}
579-
}, 100)
580591
581-
setTimeout(() => {
582-
clearSearchResultInterval()
583-
}, 1500)
592+
// No match yet - store input value, watcher will handle navigation when results arrive
593+
pendingEnterQuery.value = inputValue
594+
return
584595
}
585596
586597
if (totalSelectableCount.value <= 0) return

0 commit comments

Comments
 (0)