fix(app): show only workspace commits in Changes

Keep base history out of the commit list and explain the empty workspace state.
This commit is contained in:
Mohamed Boudra
2026-07-23 23:29:58 +02:00
parent 09cfdecbbf
commit c469ac124a
11 changed files with 58 additions and 23 deletions

View File

@@ -5,6 +5,25 @@ import { test, expect } from "./fixtures";
const COMMIT_SUBJECT = "Show commit timestamps";
test("commit history explains when the workspace has no commits ahead of its base", async ({
page,
withWorkspace,
}) => {
const workspace = await withWorkspace({ prefix: "commit-history-empty-workspace-" });
execFileSync("git", ["checkout", "-b", "feature"], { cwd: workspace.repoPath, stdio: "ignore" });
await workspace.navigateTo();
await page.getByRole("button", { name: "Open explorer" }).click();
const commitsSection = page.getByRole("button", { name: /Commits/i });
await expect(commitsSection).toBeVisible({ timeout: 30_000 });
await commitsSection.click();
await expect(page.getByTestId("commits-section-no-workspace-commits")).toHaveText(
"No commits ahead of main yet",
{ timeout: 30_000 },
);
});
test("commit history shows dates and shares diff layout preferences", async ({
page,
withWorkspace,
@@ -23,6 +42,7 @@ test("commit history shows dates and shares diff layout preferences", async ({
hasText: COMMIT_SUBJECT,
});
await expect(commitRow).toContainText(COMMIT_SUBJECT, { timeout: 30_000 });
await expect(page.locator('[data-testid^="commit-row-"]')).toHaveCount(1);
await expect(commitRow).toContainText("Jan 15");
await commitRow.click();

View File

@@ -3,6 +3,7 @@ import { Pressable, Text, View, type PressableStateCallbackType } from "react-na
import { StyleSheet } from "react-native-unistyles";
import { ThemedChevron, chevronColorMapping } from "@/git/themed-chevron";
import type { ClassifiedCheckoutCommit } from "@/git/use-commits-query";
import { CODE_SURFACE_DATASET } from "@/styles/code-surface";
import { formatTimeAgo } from "@/utils/time";
import { CommitGraphNode } from "./commit-graph-node";
@@ -41,7 +42,7 @@ export const CommitRow = memo(function CommitRow({
>
<CommitGraphNode commit={commit} isFirst={isFirst} isLast={isLast} />
<View style={styles.commitDetails}>
<Text style={styles.shortSha} numberOfLines={1}>
<Text dataSet={CODE_SURFACE_DATASET} style={styles.shortSha} numberOfLines={1}>
{commit.shortSha}
</Text>
<Text style={styles.subject} numberOfLines={1}>
@@ -79,7 +80,7 @@ const styles = StyleSheet.create((theme) => ({
fontSize: theme.fontSize.xs,
fontFamily: theme.fontFamily.mono,
color: theme.colors.foregroundMuted,
width: theme.spacing[16],
width: 70,
flexShrink: 0,
},
subject: {

View File

@@ -6,6 +6,7 @@ import { useRetainedPanelActive } from "@/components/retained-panel";
import { useChangesPreferences } from "@/hooks/use-changes-preferences";
import { useCheckoutCommitsQuery, type CheckoutCommitsQueryResult } from "@/git/use-commits-query";
import { ThemedChevron, chevronColorMapping } from "@/git/themed-chevron";
import { normalizeBranchOptionName } from "@/utils/branch-suggestions";
import { CommitRow } from "./commit-row";
interface CommitsSectionProps {
@@ -14,8 +15,6 @@ interface CommitsSectionProps {
onCommitPress: (sha: string) => void;
}
const SKELETON_ROW_KEYS = ["commit-skeleton-1", "commit-skeleton-2", "commit-skeleton-3"];
function CommitsSectionSkeleton() {
const { t } = useTranslation();
return (
@@ -25,15 +24,13 @@ function CommitsSectionSkeleton() {
style={styles.skeleton}
testID="commits-section-skeleton"
>
{SKELETON_ROW_KEYS.map((key) => (
<View key={key} style={styles.skeletonRow}>
<View style={styles.skeletonDot} />
<View style={styles.skeletonSha} />
<View style={styles.skeletonSubject} />
<View style={styles.skeletonTimestamp} />
<View style={styles.skeletonCaret} />
</View>
))}
<View style={styles.skeletonRow}>
<View style={styles.skeletonDot} />
<View style={styles.skeletonSha} />
<View style={styles.skeletonSubject} />
<View style={styles.skeletonTimestamp} />
<View style={styles.skeletonCaret} />
</View>
</View>
);
}
@@ -58,21 +55,25 @@ function CommitsSectionContent({
if (query.status !== "loaded") {
return <CommitsSectionSkeleton />;
}
if (query.data.commits.length === 0) {
const workspaceCommits = query.data.commits.filter((commit) => !commit.isOnBase);
const baseRef = normalizeBranchOptionName(query.data.baseRef) ?? t("workspace.git.diff.base");
if (workspaceCommits.length === 0) {
return (
<Text style={styles.emptyRow} testID="commits-section-empty">
{t("workspace.git.diff.commits.empty")}
</Text>
<View style={styles.noWorkspaceCommitsRow} testID="commits-section-no-workspace-commits">
<Text style={styles.noWorkspaceCommitsText}>
{t("workspace.git.diff.commits.noneAhead", { baseRef })}
</Text>
</View>
);
}
return (
<View style={styles.list}>
{query.data.commits.map((commit, index) => (
{workspaceCommits.map((commit, index) => (
<CommitRow
key={commit.sha}
commit={commit}
isFirst={index === 0}
isLast={index === query.data.commits.length - 1}
isLast={index === workspaceCommits.length - 1}
now={now}
onCommitPress={onCommitPress}
/>
@@ -193,12 +194,17 @@ const styles = StyleSheet.create((theme) => ({
list: {
paddingBottom: theme.spacing[1],
},
emptyRow: {
fontSize: theme.fontSize.xs,
color: theme.colors.foregroundMuted,
noWorkspaceCommitsRow: {
flexDirection: "row",
alignItems: "center",
paddingLeft: theme.spacing[2],
paddingRight: theme.spacing[3],
paddingVertical: theme.spacing[2],
paddingTop: theme.spacing[1],
paddingBottom: theme.spacing[2],
},
noWorkspaceCommitsText: {
fontSize: theme.fontSize.xs,
color: theme.colors.foregroundMuted,
},
errorRow: {
fontSize: theme.fontSize.xs,

View File

@@ -796,6 +796,7 @@ export const ar: TranslationResources = {
commits: {
title: "الإيداعات",
countLabel: "{{count}} من إيداعات مساحة العمل",
noneAhead: "لا توجد إيداعات متقدمة على {{baseRef}} بعد",
fileDiffEmpty: "لا توجد تغييرات لعرضها",
fileDiffError: "تعذّر تحميل فروق الملف",
loading: "جارٍ تحميل الإيداعات…",

View File

@@ -806,6 +806,7 @@ export const en = {
commits: {
title: "Commits",
countLabel: "{{count}} workspace commits",
noneAhead: "No commits ahead of {{baseRef}} yet",
fileDiffEmpty: "No changes to display",
fileDiffError: "Failed to load file diff",
loading: "Loading commits…",

View File

@@ -827,6 +827,7 @@ export const es: TranslationResources = {
commits: {
title: "Commits",
countLabel: "{{count}} commits del espacio de trabajo",
noneAhead: "Aún no hay commits por delante de {{baseRef}}",
fileDiffEmpty: "No hay cambios para mostrar",
fileDiffError: "Error al cargar el diff del archivo",
loading: "Cargando commits…",

View File

@@ -826,6 +826,7 @@ export const fr: TranslationResources = {
commits: {
title: "Commits",
countLabel: "{{count}} commits de lespace de travail",
noneAhead: "Aucun commit en avance sur {{baseRef}} pour le moment",
fileDiffEmpty: "Aucune modification à afficher",
fileDiffError: "Échec du chargement du diff du fichier",
loading: "Chargement des commits…",

View File

@@ -807,6 +807,7 @@ export const ja: TranslationResources = {
commits: {
title: "コミット",
countLabel: "ワークスペースのコミット数: {{count}}",
noneAhead: "{{baseRef}} より先のコミットはまだありません",
fileDiffEmpty: "表示する変更はありません",
fileDiffError: "ファイル差分の読み込みに失敗しました",
loading: "コミットを読み込み中…",

View File

@@ -818,6 +818,7 @@ export const ptBR: TranslationResources = {
commits: {
title: "Commits",
countLabel: "{{count}} commits do espaço de trabalho",
noneAhead: "Ainda não há commits à frente de {{baseRef}}",
fileDiffEmpty: "Nenhuma alteração para exibir",
fileDiffError: "Falha ao carregar diff do arquivo",
loading: "Carregando commits…",

View File

@@ -818,6 +818,7 @@ export const ru: TranslationResources = {
commits: {
title: "Коммиты",
countLabel: "{{count}} коммитов рабочего пространства",
noneAhead: "Коммитов впереди {{baseRef}} пока нет",
fileDiffEmpty: "Нет изменений для отображения",
fileDiffError: "Не удалось загрузить различия файла",
loading: "Загрузка коммитов…",

View File

@@ -788,6 +788,7 @@ export const zhCN: TranslationResources = {
commits: {
title: "提交",
countLabel: "{{count}} 个工作区提交",
noneAhead: "尚无领先于 {{baseRef}} 的提交",
fileDiffEmpty: "没有可显示的更改",
fileDiffError: "加载文件差异失败",
loading: "正在加载提交…",