diff --git a/app/pages/search.vue b/app/pages/search.vue index dcb285382..71537cf2d 100644 --- a/app/pages/search.vue +++ b/app/pages/search.vue @@ -8,7 +8,6 @@ import { isPlatformSpecificPackage } from '~/utils/platform-packages' import { normalizeSearchParam } from '#shared/utils/url' const route = useRoute() -const router = useRouter() // Preferences (persisted to localStorage) const { @@ -21,13 +20,16 @@ const { } = usePackageListPreferences() // Debounced URL update for page (less aggressive to avoid too many URL changes) +//Use History API directly to update URL without triggering Router's scroll-to-top const updateUrlPage = debounce((page: number) => { - router.replace({ - query: { - ...route.query, - page: page > 1 ? page : undefined, - }, - }) + const url = new URL(window.location.href) + if (page > 1) { + url.searchParams.set('page', page.toString()) + } else { + url.searchParams.delete('page') + } + // This updates the address bar "silently" + window.history.replaceState(window.history.state, '', url) }, 500) const { model: searchQuery, provider: searchProvider } = useGlobalSearch() @@ -269,6 +271,9 @@ async function loadMore() { currentPage.value++ await fetchMore(requestedSize.value) } +onBeforeUnmount(() => { + updateUrlPage.cancel() +}) // Update URL when page changes from scrolling function handlePageChange(page: number) { @@ -276,7 +281,8 @@ function handlePageChange(page: number) { } // Reset page when query changes -watch(query, () => { +watch(query, (newQuery, oldQuery) => { + if (newQuery.trim() === (oldQuery || '').trim()) return currentPage.value = 1 hasInteracted.value = true }) @@ -390,20 +396,24 @@ const totalSelectableCount = computed(() => suggestionCount.value + resultCount. * Get all focusable result elements in DOM order (suggestions first, then packages) */ function getFocusableElements(): HTMLElement[] { - const suggestions = Array.from( - document.querySelectorAll('[data-suggestion-index]'), - ).sort((a, b) => { - const aIdx = Number.parseInt(a.dataset.suggestionIndex ?? '0', 10) - const bIdx = Number.parseInt(b.dataset.suggestionIndex ?? '0', 10) - return aIdx - bIdx - }) - const packages = Array.from(document.querySelectorAll('[data-result-index]')).sort( - (a, b) => { + const isVisible = (el: HTMLElement) => el.getClientRects().length > 0 + + const suggestions = Array.from(document.querySelectorAll('[data-suggestion-index]')) + .filter(isVisible) + .sort((a, b) => { + const aIdx = Number.parseInt(a.dataset.suggestionIndex ?? '0', 10) + const bIdx = Number.parseInt(b.dataset.suggestionIndex ?? '0', 10) + return aIdx - bIdx + }) + + const packages = Array.from(document.querySelectorAll('[data-result-index]')) + .filter(isVisible) + .sort((a, b) => { const aIdx = Number.parseInt(a.dataset.resultIndex ?? '0', 10) const bIdx = Number.parseInt(b.dataset.resultIndex ?? '0', 10) return aIdx - bIdx - }, - ) + }) + return [...suggestions, ...packages] } @@ -536,7 +546,7 @@ defineOgImageComponent('Default', { + +