sourcebot/packages/web/src/app/[domain]/search/components/codePreviewPanel/index.tsx
Brendan Kellam f3a8fa3dab
Some checks failed
Publish to ghcr / build (linux/amd64, blacksmith-4vcpu-ubuntu-2404) (push) Has been cancelled
Publish to ghcr / build (linux/arm64, blacksmith-8vcpu-ubuntu-2204-arm) (push) Has been cancelled
Update Roadmap Released / update (push) Has been cancelled
Publish to ghcr / merge (push) Has been cancelled
feat(web): Streamed code search (#623)
* generate protobuf types

* stream poc over SSE

* wip: make stream search api follow existing schema. Modify UI to support streaming

* fix scrolling issue

* Dockerfile

* wip on lezer parser grammar for query language

* add lezer tree -> grpc transformer

* remove spammy log message

* fix syntax highlighting by adding a module resolution for @lezer/common

* further wip on query language

* Add case sensitivity and regexp toggles

* Improved type safety / cleanup for query lang

* support search contexts

* update Dockerfile with query langauge package

* fix filter

* Add skeletons to filter panel when search is streaming

* add client side caching

* improved cancelation handling

* add isSearchExausted flag for flagging when a search captured all results

* Add back posthog search_finished event

* remove zoekt tenant enforcement

* migrate blocking search over to grpc. Centralize everything in searchApi

* branch handling

* plumb file weburl

* add repo_sets filter for repositories a user has access to

* refactor a bunch of stuff + add support for passing in Query IR to search api

* refactor

* dev README

* wip on better error handling

* error handling for stream path

* update mcp

* changelog wip

* type fix

* style

* Support rev:* wildcard

* changelog

* changelog nit

* feedback

* fix build

* update docs and remove uneeded test file
2025-11-22 15:33:31 -08:00

74 lines
No EOL
2.4 KiB
TypeScript

'use client';
import { useQuery } from "@tanstack/react-query";
import { CodePreview } from "./codePreview";
import { SearchResultFile } from "@/features/search";
import { SymbolIcon } from "@radix-ui/react-icons";
import { SetStateAction, Dispatch, useMemo } from "react";
import { unwrapServiceError } from "@/lib/utils";
import { getFileSource } from "@/app/api/(client)/client";
interface CodePreviewPanelProps {
previewedFile: SearchResultFile;
selectedMatchIndex: number;
onClose: () => void;
onSelectedMatchIndexChange: Dispatch<SetStateAction<number>>;
}
export const CodePreviewPanel = ({
previewedFile,
selectedMatchIndex,
onClose,
onSelectedMatchIndexChange,
}: CodePreviewPanelProps) => {
// If there are multiple branches pointing to the same revision of this file, it doesn't
// matter which branch we use here, so use the first one.
const branch = useMemo(() => {
return previewedFile.branches && previewedFile.branches.length > 0 ? previewedFile.branches[0] : undefined;
}, [previewedFile]);
const { data: file, isLoading, isPending, isError } = useQuery({
queryKey: ["source", previewedFile, branch],
queryFn: () => unwrapServiceError(
getFileSource({
fileName: previewedFile.fileName.text,
repository: previewedFile.repository,
branch,
})
),
select: (data) => {
return {
content: data.source,
filepath: previewedFile.fileName.text,
matches: previewedFile.chunks,
link: previewedFile.webUrl,
language: previewedFile.language,
revision: branch ?? "HEAD",
};
}
});
if (isLoading || isPending) {
return <div className="flex flex-col items-center justify-center h-full">
<SymbolIcon className="h-6 w-6 animate-spin" />
<p className="font-semibold text-center">Loading...</p>
</div>
}
if (isError) {
return (
<p>Failed to load file source</p>
)
}
return (
<CodePreview
file={file}
repoName={previewedFile.repository}
selectedMatchIndex={selectedMatchIndex}
onSelectedMatchIndexChange={onSelectedMatchIndexChange}
onClose={onClose}
/>
)
}