({ repoFullName }: { repoFullName: string })
| 51 | } |
| 52 | |
| 53 | export default function RepositoryKeyFiles({ repoFullName }: { repoFullName: string }) { |
| 54 | const [keyFiles, setKeyFiles] = useState<KeyFile[]>([]); |
| 55 | const [loading, setLoading] = useState(true); |
| 56 | const [error, setError] = useState<string | null>(null); |
| 57 | const [selectedFile, setSelectedFile] = useState<KeyFile | null>(null); |
| 58 | const [isDialogOpen, setIsDialogOpen] = useState(false); |
| 59 | const [fileContent, setFileContent] = useState<string | null>(null); |
| 60 | const [fileContentLoading, setFileContentLoading] = useState(false); |
| 61 | |
| 62 | // Use a global cache on window to persist across remounts/tab switches |
| 63 | const getKeyFilesCache = (): { [key: string]: KeyFile[] } => { |
| 64 | if (typeof window !== 'undefined') { |
| 65 | |
| 66 | if (!(window as any).__keyFilesCache) { |
| 67 | (window as any).__keyFilesCache = {}; |
| 68 | } |
| 69 | |
| 70 | return (window as any).__keyFilesCache; |
| 71 | } |
| 72 | // SSR fallback (shouldn't happen for this component) |
| 73 | return {}; |
| 74 | }; |
| 75 | |
| 76 | useEffect(() => { |
| 77 | // Declare controller and timeoutId in the outer scope so they are accessible in cleanup |
| 78 | let controller: AbortController; |
| 79 | let timeoutId: ReturnType<typeof setTimeout>; |
| 80 | |
| 81 | const fetchKeyFiles = async () => { |
| 82 | if (!repoFullName) return; |
| 83 | const cache = getKeyFilesCache(); |
| 84 | if (cache[repoFullName]) { |
| 85 | setKeyFiles(cache[repoFullName]); |
| 86 | setLoading(false); |
| 87 | return; |
| 88 | } |
| 89 | |
| 90 | // Use AbortController to handle timeouts and cancellations |
| 91 | controller = new AbortController(); |
| 92 | timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout |
| 93 | |
| 94 | setLoading(true); |
| 95 | setError(null); |
| 96 | try { |
| 97 | // Use our API endpoint to get the repository structure |
| 98 | const structureRes = await fetch(`/api/get-repo-structure?repo=${encodeURIComponent(repoFullName)}`); |
| 99 | const structureData = await structureRes.json(); |
| 100 | // Debug: log the structureData for troubleshooting |
| 101 | if (typeof window !== 'undefined') { |
| 102 | // Only log in browser |
| 103 | console.log('Repo structureData:', structureData); |
| 104 | } |
| 105 | // Get the file tree from the structure data |
| 106 | |
| 107 | let files: any[] = []; |
| 108 | if (structureData.fileTree && Array.isArray(structureData.fileTree)) { |
| 109 | // Extract all files from the hierarchical file tree |
| 110 |
nothing calls this directly
no test coverage detected