"use client"; import { useEffect, useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import Editor from "@monaco-editor/react"; import { useEditor } from "@/hooks/useEditor"; const TEXT_EXT = ["js","ts","tsx","jsx","json","md","css","html","txt","mjs","cjs","tsconfig","eslintrc","prettierrc"]; function isTextFile(path: string) { const ext = (path.split('.').pop() || '').toLowerCase(); return TEXT_EXT.includes(ext) || path.endsWith('.d.ts'); } export function FilesExplorerButton() { const [open, setOpen] = useState(false); return ( <> {open && setOpen(false)} />} ); } function FilesExplorer({ open, onClose }: { open: boolean; onClose: () => void }) { const { project } = useEditor(); const space = project?.space_id || ''; const [namespace, repoId] = space.split('/'); const [paths, setPaths] = useState<{ path: string; type: string }[]>([]); const [selected, setSelected] = useState(null); const [content, setContent] = useState(''); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const canSave = useMemo(() => !!selected && isTextFile(selected!), [selected]); useEffect(() => { (async () => { if (!namespace || !repoId) return; const res = await fetch(`/api/me/projects/${namespace}/${repoId}/files`); const data = await res.json(); if (data?.ok) setPaths(data.paths || []); })(); }, [namespace, repoId]); const openFile = async (p: string) => { setSelected(p); setContent(''); setLoading(true); try { if (isTextFile(p)) { const res = await fetch(`/api/me/projects/${namespace}/${repoId}/file?path=${encodeURIComponent(p)}`); const data = await res.json(); if (data?.ok) setContent(data.content || ''); } } finally { setLoading(false); } }; const saveFile = async () => { if (!selected) return; setSaving(true); try { const res = await fetch(`/api/me/projects/${namespace}/${repoId}/apply`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ files: [{ path: selected, action: 'update', content }], commitTitle: `Edit ${selected}` }) }); await res.json(); } finally { setSaving(false); } }; return ( onClose()}> Project Files
    {paths.map(p => (
  • openFile(p.path)}> {p.path}
  • ))}
{!selected &&
Select a file to preview/edit
} {selected && isTextFile(selected) && ( {loading ? 'Loading…' : ''}
} onChange={(v) => setContent(v || '')} options={{ minimap: { enabled: false }, wordWrap: 'on' }} /> )} {selected && !isTextFile(selected) && (
Binary/non-text file. Download/edit locally if needed.
)}
); }