"use client"; import { useEffect, useState } from "react"; import { highlight } from "sugar-high"; import { getFileContent } from "~/utils/git"; export type FileViewerProps = { path: string; gitRef: string; }; export function FileViewer({ path, gitRef }: FileViewerProps) { const [content, setContent] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { let active = true; setLoading(true); setError(null); getFileContent({ data: { ref: gitRef, path } }) .then((nextContent: string) => { if (!active) return; setContent(nextContent); }) .catch((error: unknown) => { if (!active) return; setError(error instanceof Error && error.message ? error.message : "Failed to load file"); }) .finally(() => { if (active) { setLoading(false); } }); return () => { active = false; }; }, [path, gitRef]); if (loading) { return
Loading…
; } if (error) { return
{error}
; } const isBinary = content !== null && content.includes("\x00"); return (
{path} {content && {content.split("\n").length} lines}
{isBinary ? (
Binary file
) : ( )}
); } function HighlightedCode({ code }: { code: string }) { const html = highlight(code); const lines = html.split("\n"); return (
{lines.map((line, i) => ( // oxlint-disable-next-line react/no-array-index-key -- source lines are static and never reordered; index is the line number ))}
{i + 1}
); }