From 79515d0a2d58d4883df96d563764414fab8af721 Mon Sep 17 00:00:00 2001 From: Naresh-official Date: Sun, 1 Feb 2026 13:18:02 +0530 Subject: [PATCH] fix: improve UX for empty repositories (#821) - Add empty state UI with clear messaging in file tree and preview panels - Implement revision verification to gracefully handle empty repos - Replace generic error messages with user-friendly 'No commits yet' state - Add FolderOpen icon and helpful text for empty repository indication - Prevent rendering errors when repository has no children nodes Fixes #821 --- .../[...path]/components/treePreviewPanel.tsx | 29 ++++++++++++++++++- packages/web/src/features/fileTree/api.ts | 14 +++++++++ .../fileTree/components/fileTreePanel.tsx | 9 +++++- .../fileTree/components/pureFileTreePanel.tsx | 4 +++ 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx b/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx index ada848eff..557e84dd3 100644 --- a/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx +++ b/packages/web/src/app/[domain]/browse/[...path]/components/treePreviewPanel.tsx @@ -1,10 +1,10 @@ - import { Separator } from "@/components/ui/separator"; import { getRepoInfoByName } from "@/actions"; import { PathHeader } from "@/app/[domain]/components/pathHeader"; import { getFolderContents } from "@/features/fileTree/api"; import { isServiceError } from "@/lib/utils"; import { PureTreePreviewPanel } from "./pureTreePreviewPanel"; +import { FolderOpen } from "lucide-react"; interface TreePreviewPanelProps { path: string; @@ -26,6 +26,33 @@ export const TreePreviewPanel = async ({ path, repoName, revisionName }: TreePre return
Error loading tree preview
} + if (folderContentsResponse.length === 0) { + return ( + <> +
+ +
+ +
+ +

No commits yet

+

This repository doesn't have any code yet

+
+ + ) + } + return ( <>
diff --git a/packages/web/src/features/fileTree/api.ts b/packages/web/src/features/fileTree/api.ts index 6b5ab574f..5f2244ae3 100644 --- a/packages/web/src/features/fileTree/api.ts +++ b/packages/web/src/features/fileTree/api.ts @@ -39,6 +39,13 @@ export const getTree = async (params: { repoName: string, revisionName: string, const normalizedPaths = paths.map(path => normalizePath(path)); + // Verify that the revision is not empty + try{ + await git.raw(["rev-parse","--verify",revisionName]) + }catch(_error){ + return {tree:{}} + } + let result: string = ''; try { @@ -106,6 +113,13 @@ export const getFolderContents = async (params: { repoName: string, revisionName } const normalizedPath = normalizePath(path); + // Verify that the revision is not empty + try{ + await git.raw(["rev-parse","--verify",revisionName]) + } catch(_error){ + return []; + } + let result: string; try { result = await git.raw([ diff --git a/packages/web/src/features/fileTree/components/fileTreePanel.tsx b/packages/web/src/features/fileTree/components/fileTreePanel.tsx index 89696eba4..3221c1e06 100644 --- a/packages/web/src/features/fileTree/components/fileTreePanel.tsx +++ b/packages/web/src/features/fileTree/components/fileTreePanel.tsx @@ -13,6 +13,7 @@ import useCaptureEvent from "@/hooks/useCaptureEvent"; import { measure, unwrapServiceError } from "@/lib/utils"; import { useQuery } from "@tanstack/react-query"; import { SearchIcon } from "lucide-react"; +import { FolderOpen } from "lucide-react"; import { useCallback, useEffect, useRef, useState } from "react"; import { useHotkeys } from "react-hotkeys-hook"; import { @@ -55,7 +56,7 @@ export const FileTreePanel = ({ order }: FileTreePanelProps) => { paths: Array.from(openPaths), }) ), 'getTree'); - + captureEvent('wa_file_tree_loaded', { durationMs: result.durationMs, }); @@ -189,6 +190,12 @@ export const FileTreePanel = ({ order }: FileTreePanelProps) => {

Error loading file tree

+ ) : !data.tree.children || data.tree.children.length === 0 ? ( +
+ +

No files yet

+

This repository doesn't have any code yet

+
) : ( { + if (!nodes.children || nodes.children.length === 0) { + return null; + } + return ( <> {nodes.children.map((node) => {