"use client"; import { PanelBody } from "./panel-primitives"; import { DiscardDialog, AmendDialog, ResetDialog } from "./changes-panel-dialogs"; import { FileListSection, CommitsSection, ReviewProgressBar, PRFilesSection, } from "./changes-panel-timeline"; import { firstVisibleSection, mergeCommits, separateCommitHistories, } from "./changes-panel-helpers"; import type { ChangesPanelBodyProps } from "./changes-panel-data"; import { useTranslation } from "react-i18next"; import { IconAlertTriangle } from "@tabler/icons-react"; function ComparisonTargetNotice({ comparisonTargets, comparisonUnavailable, }: Pick) { const { t } = useTranslation(); if (!comparisonUnavailable) return null; const targetLabel = comparisonTargets.join(", ") || t("task:comparisonTargetUnknown"); return (

{t("task:comparisonTargetUnavailable")}

{t("task:comparisonTargetUnavailableDescription", { target: targetLabel })}

); } function ChangesPanelDialogsSection({ dialogs, isLoading, }: Pick) { return ( <> ); } type TimelineProps = Pick< ChangesPanelBodyProps, | "hasAnything" | "hasUnstaged" | "hasStaged" | "hasCommits" | "hasPRFiles" | "relation" | "resolution" | "resolutionTarget" | "providerPRNumber" | "pushDisabled" | "pullDisabled" | "canPush" | "canCreatePR" | "existingPrUrl" | "unstagedFiles" | "stagedFiles" | "prFiles" | "prCommits" | "commits" | "pendingStageFiles" | "aheadCount" | "isLoading" | "loadingOperation" | "dialogs" | "onOpenDiffFile" | "onEditFile" | "onOpenCommitDetail" | "onRevertCommit" | "onStageAll" | "onUnstageAll" | "onStage" | "onUnstage" | "onBulkStage" | "onBulkUnstage" | "onBulkDiscard" | "onPush" | "onForcePush" | "onRepoStageAll" | "onRepoUnstageAll" | "onRepoCommit" | "onRepoPush" | "onRepoCreatePR" | "repoDisplayName" | "perRepoStatus" | "prByRepo" >; type WorkingTreeProps = Pick< TimelineProps, | "hasUnstaged" | "hasStaged" | "unstagedFiles" | "stagedFiles" | "pendingStageFiles" | "isLoading" | "loadingOperation" | "dialogs" | "onOpenDiffFile" | "onEditFile" | "onStageAll" | "onUnstageAll" | "onStage" | "onUnstage" | "onBulkStage" | "onBulkUnstage" | "onBulkDiscard" | "onRepoStageAll" | "onRepoUnstageAll" | "onRepoCommit" | "repoDisplayName" >; function WorkingTreeSections(props: WorkingTreeProps) { const { t } = useTranslation(); const isBulkOp = props.pendingStageFiles.size === 0; return ( <> {props.hasUnstaged && ( )} {props.hasStaged && ( props.dialogs.openCommitDialog()} secondaryActionLabel={t("task:unstageAll")} isSecondaryActionLoading={ props.isLoading || (isBulkOp && props.loadingOperation === "unstage") } onSecondaryAction={props.onUnstageAll} onOpenDiff={props.onOpenDiffFile} onEditFile={props.onEditFile} onStage={props.onStage} onUnstage={props.onUnstage} onDiscard={props.dialogs.handleDiscardClick} onBulkUnstage={props.onBulkUnstage} onBulkDiscard={props.onBulkDiscard} onRepoAction={props.onRepoCommit} onRepoSecondaryAction={props.onRepoUnstageAll} repoDisplayName={props.repoDisplayName} /> )} ); } function CommitHistorySections({ props, isDiverged, defaultCollapsed, mergedCommits, separated, }: { props: TimelineProps; isDiverged: boolean; defaultCollapsed: boolean; mergedCommits: ReturnType; separated: ReturnType; }) { const { t } = useTranslation(); if (isDiverged) { return ( <> {separated.localCommits.length > 0 && ( )} {separated.providerCommits.length > 0 && ( )} ); } return ( ); } function EmptyChangesPanel() { const { t } = useTranslation(); return (
{t("task:yourChangedFilesWillAppearHere")}
); } function ChangesPanelTimeline(props: TimelineProps) { if (!props.hasAnything) { return ; } const isDiverged = props.relation.presentation === "separate"; const separated = isDiverged ? separateCommitHistories(props.commits, props.prCommits) : { providerCommits: [], localCommits: [] }; const mergedCommits = isDiverged ? [] : mergeCommits(props.commits, props.prCommits); const hasMergedCommits = isDiverged ? separated.providerCommits.length > 0 || separated.localCommits.length > 0 : mergedCommits.length > 0; const hasLocalChanges = props.hasUnstaged || props.hasStaged; const showCommitsList = props.hasStaged || hasMergedCommits; // Auto-expand the first (topmost) visible section so the panel never opens // looking empty (e.g. review mode: PR + Commits both collapsed). Unstaged / // Staged keep their always-expanded default; PR and Commits are gated. Large // PR diffs (>5 files) skip PR Changes and expand Commits instead. const firstSection = firstVisibleSection({ hasPRFiles: props.hasPRFiles, hasUnstaged: props.hasUnstaged, hasStaged: props.hasStaged, showCommitsList, prFileCount: props.prFiles.length, }); return (
{props.hasPRFiles && !hasLocalChanges && (
)} {props.hasPRFiles && hasLocalChanges && (
)} {showCommitsList && ( )}
); } export function ChangesPanelBody(props: ChangesPanelBodyProps) { return (
); }