Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Send anonymous server-side PostHog events as personless so unauthenticated requests don't inflate person counts. [#1367](https://github.com/sourcebot-dev/sourcebot/pull/1367)
- [EE] Fixed Ask Sourcebot mermaid diagrams overflowing their container by contain-fitting them to both width and height, and made revealing a diagram from the answer jump it into view instantly to avoid over/undershooting. [#1373](https://github.com/sourcebot-dev/sourcebot/pull/1373)
- Passed Zoekt index parameters via argv to preserve revision names with punctuation. [#1376](https://github.com/sourcebot-dev/sourcebot/pull/1376)
- Show a clear empty repository state in the browse tree instead of generic tree loading errors. [#1380](https://github.com/sourcebot-dev/sourcebot/pull/1380)

## [5.0.4] - 2026-06-18

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,20 @@ import { FileTreeItem } from "@/features/git";

interface PureTreePreviewPanelProps {
items: FileTreeItem[];
isRepositoryEmpty: boolean;
}

export const PureTreePreviewPanel = ({ items }: PureTreePreviewPanelProps) => {
export const PureTreePreviewPanel = ({ items, isRepositoryEmpty }: PureTreePreviewPanelProps) => {
const { repoName, revisionName } = useBrowseParams();
const scrollAreaRef = useRef<HTMLDivElement>(null);

if (isRepositoryEmpty) {
return (
<div className="flex h-full items-center justify-center p-4 text-sm text-muted-foreground">
This repository is empty
</div>
);
}

return (
<ScrollArea
Expand All @@ -38,4 +47,4 @@ export const PureTreePreviewPanel = ({ items }: PureTreePreviewPanelProps) => {
))}
</ScrollArea>
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ export const TreePreviewPanel = async ({ path, repoName, revisionName }: TreePre
/>
</div>
<Separator />
<PureTreePreviewPanel items={folderContentsResponse} />
<PureTreePreviewPanel
items={folderContentsResponse.items}
isRepositoryEmpty={folderContentsResponse.isRepositoryEmpty}
/>
</>
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { cleanup, render, screen } from '@testing-library/react';
import { afterEach, describe, expect, test, vi } from 'vitest';
import { PureFileTreePanel } from './pureFileTreePanel';
import { PureTreePreviewPanel } from '../[...path]/components/treePreviewPanel/pureTreePreviewPanel';

vi.mock('@/app/(app)/browse/hooks/useBrowseParams', () => ({
useBrowseParams: () => ({
repoName: 'github.com/sourcebot-dev/empty',
revisionName: 'HEAD',
path: '',
pathType: 'tree',
}),
}));

vi.mock('@bprogress/next', () => ({
useProgress: () => ({
stop: vi.fn(),
}),
}));

afterEach(() => {
cleanup();
});

describe('empty repository browse panels', () => {
test('tree preview panel shows a clear empty repository state', () => {
render(<PureTreePreviewPanel items={[]} isRepositoryEmpty={true} />);

expect(screen.queryByText('This repository is empty')).toBeTruthy();
});

test('tree preview panel does not infer repository emptiness from empty items', () => {
render(<PureTreePreviewPanel items={[]} isRepositoryEmpty={false} />);

expect(screen.queryByText('This repository is empty')).toBeNull();
});

test('file tree panel shows a clear empty repository state', () => {
render(
<PureFileTreePanel
tree={{
name: 'root',
path: '',
type: 'tree',
children: [],
}}
openPaths={new Set()}
path=""
onTreeNodeClicked={vi.fn()}
/>
);

expect(screen.queryByText('This repository is empty')).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ export const PureFileTreePanel = ({ tree, openPaths, path, onTreeNodeClicked }:

const renderedTree = useMemo(() => renderTree(tree), [tree, renderTree]);

if (tree.children.length === 0) {
return (
<div className="flex h-full items-center justify-center p-4 text-sm text-muted-foreground">
This repository is empty
</div>
);
}

return (
<ScrollArea
className="h-full w-full overflow-auto p-0.5"
Expand All @@ -94,4 +102,3 @@ export const PureFileTreePanel = ({ tree, openPaths, path, onTreeNodeClicked }:
</ScrollArea>
)
}

Loading