diff --git a/CHANGELOG.md b/CHANGELOG.md index a121f0de..af677fb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed issue with external source code links being broken for paths with spaces. [#364](https://github.com/sourcebot-dev/sourcebot/pull/364) +- Fixed issue where files would sometimes never load in the code browser. [#365](https://github.com/sourcebot-dev/sourcebot/pull/365) ## [4.5.0] - 2025-06-21 diff --git a/packages/web/src/app/[domain]/browse/[...path]/components/codePreviewPanel.tsx b/packages/web/src/app/[domain]/browse/[...path]/components/codePreviewPanel.tsx index bedd7aed..c25f9a33 100644 --- a/packages/web/src/app/[domain]/browse/[...path]/components/codePreviewPanel.tsx +++ b/packages/web/src/app/[domain]/browse/[...path]/components/codePreviewPanel.tsx @@ -1,63 +1,39 @@ -'use client'; - -import { getCodeHostInfoForRepo, unwrapServiceError } from "@/lib/utils"; -import { useBrowseParams } from "@/app/[domain]/browse/hooks/useBrowseParams"; -import { useQuery } from "@tanstack/react-query"; -import { getFileSource } from "@/features/search/fileSourceApi"; -import { useDomain } from "@/hooks/useDomain"; -import { Loader2 } from "lucide-react"; -import { Separator } from "@/components/ui/separator"; import { getRepoInfoByName } from "@/actions"; -import { cn } from "@/lib/utils"; +import { PathHeader } from "@/app/[domain]/components/pathHeader"; +import { Separator } from "@/components/ui/separator"; +import { getFileSource } from "@/features/search/fileSourceApi"; +import { cn, getCodeHostInfoForRepo, isServiceError } from "@/lib/utils"; import Image from "next/image"; -import { useMemo } from "react"; import { PureCodePreviewPanel } from "./pureCodePreviewPanel"; -import { PathHeader } from "@/app/[domain]/components/pathHeader"; -export const CodePreviewPanel = () => { - const { path, repoName, revisionName } = useBrowseParams(); - const domain = useDomain(); +interface CodePreviewPanelProps { + path: string; + repoName: string; + revisionName?: string; + domain: string; +} - const { data: fileSourceResponse, isPending: isFileSourcePending, isError: isFileSourceError } = useQuery({ - queryKey: ['fileSource', repoName, revisionName, path, domain], - queryFn: () => unwrapServiceError(getFileSource({ +export const CodePreviewPanel = async ({ path, repoName, revisionName, domain }: CodePreviewPanelProps) => { + const [fileSourceResponse, repoInfoResponse] = await Promise.all([ + getFileSource({ fileName: path, repository: repoName, - branch: revisionName - }, domain)), - }); + branch: revisionName, + }, domain), + getRepoInfoByName(repoName, domain), + ]); - const { data: repoInfoResponse, isPending: isRepoInfoPending, isError: isRepoInfoError } = useQuery({ - queryKey: ['repoInfo', repoName, domain], - queryFn: () => unwrapServiceError(getRepoInfoByName(repoName, domain)), - }); - - const codeHostInfo = useMemo(() => { - if (!repoInfoResponse) { - return undefined; - } - - return getCodeHostInfoForRepo({ - codeHostType: repoInfoResponse.codeHostType, - name: repoInfoResponse.name, - displayName: repoInfoResponse.displayName, - webUrl: repoInfoResponse.webUrl, - }); - }, [repoInfoResponse]); - - if (isFileSourcePending || isRepoInfoPending) { - return ( -
- - Loading... -
- ) - } - - if (isFileSourceError || isRepoInfoError) { + if (isServiceError(fileSourceResponse) || isServiceError(repoInfoResponse)) { return
Error loading file source
} + const codeHostInfo = getCodeHostInfoForRepo({ + codeHostType: repoInfoResponse.codeHostType, + name: repoInfoResponse.name, + displayName: repoInfoResponse.displayName, + webUrl: repoInfoResponse.webUrl, + }); + return ( <>
diff --git a/packages/web/src/app/[domain]/browse/[...path]/components/pureTreePreviewPanel.tsx b/packages/web/src/app/[domain]/browse/[...path]/components/pureTreePreviewPanel.tsx new file mode 100644 index 00000000..17860185 --- /dev/null +++ b/packages/web/src/app/[domain]/browse/[...path]/components/pureTreePreviewPanel.tsx @@ -0,0 +1,46 @@ +'use client'; + +import { useCallback, useRef } from "react"; +import { FileTreeItem } from "@/features/fileTree/actions"; +import { FileTreeItemComponent } from "@/features/fileTree/components/fileTreeItemComponent"; +import { useBrowseNavigation } from "../../hooks/useBrowseNavigation"; +import { ScrollArea } from "@/components/ui/scroll-area"; +import { useBrowseParams } from "../../hooks/useBrowseParams"; + +interface PureTreePreviewPanelProps { + items: FileTreeItem[]; +} + +export const PureTreePreviewPanel = ({ items }: PureTreePreviewPanelProps) => { + const { repoName, revisionName } = useBrowseParams(); + const { navigateToPath } = useBrowseNavigation(); + const scrollAreaRef = useRef(null); + + const onNodeClicked = useCallback((node: FileTreeItem) => { + navigateToPath({ + repoName: repoName, + revisionName: revisionName, + path: node.path, + pathType: node.type === 'tree' ? 'tree' : 'blob', + }); + }, [navigateToPath, repoName, revisionName]); + + return ( + + {items.map((item) => ( + onNodeClicked(item)} + parentRef={scrollAreaRef} + /> + ))} + + ) +} \ No newline at end of file diff --git a/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx b/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx index 33336ad3..f2484507 100644 --- a/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx +++ b/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx @@ -1,74 +1,30 @@ -'use client'; -import { Loader2 } from "lucide-react"; import { Separator } from "@/components/ui/separator"; import { getRepoInfoByName } from "@/actions"; import { PathHeader } from "@/app/[domain]/components/pathHeader"; -import { useCallback, useRef } from "react"; -import { FileTreeItem, getFolderContents } from "@/features/fileTree/actions"; -import { FileTreeItemComponent } from "@/features/fileTree/components/fileTreeItemComponent"; -import { useBrowseNavigation } from "../../hooks/useBrowseNavigation"; -import { ScrollArea } from "@/components/ui/scroll-area"; -import { unwrapServiceError } from "@/lib/utils"; -import { useBrowseParams } from "../../hooks/useBrowseParams"; -import { useDomain } from "@/hooks/useDomain"; -import { useQuery } from "@tanstack/react-query"; -import { usePrefetchFileSource } from "@/hooks/usePrefetchFileSource"; -import { usePrefetchFolderContents } from "@/hooks/usePrefetchFolderContents"; - -export const TreePreviewPanel = () => { - const { path } = useBrowseParams(); - const { repoName, revisionName } = useBrowseParams(); - const domain = useDomain(); - const { navigateToPath } = useBrowseNavigation(); - const { prefetchFileSource } = usePrefetchFileSource(); - const { prefetchFolderContents } = usePrefetchFolderContents(); - const scrollAreaRef = useRef(null); - - const { data: repoInfoResponse, isPending: isRepoInfoPending, isError: isRepoInfoError } = useQuery({ - queryKey: ['repoInfo', repoName, domain], - queryFn: () => unwrapServiceError(getRepoInfoByName(repoName, domain)), - }); - - const { data, isPending: isFolderContentsPending, isError: isFolderContentsError } = useQuery({ - queryKey: ['tree', repoName, revisionName, path, domain], - queryFn: () => unwrapServiceError( - getFolderContents({ - repoName, - revisionName: revisionName ?? 'HEAD', - path, - }, domain) - ), - }); - - const onNodeClicked = useCallback((node: FileTreeItem) => { - navigateToPath({ - repoName: repoName, - revisionName: revisionName, - path: node.path, - pathType: node.type === 'tree' ? 'tree' : 'blob', - }); - }, [navigateToPath, repoName, revisionName]); - - const onNodeMouseEnter = useCallback((node: FileTreeItem) => { - if (node.type === 'blob') { - prefetchFileSource(repoName, revisionName ?? 'HEAD', node.path); - } else if (node.type === 'tree') { - prefetchFolderContents(repoName, revisionName ?? 'HEAD', node.path); - } - }, [prefetchFileSource, prefetchFolderContents, repoName, revisionName]); - - if (isFolderContentsPending || isRepoInfoPending) { - return ( -
- - Loading... -
- ) - } - - if (isFolderContentsError || isRepoInfoError) { - return
Error loading tree
+import { getFolderContents } from "@/features/fileTree/actions"; +import { isServiceError } from "@/lib/utils"; +import { PureTreePreviewPanel } from "./pureTreePreviewPanel"; + +interface TreePreviewPanelProps { + path: string; + repoName: string; + revisionName?: string; + domain: string; +} + +export const TreePreviewPanel = async ({ path, repoName, revisionName, domain }: TreePreviewPanelProps) => { + const [repoInfoResponse, folderContentsResponse] = await Promise.all([ + getRepoInfoByName(repoName, domain), + getFolderContents({ + repoName, + revisionName: revisionName ?? 'HEAD', + path, + }, domain) + ]); + + if (isServiceError(folderContentsResponse) || isServiceError(repoInfoResponse)) { + return
Error loading tree preview
} return ( @@ -86,23 +42,7 @@ export const TreePreviewPanel = () => { />
- - {data.map((item) => ( - onNodeClicked(item)} - onMouseEnter={() => onNodeMouseEnter(item)} - parentRef={scrollAreaRef} - /> - ))} - + ) } \ No newline at end of file diff --git a/packages/web/src/app/[domain]/browse/[...path]/page.tsx b/packages/web/src/app/[domain]/browse/[...path]/page.tsx index 3099f816..12689f86 100644 --- a/packages/web/src/app/[domain]/browse/[...path]/page.tsx +++ b/packages/web/src/app/[domain]/browse/[...path]/page.tsx @@ -1,19 +1,44 @@ -'use client'; - -import { useBrowseParams } from "@/app/[domain]/browse/hooks/useBrowseParams"; +import { Suspense } from "react"; +import { getBrowseParamsFromPathParam } from "../hooks/utils"; import { CodePreviewPanel } from "./components/codePreviewPanel"; +import { Loader2 } from "lucide-react"; import { TreePreviewPanel } from "./components/treePreviewPanel"; -export default function BrowsePage() { - const { pathType } = useBrowseParams(); +interface BrowsePageProps { + params: { + path: string[]; + domain: string; + }; +} + +export default async function BrowsePage({ params: { path: _rawPath, domain } }: BrowsePageProps) { + const rawPath = decodeURIComponent(_rawPath.join('/')); + const { repoName, revisionName, path, pathType } = getBrowseParamsFromPathParam(rawPath); + return (
- - {pathType === 'blob' ? ( - - ) : ( - - )} + + + Loading... +
+ }> + {pathType === 'blob' ? ( + + ) : ( + + )} + ) } diff --git a/packages/web/src/app/[domain]/browse/components/fileSearchCommandDialog.tsx b/packages/web/src/app/[domain]/browse/components/fileSearchCommandDialog.tsx index 27e0261f..d87eab85 100644 --- a/packages/web/src/app/[domain]/browse/components/fileSearchCommandDialog.tsx +++ b/packages/web/src/app/[domain]/browse/components/fileSearchCommandDialog.tsx @@ -10,7 +10,6 @@ import { useDomain } from "@/hooks/useDomain"; import { Dialog, DialogContent, DialogDescription, DialogTitle } from "@/components/ui/dialog"; import { useBrowseNavigation } from "../hooks/useBrowseNavigation"; import { useBrowseState } from "../hooks/useBrowseState"; -import { usePrefetchFileSource } from "@/hooks/usePrefetchFileSource"; import { useBrowseParams } from "../hooks/useBrowseParams"; import { FileTreeItemIcon } from "@/features/fileTree/components/fileTreeItemIcon"; import { useLocalStorage } from "usehooks-ts"; @@ -36,7 +35,6 @@ export const FileSearchCommandDialog = () => { const inputRef = useRef(null); const [searchQuery, setSearchQuery] = useState(''); const { navigateToPath } = useBrowseNavigation(); - const { prefetchFileSource } = usePrefetchFileSource(); const [recentlyOpened, setRecentlyOpened] = useLocalStorage(`recentlyOpenedFiles-${repoName}`, []); @@ -122,14 +120,6 @@ export const FileSearchCommandDialog = () => { }); }, [navigateToPath, repoName, revisionName, setRecentlyOpened, updateBrowseState]); - const onMouseEnter = useCallback((file: FileTreeItem) => { - prefetchFileSource( - repoName, - revisionName ?? 'HEAD', - file.path - ); - }, [prefetchFileSource, repoName, revisionName]); - // @note: We were hitting issues when the user types into the input field while the files are still // loading. The workaround was to set `disabled` when loading and then focus the input field when // the files are loaded, hence the `useEffect` below. @@ -181,7 +171,6 @@ export const FileSearchCommandDialog = () => { key={file.path} file={file} onSelect={() => onSelect(file)} - onMouseEnter={() => onMouseEnter(file)} /> ); })} @@ -196,7 +185,6 @@ export const FileSearchCommandDialog = () => { file={file} match={match} onSelect={() => onSelect(file)} - onMouseEnter={() => onMouseEnter(file)} /> ); })} @@ -223,20 +211,17 @@ interface SearchResultComponentProps { to: number; }; onSelect: () => void; - onMouseEnter: () => void; } const SearchResultComponent = ({ file, match, onSelect, - onMouseEnter, }: SearchResultComponentProps) => { return (
diff --git a/packages/web/src/app/[domain]/browse/hooks/useBrowseParams.ts b/packages/web/src/app/[domain]/browse/hooks/useBrowseParams.ts index b671d3fc..d7917f72 100644 --- a/packages/web/src/app/[domain]/browse/hooks/useBrowseParams.ts +++ b/packages/web/src/app/[domain]/browse/hooks/useBrowseParams.ts @@ -1,48 +1,18 @@ -'use client'; - import { usePathname } from "next/navigation"; +import { useMemo } from "react"; +import { getBrowseParamsFromPathParam } from "./utils"; export const useBrowseParams = () => { const pathname = usePathname(); - const startIndex = pathname.indexOf('/browse/'); - if (startIndex === -1) { - throw new Error(`Invalid browse pathname: "${pathname}" - expected to contain "/browse/"`); - } - - const rawPath = pathname.substring(startIndex + '/browse/'.length); - const sentinalIndex = rawPath.search(/\/-\/(tree|blob)\//); - if (sentinalIndex === -1) { - throw new Error(`Invalid browse pathname: "${pathname}" - expected to contain "/-/(tree|blob)/" pattern`); - } - - const repoAndRevisionName = rawPath.substring(0, sentinalIndex).split('@'); - const repoName = repoAndRevisionName[0]; - const revisionName = repoAndRevisionName.length > 1 ? repoAndRevisionName[1] : undefined; - - const { path, pathType } = ((): { path: string, pathType: 'tree' | 'blob' } => { - const path = rawPath.substring(sentinalIndex + '/-/'.length); - const pathType = path.startsWith('tree/') ? 'tree' : 'blob'; - - // @note: decodedURIComponent is needed here incase the path contains a space. - switch (pathType) { - case 'tree': - return { - path: decodeURIComponent(path.substring('tree/'.length)), - pathType, - }; - case 'blob': - return { - path: decodeURIComponent(path.substring('blob/'.length)), - pathType, - }; + return useMemo(() => { + const startIndex = pathname.indexOf('/browse/'); + if (startIndex === -1) { + throw new Error(`Invalid browse pathname: "${pathname}" - expected to contain "/browse/"`); } - })(); - return { - repoName, - revisionName, - path, - pathType, - } -} \ No newline at end of file + const rawPath = pathname.substring(startIndex + '/browse/'.length); + return getBrowseParamsFromPathParam(rawPath); + }, [pathname]); +} + diff --git a/packages/web/src/app/[domain]/browse/hooks/utils.ts b/packages/web/src/app/[domain]/browse/hooks/utils.ts new file mode 100644 index 00000000..a0e423be --- /dev/null +++ b/packages/web/src/app/[domain]/browse/hooks/utils.ts @@ -0,0 +1,37 @@ + +export const getBrowseParamsFromPathParam = (pathParam: string) => { + const sentinalIndex = pathParam.search(/\/-\/(tree|blob)\//); + if (sentinalIndex === -1) { + throw new Error(`Invalid browse pathname: "${pathParam}" - expected to contain "/-/(tree|blob)/" pattern`); + } + + const repoAndRevisionName = pathParam.substring(0, sentinalIndex).split('@'); + const repoName = repoAndRevisionName[0]; + const revisionName = repoAndRevisionName.length > 1 ? repoAndRevisionName[1] : undefined; + + const { path, pathType } = ((): { path: string, pathType: 'tree' | 'blob' } => { + const path = pathParam.substring(sentinalIndex + '/-/'.length); + const pathType = path.startsWith('tree/') ? 'tree' : 'blob'; + + // @note: decodedURIComponent is needed here incase the path contains a space. + switch (pathType) { + case 'tree': + return { + path: decodeURIComponent(path.substring('tree/'.length)), + pathType, + }; + case 'blob': + return { + path: decodeURIComponent(path.substring('blob/'.length)), + pathType, + }; + } + })(); + + return { + repoName, + revisionName, + path, + pathType, + } +} \ No newline at end of file diff --git a/packages/web/src/app/[domain]/components/pathHeader.tsx b/packages/web/src/app/[domain]/components/pathHeader.tsx index d4fd1e74..5118392f 100644 --- a/packages/web/src/app/[domain]/components/pathHeader.tsx +++ b/packages/web/src/app/[domain]/components/pathHeader.tsx @@ -8,8 +8,6 @@ import { useBrowseNavigation } from "../browse/hooks/useBrowseNavigation"; import { Copy, CheckCircle2, ChevronRight, MoreHorizontal } from "lucide-react"; import { useCallback, useState, useMemo, useRef, useEffect } from "react"; import { useToast } from "@/components/hooks/use-toast"; -import { usePrefetchFolderContents } from "@/hooks/usePrefetchFolderContents"; -import { usePrefetchFileSource } from "@/hooks/usePrefetchFileSource"; import { DropdownMenu, DropdownMenuContent, @@ -62,8 +60,6 @@ export const PathHeader = ({ const { navigateToPath } = useBrowseNavigation(); const { toast } = useToast(); const [copied, setCopied] = useState(false); - const { prefetchFolderContents } = usePrefetchFolderContents(); - const { prefetchFileSource } = usePrefetchFileSource(); const containerRef = useRef(null); const breadcrumbsRef = useRef(null); @@ -188,19 +184,6 @@ export const PathHeader = ({ }); }, [repo.name, branchDisplayName, navigateToPath, pathType]); - const onBreadcrumbMouseEnter = useCallback((segment: BreadcrumbSegment) => { - if (segment.isLastSegment && pathType === 'blob') { - prefetchFileSource(repo.name, branchDisplayName ?? 'HEAD', segment.fullPath); - } else { - prefetchFolderContents(repo.name, branchDisplayName ?? 'HEAD', segment.fullPath); - } - }, [ - repo.name, - branchDisplayName, - prefetchFolderContents, - pathType, - prefetchFileSource, - ]); const renderSegmentWithHighlight = (segment: BreadcrumbSegment) => { if (!segment.highlightRange) { @@ -274,7 +257,6 @@ export const PathHeader = ({ onBreadcrumbClick(segment)} - onMouseEnter={() => onBreadcrumbMouseEnter(segment)} className="font-mono text-sm cursor-pointer" > {renderSegmentWithHighlight(segment)} @@ -292,7 +274,6 @@ export const PathHeader = ({ "font-mono text-sm truncate cursor-pointer hover:underline", )} onClick={() => onBreadcrumbClick(segment)} - onMouseEnter={() => onBreadcrumbMouseEnter(segment)} > {renderSegmentWithHighlight(segment)} diff --git a/packages/web/src/ee/features/codeNav/components/exploreMenu/referenceList.tsx b/packages/web/src/ee/features/codeNav/components/exploreMenu/referenceList.tsx index b55edc3f..0458ecbc 100644 --- a/packages/web/src/ee/features/codeNav/components/exploreMenu/referenceList.tsx +++ b/packages/web/src/ee/features/codeNav/components/exploreMenu/referenceList.tsx @@ -8,7 +8,6 @@ import { RepositoryInfo, SourceRange } from "@/features/search/types"; import { useMemo, useRef } from "react"; import useCaptureEvent from "@/hooks/useCaptureEvent"; import { useVirtualizer } from "@tanstack/react-virtual"; -import { usePrefetchFileSource } from "@/hooks/usePrefetchFileSource"; interface ReferenceListProps { data: FindRelatedSymbolsResponse; @@ -31,7 +30,6 @@ export const ReferenceList = ({ const { navigateToPath } = useBrowseNavigation(); const captureEvent = useCaptureEvent(); - const { prefetchFileSource } = usePrefetchFileSource(); // Virtualization setup const parentRef = useRef(null); @@ -120,13 +118,6 @@ export const ReferenceList = ({ highlightRange: match.range, }) }} - // @note: We prefetch the file source when the user hovers over a file. - // This is to try and mitigate having a loading spinner appear when - // the user clicks on a file to open it. - // @see: /browse/[...path]/page.tsx - onMouseEnter={() => { - prefetchFileSource(file.repository, revisionName, file.fileName); - }} /> ))}
@@ -144,7 +135,6 @@ interface ReferenceListItemProps { range: SourceRange; language: string; onClick: () => void; - onMouseEnter: () => void; } const ReferenceListItem = ({ @@ -152,7 +142,6 @@ const ReferenceListItem = ({ range, language, onClick, - onMouseEnter, }: ReferenceListItemProps) => { const highlightRanges = useMemo(() => [range], [range]); @@ -160,7 +149,6 @@ const ReferenceListItem = ({
void, - onMouseEnter: () => void, parentRef: React.RefObject, }) => { const ref = useRef(null); @@ -67,7 +65,6 @@ export const FileTreeItemComponent = ({ } }} onClick={onClick} - onMouseEnter={onMouseEnter} >
& { @@ -44,7 +43,6 @@ export const PureFileTreePanel = ({ tree: _tree, path }: PureFileTreePanelProps) const scrollAreaRef = useRef(null); const { navigateToPath } = useBrowseNavigation(); const { repoName, revisionName } = useBrowseParams(); - const { prefetchFileSource } = usePrefetchFileSource(); // @note: When `_tree` changes, it indicates that a new tree has been loaded. // In that case, we need to rebuild the collapsable tree. @@ -89,18 +87,6 @@ export const PureFileTreePanel = ({ tree: _tree, path }: PureFileTreePanelProps) } }, [setIsCollapsed, navigateToPath, repoName, revisionName]); - // @note: We prefetch the file source when the user hovers over a file. - // This is to try and mitigate having a loading spinner appear when - // the user clicks on a file to open it. - // @see: /browse/[...path]/page.tsx - const onNodeMouseEnter = useCallback((node: FileTreeNode) => { - if (node.type !== 'blob') { - return; - } - - prefetchFileSource(repoName, revisionName ?? 'HEAD', node.path); - }, [prefetchFileSource, repoName, revisionName]); - const renderTree = useCallback((nodes: FileTreeNode, depth = 0): React.ReactNode => { return ( <> @@ -115,7 +101,6 @@ export const PureFileTreePanel = ({ tree: _tree, path }: PureFileTreePanelProps) isCollapsed={node.isCollapsed} isCollapseChevronVisible={node.type === 'tree'} onClick={() => onNodeClicked(node)} - onMouseEnter={() => onNodeMouseEnter(node)} parentRef={scrollAreaRef} /> {node.children.length > 0 && !node.isCollapsed && renderTree(node, depth + 1)} @@ -124,7 +109,7 @@ export const PureFileTreePanel = ({ tree: _tree, path }: PureFileTreePanelProps) })} ); - }, [path, onNodeClicked, onNodeMouseEnter]); + }, [path, onNodeClicked]); const renderedTree = useMemo(() => renderTree(tree), [tree, renderTree]); diff --git a/packages/web/src/hooks/usePrefetchFileSource.ts b/packages/web/src/hooks/usePrefetchFileSource.ts deleted file mode 100644 index de9cce34..00000000 --- a/packages/web/src/hooks/usePrefetchFileSource.ts +++ /dev/null @@ -1,34 +0,0 @@ -'use client'; - -import { useQueryClient } from "@tanstack/react-query"; -import { useDomain } from "./useDomain"; -import { unwrapServiceError } from "@/lib/utils"; -import { getFileSource } from "@/features/search/fileSourceApi"; -import { useDebounceCallback } from "usehooks-ts"; - -interface UsePrefetchFileSourceProps { - debounceDelay?: number; - staleTime?: number; -} - -export const usePrefetchFileSource = ({ - debounceDelay = 200, - staleTime = 5 * 60 * 1000, // 5 minutes -}: UsePrefetchFileSourceProps = {}) => { - const queryClient = useQueryClient(); - const domain = useDomain(); - - const prefetchFileSource = useDebounceCallback((repoName: string, revisionName: string, path: string) => { - queryClient.prefetchQuery({ - queryKey: ['fileSource', repoName, revisionName, path, domain], - queryFn: () => unwrapServiceError(getFileSource({ - fileName: path, - repository: repoName, - branch: revisionName, - }, domain)), - staleTime, - }); - }, debounceDelay); - - return { prefetchFileSource }; -} \ No newline at end of file diff --git a/packages/web/src/hooks/usePrefetchFolderContents.ts b/packages/web/src/hooks/usePrefetchFolderContents.ts deleted file mode 100644 index e135cb7a..00000000 --- a/packages/web/src/hooks/usePrefetchFolderContents.ts +++ /dev/null @@ -1,36 +0,0 @@ -'use client'; - -import { useQueryClient } from "@tanstack/react-query"; -import { useDomain } from "./useDomain"; -import { unwrapServiceError } from "@/lib/utils"; -import { getFolderContents } from "@/features/fileTree/actions"; -import { useDebounceCallback } from "usehooks-ts"; - -interface UsePrefetchFolderContentsProps { - debounceDelay?: number; - staleTime?: number; -} - -export const usePrefetchFolderContents = ({ - debounceDelay = 200, - staleTime = 5 * 60 * 1000, // 5 minutes -}: UsePrefetchFolderContentsProps = {}) => { - const queryClient = useQueryClient(); - const domain = useDomain(); - - const prefetchFolderContents = useDebounceCallback((repoName: string, revisionName: string, path: string) => { - queryClient.prefetchQuery({ - queryKey: ['tree', repoName, revisionName, path, domain], - queryFn: () => unwrapServiceError( - getFolderContents({ - repoName, - revisionName, - path, - }, domain) - ), - staleTime, - }); - }, debounceDelay); - - return { prefetchFolderContents }; -} \ No newline at end of file