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 @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Upgraded `nodemailer` to `^9.0.1`. [#1356](https://github.com/sourcebot-dev/sourcebot/pull/1356)
- Upgraded `@opentelemetry/core` to `^2.8.0`. [#1413](https://github.com/sourcebot-dev/sourcebot/pull/1413)
- [EE] Fixed connector setup dialogs to add scrolling when connector setup content goes out of view.
- 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