sourcebot/packages/web/src/app/components/searchBar/useSuggestionsData.ts

147 lines
4.6 KiB
TypeScript
Raw Normal View History

2024-11-24 21:58:05 +00:00
'use client';
import { useQuery } from "@tanstack/react-query";
import { Suggestion, SuggestionMode } from "./searchSuggestionsBox";
import { getRepos, search } from "@/app/api/(client)/client";
import { useMemo } from "react";
2024-11-28 21:26:27 +00:00
import { Symbol } from "@/lib/types";
2024-11-24 21:58:05 +00:00
import languages from "./languages";
2024-11-28 21:26:27 +00:00
import {
VscSymbolClass,
VscSymbolConstant,
VscSymbolEnum,
VscSymbolField,
VscSymbolInterface,
VscSymbolMethod,
VscSymbolProperty,
VscSymbolStructure,
VscSymbolVariable
} from "react-icons/vsc";
2024-11-24 21:58:05 +00:00
interface Props {
suggestionMode: SuggestionMode;
suggestionQuery: string;
}
/**
* Fetches suggestions for the search bar.
*/
export const useSuggestionsData = ({
suggestionMode,
suggestionQuery,
}: Props) => {
2024-11-28 21:26:27 +00:00
const { data: repoSuggestions, isLoading: _isLoadingRepos } = useQuery({
2024-11-24 21:58:05 +00:00
queryKey: ["repoSuggestions"],
queryFn: getRepos,
select: (data): Suggestion[] => {
return data.List.Repos
.map(r => r.Repository)
.map(r => ({
value: r.Name
}));
},
enabled: suggestionMode === "repo",
});
2024-11-28 21:26:27 +00:00
const isLoadingRepos = useMemo(() => suggestionMode === "repo" && _isLoadingRepos, [_isLoadingRepos, suggestionMode]);
2024-11-24 21:58:05 +00:00
2024-11-28 21:26:27 +00:00
const { data: fileSuggestions, isLoading: _isLoadingFiles } = useQuery({
2024-11-24 21:58:05 +00:00
queryKey: ["fileSuggestions", suggestionQuery],
queryFn: () => search({
query: `file:${suggestionQuery}`,
maxMatchDisplayCount: 15,
}),
select: (data): Suggestion[] => {
return data.Result.Files?.map((file) => ({
value: file.FileName
})) ?? [];
},
enabled: suggestionMode === "file"
});
2024-11-28 21:26:27 +00:00
const isLoadingFiles = useMemo(() => suggestionMode === "file" && _isLoadingFiles, [_isLoadingFiles, suggestionMode]);
const { data: symbolSuggestions, isLoading: _isLoadingSymbols } = useQuery({
queryKey: ["symbolSuggestions", suggestionQuery],
queryFn: () => search({
query: `sym:${suggestionQuery.length > 0 ? suggestionQuery : ".*"}`,
maxMatchDisplayCount: 15,
}),
select: (data): Suggestion[] => {
const symbols = data.Result.Files?.flatMap((file) => file.ChunkMatches).flatMap((chunk) => chunk.SymbolInfo ?? []);
if (!symbols) {
return [];
}
// De-duplicate on symbol name & kind.
const symbolMap = new Map<string, Symbol>(symbols.map((symbol: Symbol) => [`${symbol.Kind}.${symbol.Sym}`, symbol]));
const suggestions = Array.from(symbolMap.values()).map((symbol) => ({
value: symbol.Sym,
Icon: getSymbolIcon(symbol),
} satisfies Suggestion));
return suggestions;
},
enabled: suggestionMode === "symbol",
});
const isLoadingSymbols = useMemo(() => suggestionMode === "symbol" && _isLoadingSymbols, [suggestionMode, _isLoadingSymbols]);
2024-11-24 21:58:05 +00:00
const languageSuggestions = useMemo((): Suggestion[] => {
return languages.map((lang) => {
const spotlight = [
"Python",
"Java",
"TypeScript",
"Go",
"C++",
"C#"
].includes(lang);
return {
value: lang,
spotlight,
};
});
}, []);
2024-11-28 21:26:27 +00:00
const isLoadingSuggestions = useMemo(() => {
return isLoadingSymbols || isLoadingFiles || isLoadingRepos;
}, [isLoadingFiles, isLoadingRepos, isLoadingSymbols]);
return {
repoSuggestions: repoSuggestions ?? [],
fileSuggestions: fileSuggestions ?? [],
symbolSuggestions: symbolSuggestions ?? [],
languageSuggestions,
isLoadingSuggestions,
}
}
2024-11-24 21:58:05 +00:00
2024-11-28 21:26:27 +00:00
const getSymbolIcon = (symbol: Symbol) => {
switch (symbol.Kind) {
case "methodSpec":
case "method":
case "function":
case "func":
return VscSymbolMethod;
case "variable":
return VscSymbolVariable;
case "class":
return VscSymbolClass;
case "const":
case "macro":
case "constant":
return VscSymbolConstant;
case "property":
return VscSymbolProperty;
case "struct":
return VscSymbolStructure;
case "field":
case "member":
return VscSymbolField;
case "interface":
return VscSymbolInterface;
case "enum":
case "enumerator":
return VscSymbolEnum;
}
2024-11-24 21:58:05 +00:00
}