"use client"; import { IconGitCommit, IconArrowBackUp, IconPencil, IconHistoryToggle, IconArrowUp, } from "@tabler/icons-react"; import { Tooltip, TooltipContent, TooltipTrigger } from "@kandev/ui/tooltip"; import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger, } from "@kandev/ui/context-menu"; import { timeAgo } from "@/lib/utils/time"; import type { CommitDetailTarget } from "./changes-diff-target"; import { useTranslation } from "react-i18next"; export type CommitPresentation = "current_pr" | "local_checkout"; export type CommitItem = { commit_sha: string; commit_message: string; insertions: number; deletions: number; pushed?: boolean; statsAvailable: boolean; detailTarget: CommitDetailTarget; /** Multi-repo: name of the repo this commit was made in. Empty for single-repo. */ repository_name?: string; committed_at?: string; /** Explicit provenance used when provider and checkout histories diverge. */ presentation?: CommitPresentation; }; /** Context menu for commit items */ function CommitContextMenu({ children, commit, isLatest, onAmendCommit, onRevertCommit, onResetToCommit, }: { children: React.ReactNode; commit: CommitItem; isLatest: boolean; // Multi-repo: handlers receive the commit's repository_name so the // amend/revert/reset op runs in the right git repo. Without it, ops hit // the workspace root which fails on multi-repo task workspaces. onAmendCommit?: (currentMessage: string, repo?: string) => void; onRevertCommit?: (sha: string, repo?: string) => void; onResetToCommit?: (sha: string, repo?: string) => void; }) { const { t } = useTranslation(); const hasActions = commit.detailTarget.source === "local" && (onAmendCommit || onRevertCommit || onResetToCommit); if (!hasActions) { return <>{children}; } return ( {children} {isLatest && onAmendCommit && ( onAmendCommit(commit.commit_message, commit.repository_name)} > {t("task:amendMessage")} )} {isLatest && onRevertCommit && ( onRevertCommit(commit.commit_sha, commit.repository_name)} > {t("task:revertCommit")} )} {onResetToCommit && ( onResetToCommit(commit.commit_sha, commit.repository_name)} > {t("task:resetToThisCommit")} )} ); } /** Hover action buttons for a commit row */ function CommitRowActions({ commit, isLatest, onAmendCommit, onRevertCommit, onResetToCommit, }: { commit: CommitItem; isLatest: boolean; // Multi-repo: handlers receive the commit's repository_name so the // amend/revert/reset op runs in the right git repo. Without it, ops hit // the workspace root which fails on multi-repo task workspaces. onAmendCommit?: (currentMessage: string, repo?: string) => void; onRevertCommit?: (sha: string, repo?: string) => void; onResetToCommit?: (sha: string, repo?: string) => void; }) { const { t } = useTranslation(); return ( {isLatest && onAmendCommit && ( {t("task:amendCommitMessage2")} )} {isLatest && onRevertCommit && ( {t("task:revertCommit")} )} {onResetToCommit && ( {t("task:resetToThisCommit")} )} ); } function CommitStatusMarker({ commit }: { commit: CommitItem }) { const { t } = useTranslation(); let label: string; let marker =