From b09def9ddd5e9f6e911bbbac12ab2e3fd547c9d2 Mon Sep 17 00:00:00 2001 From: bkellam Date: Tue, 18 Nov 2025 11:58:36 -0800 Subject: [PATCH] fix filter --- .../components/searchResultsPanel/index.tsx | 44 +++++++++++-------- .../api/(server)/stream_search/transformer.ts | 34 +++++++------- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx b/packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx index 978a254d..aa5efdf8 100644 --- a/packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx +++ b/packages/web/src/app/[domain]/search/components/searchResultsPanel/index.tsx @@ -1,10 +1,11 @@ 'use client'; import { RepositoryInfo, SearchResultFile } from "@/features/search/types"; -import { FileMatchContainer, MAX_MATCHES_TO_PREVIEW } from "./fileMatchContainer"; import { useVirtualizer, VirtualItem } from "@tanstack/react-virtual"; -import { useCallback, useEffect, useImperativeHandle, useRef, useState, forwardRef } from "react"; import { useDebounce } from "@uidotdev/usehooks"; +import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef } from "react"; +import { useMap } from "usehooks-ts"; +import { FileMatchContainer, MAX_MATCHES_TO_PREVIEW } from "./fileMatchContainer"; interface SearchResultsPanelProps { fileMatches: SearchResultFile[]; @@ -26,7 +27,15 @@ const ESTIMATED_MATCH_CONTAINER_HEIGHT_PX = 30; type ScrollHistoryState = { scrollOffset?: number; measurementsCache?: VirtualItem[]; - showAllMatchesStates?: boolean[]; + showAllMatchesMap?: [string, boolean][]; +} + +/** + * Unique key for a given file match. Used to store the "show all matches" state for a + * given file match. + */ +const getFileMatchKey = (fileMatch: SearchResultFile) => { + return `${fileMatch.repository}-${fileMatch.fileName.text}`; } export const SearchResultsPanel = forwardRef(({ @@ -46,17 +55,17 @@ export const SearchResultsPanel = forwardRef(restoreShowAllMatchesStates || []); const virtualizer = useVirtualizer({ count: fileMatches.length, getScrollElement: () => parentRef.current, estimateSize: (index) => { const fileMatch = fileMatches[index]; - const showAllMatches = showAllMatchesStates[index]; + const showAllMatches = showAllMatchesMap.get(getFileMatchKey(fileMatch)); // Quick guesstimation ;) This needs to be quick since the virtualizer will // run this upfront for all items in the list. @@ -78,7 +87,6 @@ export const SearchResultsPanel = forwardRef { - setShowAllMatchesStates(Array(fileMatches.length).fill(false)); virtualizer.scrollToIndex(0); }, [fileMatches.length, virtualizer]); @@ -89,24 +97,22 @@ export const SearchResultsPanel = forwardRef { history.replaceState( { scrollOffset: debouncedScrollOffset ?? undefined, measurementsCache: virtualizer.measurementsCache, - showAllMatchesStates, + showAllMatchesMap: Array.from(showAllMatchesMap.entries()), } satisfies ScrollHistoryState, '', window.location.href ); - }, [debouncedScrollOffset, virtualizer.measurementsCache, showAllMatchesStates]); + }, [debouncedScrollOffset, virtualizer.measurementsCache, showAllMatchesMap]); - const onShowAllMatchesButtonClicked = useCallback((index: number) => { - const states = [...showAllMatchesStates]; - const wasShown = states[index]; - states[index] = !wasShown; - setShowAllMatchesStates(states); + const onShowAllMatchesButtonClicked = useCallback((fileMatchKey: string, index: number) => { + const wasShown = showAllMatchesMap.get(fileMatchKey) ?? false; + showAllMatchesActions.set(fileMatchKey, !wasShown); // When collapsing, scroll to the top of the file match container. This ensures // that the focused "show fewer matches" button is visible. @@ -115,7 +121,7 @@ export const SearchResultsPanel = forwardRef { onOpenFilePreview(file, matchIndex); }} - showAllMatches={showAllMatchesStates[virtualRow.index]} + showAllMatches={showAllMatchesMap.get(getFileMatchKey(file)) ?? false} onShowAllMatchesButtonClicked={() => { - onShowAllMatchesButtonClicked(virtualRow.index); + onShowAllMatchesButtonClicked(getFileMatchKey(file), virtualRow.index); }} isBranchFilteringEnabled={isBranchFilteringEnabled} repoInfo={repoInfo} @@ -181,4 +187,4 @@ export const SearchResultsPanel = forwardRef