"use client"; import { useState, useEffect, useCallback } from "react"; import { CodeViewer } from "./code-viewer"; import { Loader2 } from "lucide-react"; const CHUNK_SIZE = 64 * 1024; const LARGE_FILE_THRESHOLD = 100 * 1024; interface ChunkedCodeViewerProps { username: string; repoName: string; branch: string; filePath: string; language: string; initialContent?: string; totalSize?: number; } export function ChunkedCodeViewer({ username, repoName, branch, filePath, language, initialContent, totalSize }: ChunkedCodeViewerProps) { const [content, setContent] = useState(initialContent || ""); const [loading, setLoading] = useState(!initialContent); const [progress, setProgress] = useState(initialContent ? 100 : 0); const [error, setError] = useState(null); const loadFile = useCallback(async () => { if (initialContent) return; setLoading(true); setError(null); try { const response = await fetch(`/api/file/${username}/${repoName}/${branch}/${filePath}`); if (!response.ok) { throw new Error("Failed to load file"); } const size = parseInt(response.headers.get("X-Total-Size") || "0", 10); if (size < LARGE_FILE_THRESHOLD || !response.body) { const text = await response.text(); setContent(text); setProgress(100); setLoading(false); return; } const reader = response.body.getReader(); const decoder = new TextDecoder(); let result = ""; let loaded = 0; while (true) { const { done, value } = await reader.read(); if (done) break; result += decoder.decode(value, { stream: true }); loaded += value.length; setProgress(Math.min(Math.round((loaded / size) * 100), 100)); setContent(result); } result += decoder.decode(); setContent(result); setProgress(100); } catch (err) { setError(err instanceof Error ? err.message : "Failed to load file"); } finally { setLoading(false); } }, [username, repoName, branch, filePath, initialContent]); useEffect(() => { loadFile(); }, [loadFile]); if (error) { return (

{error}

); } return (
{loading && progress < 100 && (
{progress}%
)} {content ? ( ) : (
)}
); }