feat(codebase): auto-select the best entry point file on load so preview isn't empty
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
* Gitea's web UI on click.
|
||||
*/
|
||||
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import { useEffect, useState, useCallback, useRef } from "react";
|
||||
import { Loader2, AlertCircle } from "lucide-react";
|
||||
import { Tree, Folder, File } from "@/components/ui/file-tree";
|
||||
import { THEME } from "@/components/project/dashboard-ui";
|
||||
@@ -36,6 +36,8 @@ interface GiteaFileTreeProps {
|
||||
onSelectFile?: (path: string) => void;
|
||||
/** Path of the currently-selected file, used to highlight the row. */
|
||||
selectedPath?: string;
|
||||
/** If true, automatically selects the best available file (e.g. page.tsx, package.json) on mount. */
|
||||
autoSelect?: boolean;
|
||||
}
|
||||
|
||||
// ── In-memory cache to persist tree state across tab navigations ──
|
||||
@@ -48,13 +50,45 @@ const treeCache: Record<
|
||||
}
|
||||
> = {};
|
||||
|
||||
function pickBestFile(paths: string[]): string | undefined {
|
||||
const PREFERRED = [
|
||||
"src/app/page.tsx",
|
||||
"src/app/page.jsx",
|
||||
"app/page.tsx",
|
||||
"app/page.jsx",
|
||||
"src/pages/index.tsx",
|
||||
"src/pages/index.jsx",
|
||||
"pages/index.tsx",
|
||||
"pages/index.jsx",
|
||||
"src/App.tsx",
|
||||
"src/App.jsx",
|
||||
"src/main.tsx",
|
||||
"src/main.jsx",
|
||||
"src/index.ts",
|
||||
"src/index.js",
|
||||
"package.json",
|
||||
"README.md",
|
||||
];
|
||||
for (const p of PREFERRED) {
|
||||
if (paths.includes(p)) return p;
|
||||
}
|
||||
const fallbackExts = [".tsx", ".ts", ".jsx", ".js", ".json"];
|
||||
for (const ext of fallbackExts) {
|
||||
const found = paths.find((p) => p.endsWith(ext));
|
||||
if (found) return found;
|
||||
}
|
||||
return paths[0];
|
||||
}
|
||||
|
||||
export function GiteaFileTree({
|
||||
projectId,
|
||||
rootPath,
|
||||
onSelectFile,
|
||||
selectedPath,
|
||||
autoSelect,
|
||||
}: GiteaFileTreeProps) {
|
||||
const cacheKey = `${projectId}::${rootPath}`;
|
||||
const autoSelectedRef = useRef(false);
|
||||
|
||||
const [rootItems, setRootItems] = useState<TreeItem[] | null>(() => {
|
||||
return treeCache[cacheKey]?.rootItems ?? null;
|
||||
@@ -101,7 +135,22 @@ export function GiteaFileTree({
|
||||
// Load root whenever projectId or rootPath changes
|
||||
useEffect(() => {
|
||||
// If we already loaded this from cache on mount, skip fetching again
|
||||
if (treeCache[cacheKey]) return;
|
||||
if (treeCache[cacheKey]) {
|
||||
if (autoSelect && !autoSelectedRef.current && onSelectFile) {
|
||||
autoSelectedRef.current = true;
|
||||
const cached = treeCache[cacheKey];
|
||||
const allItems = [
|
||||
...cached.rootItems,
|
||||
...Object.values(cached.childrenByPath).flat(),
|
||||
];
|
||||
const filePaths = allItems
|
||||
.filter((i) => i.type === "file")
|
||||
.map((i) => i.path);
|
||||
const best = pickBestFile(filePaths);
|
||||
if (best) onSelectFile(best);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
setLoading(true);
|
||||
@@ -184,6 +233,19 @@ export function GiteaFileTree({
|
||||
);
|
||||
}
|
||||
|
||||
if (autoSelect && !autoSelectedRef.current && onSelectFile) {
|
||||
autoSelectedRef.current = true;
|
||||
const allItems = [
|
||||
...items,
|
||||
...Object.values(newChildrenByPath).flat(),
|
||||
];
|
||||
const filePaths = allItems
|
||||
.filter((i) => i.type === "file")
|
||||
.map((i) => i.path);
|
||||
const best = pickBestFile(filePaths);
|
||||
if (best) onSelectFile(best);
|
||||
}
|
||||
|
||||
if (cancelled) return;
|
||||
|
||||
setRootItems(items);
|
||||
|
||||
Reference in New Issue
Block a user