Files
paseo/packages/app/src/git/worktree-archive-warning.ts
T
chyendongnhanh338andGitHub 08ebe5e7e1 Complete client UI i18n migration
Adds client-side i18n support, language settings, translated UI copy, and locale parity coverage.
2026-06-11 14:15:35 +08:00

119 lines
3.9 KiB
TypeScript

import { confirmDialog } from "@/utils/confirm-dialog";
import { i18n } from "@/i18n/i18next";
export interface WorktreeArchiveRisk {
isDirty?: boolean | null;
aheadOfOrigin?: number | null;
diffStat?: { additions: number; deletions: number } | null;
}
export interface WorktreeArchiveConfirmationInput extends WorktreeArchiveRisk {
worktreeName: string;
}
export interface WorktreeArchiveWarningLabels {
title: (worktreeName: string) => string;
confirm: string;
cancel: string;
uncommittedChanges: string;
uncommittedChangesWithDiff: (diffStat: string) => string;
addedLine: (count: number) => string;
deletedLine: (count: number) => string;
unpushedCommit: (count: number) => string;
}
export const DEFAULT_WORKTREE_ARCHIVE_WARNING_LABELS: WorktreeArchiveWarningLabels = {
title: (worktreeName) => i18n.t("workspace.git.actions.archiveWarning.title", { worktreeName }),
confirm: i18n.t("workspace.git.actions.archiveWarning.confirm"),
cancel: i18n.t("workspace.git.actions.archiveWarning.cancel"),
uncommittedChanges: i18n.t("workspace.git.actions.archiveWarning.uncommittedChanges"),
uncommittedChangesWithDiff: (diffStat) =>
i18n.t("workspace.git.actions.archiveWarning.uncommittedChangesWithDiff", { diffStat }),
addedLine: (count) =>
count === 1
? i18n.t("workspace.git.actions.archiveWarning.addedLine", { count })
: i18n.t("workspace.git.actions.archiveWarning.addedLines", { count }),
deletedLine: (count) =>
count === 1
? i18n.t("workspace.git.actions.archiveWarning.deletedLine", { count })
: i18n.t("workspace.git.actions.archiveWarning.deletedLines", { count }),
unpushedCommit: (count) =>
count === 1
? i18n.t("workspace.git.actions.archiveWarning.unpushedCommit", { count })
: i18n.t("workspace.git.actions.archiveWarning.unpushedCommits", { count }),
};
function formatDiffStat(
diffStat: WorktreeArchiveRisk["diffStat"],
labels: WorktreeArchiveWarningLabels,
): string | null {
if (!diffStat) {
return null;
}
const parts: string[] = [];
if (diffStat.additions > 0) {
parts.push(labels.addedLine(diffStat.additions));
}
if (diffStat.deletions > 0) {
parts.push(labels.deletedLine(diffStat.deletions));
}
return parts.length > 0 ? parts.join(", ") : null;
}
export function buildWorktreeArchiveRiskReasons(
input: WorktreeArchiveRisk,
labels: WorktreeArchiveWarningLabels = DEFAULT_WORKTREE_ARCHIVE_WARNING_LABELS,
): string[] {
const reasons: string[] = [];
const diffStat = input.diffStat;
const hasDiffStatChanges = diffStat ? diffStat.additions > 0 || diffStat.deletions > 0 : false;
const hasUncommittedChanges =
input.isDirty === true || (input.isDirty == null && hasDiffStatChanges);
if (hasUncommittedChanges) {
const diffStatLabel = formatDiffStat(diffStat, labels);
reasons.push(
diffStatLabel ? labels.uncommittedChangesWithDiff(diffStatLabel) : labels.uncommittedChanges,
);
}
if ((input.aheadOfOrigin ?? 0) > 0) {
const aheadOfOrigin = input.aheadOfOrigin ?? 0;
reasons.push(labels.unpushedCommit(aheadOfOrigin));
}
return reasons;
}
export function buildWorktreeArchiveConfirmationMessage(
input: WorktreeArchiveConfirmationInput,
labels: WorktreeArchiveWarningLabels = DEFAULT_WORKTREE_ARCHIVE_WARNING_LABELS,
): string | null {
const reasons = buildWorktreeArchiveRiskReasons(input, labels);
if (reasons.length === 0) {
return null;
}
return reasons.join("\n");
}
export async function confirmRiskyWorktreeArchive(
input: WorktreeArchiveConfirmationInput,
labels: WorktreeArchiveWarningLabels = DEFAULT_WORKTREE_ARCHIVE_WARNING_LABELS,
): Promise<boolean> {
const message = buildWorktreeArchiveConfirmationMessage(input, labels);
if (!message) {
return true;
}
return await confirmDialog({
title: labels.title(input.worktreeName),
message,
confirmLabel: labels.confirm,
cancelLabel: labels.cancel,
destructive: true,
});
}