From ebe44d03a5fa6c34fdae2a67d53ef2ed6ba32737 Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Mon, 2 Mar 2026 20:17:47 -0800 Subject: [PATCH] Revert git action button logic toward main behavior Co-authored-by: codex --- .../GitActionsControl.logic.test.ts | 31 ++------- .../src/components/GitActionsControl.logic.ts | 17 +---- apps/web/src/components/GitActionsControl.tsx | 67 ++++++++++--------- 3 files changed, 46 insertions(+), 69 deletions(-) diff --git a/apps/web/src/components/GitActionsControl.logic.test.ts b/apps/web/src/components/GitActionsControl.logic.test.ts index 8bf548515192e26cbaed1988d3e8ded3f1f3168a..628f2f359e119eb562b972a2b3b627b2eaa737be 100644 --- a/apps/web/src/components/GitActionsControl.logic.test.ts +++ b/apps/web/src/components/GitActionsControl.logic.test.ts @@ -250,20 +250,15 @@ describe("when: branch is clean, ahead, and has no open PR", () => { }); describe("when: branch is clean, up to date, and has no open PR", () => { - it("resolveQuickAction offers create PR", () => { + it("resolveQuickAction returns disabled no-action state", () => { const quick = resolveQuickAction( status({ aheadCount: 0, behindCount: 0, hasWorkingTreeChanges: false, pr: null }), false, ); - assert.deepInclude(quick, { - kind: "run_action", - action: "commit_push_pr", - label: "Create PR", - disabled: false, - }); + assert.deepInclude(quick, { kind: "show_hint", label: "Commit", disabled: true }); }); - it("buildMenuItems enables create PR and keeps commit/push disabled", () => { + it("buildMenuItems disables commit, push, and create PR", () => { const items = buildMenuItems(status({ aheadCount: 0, behindCount: 0, pr: null }), false); assert.deepEqual(items, [ { @@ -285,25 +280,13 @@ describe("when: branch is clean, up to date, and has no open PR", () => { { id: "pr", label: "Create PR", - disabled: false, + disabled: true, icon: "pr", kind: "open_dialog", dialogAction: "create_pr", }, ]); }); - - it("buildMenuItems keeps create PR disabled on default branch", () => { - const items = buildMenuItems(status({ branch: "main", aheadCount: 0, behindCount: 0 }), false, true); - assert.deepEqual(items[2], { - id: "pr", - label: "Create PR", - disabled: true, - icon: "pr", - kind: "open_dialog", - dialogAction: "create_pr", - }); - }); }); describe("when: branch is behind upstream", () => { @@ -365,7 +348,7 @@ describe("when: working tree has local changes", () => { }); }); - it("resolveQuickAction keeps full commit/push/pr flow on non-default branches even when PR exists", () => { + it("resolveQuickAction returns commit and push when open PR exists", () => { const quick = resolveQuickAction( status({ hasWorkingTreeChanges: true, @@ -382,8 +365,8 @@ describe("when: working tree has local changes", () => { ); assert.deepInclude(quick, { kind: "run_action", - action: "commit_push_pr", - label: "Commit, push & create PR", + action: "commit_push", + label: "Commit & push", }); }); diff --git a/apps/web/src/components/GitActionsControl.logic.ts b/apps/web/src/components/GitActionsControl.logic.ts index 59cb8b9d781f0c2fea7177b0df6925d61a3fae22..9a9476e4cea571851055b7a80693d94c4e0a61cb 100644 --- a/apps/web/src/components/GitActionsControl.logic.ts +++ b/apps/web/src/components/GitActionsControl.logic.ts @@ -113,7 +113,6 @@ export function summarizeGitResult(result: GitRunStackedActionResult): { export function buildMenuItems( gitStatus: GitStatusResult | null, isBusy: boolean, - isDefaultBranch = false, ): GitActionMenuItem[] { if (!gitStatus) return []; @@ -128,9 +127,8 @@ export function buildMenuItems( hasBranch && !hasChanges && !hasOpenPr && - !isBehind && - !isDefaultBranch && - (gitStatus.aheadCount > 0 || gitStatus.hasUpstream); + gitStatus.aheadCount > 0 && + !isBehind; const canOpenPr = !isBusy && hasOpenPr; return [ @@ -204,7 +202,7 @@ export function resolveQuickAction( } if (hasChanges) { - if (isDefaultBranch) { + if (hasOpenPr || isDefaultBranch) { return { label: "Commit & push", disabled: false, kind: "run_action", action: "commit_push" }; } return { @@ -267,15 +265,6 @@ export function resolveQuickAction( }; } - if (!hasOpenPr && !isDefaultBranch && gitStatus.hasUpstream) { - return { - label: "Create PR", - disabled: false, - kind: "run_action", - action: "commit_push_pr", - }; - } - if (hasOpenPr && gitStatus.hasUpstream) { return { label: "Open PR", disabled: false, kind: "open_pr" }; } diff --git a/apps/web/src/components/GitActionsControl.tsx b/apps/web/src/components/GitActionsControl.tsx index e1b48e9244c7b511244e7985e608d804a6287148..21c0da40996d7cccdf60dea95ff14118cc1c26ca 100644 --- a/apps/web/src/components/GitActionsControl.tsx +++ b/apps/web/src/components/GitActionsControl.tsx @@ -57,6 +57,8 @@ interface PendingDefaultBranchAction { onConfirmed?: () => void; } +type GitActionToastId = ReturnType; + function getMenuActionDisabledReason( item: GitActionMenuItem, gitStatus: GitStatusResult | null, @@ -180,19 +182,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions const current = branchList?.branches.find((branch) => branch.name === branchName); return current?.isDefault ?? (branchName === "main" || branchName === "master"); }, [branchList?.branches, gitStatusForActions?.branch]); - const isDefaultBranchName = useCallback( - (branchName: string | null | undefined) => { - if (!branchName) return false; - const defaultBranchName = branchList?.branches.find((branch) => branch.isDefault)?.name; - if (defaultBranchName) return branchName === defaultBranchName; - return branchName === "main" || branchName === "master"; - }, - [branchList?.branches], - ); const gitActionMenuItems = useMemo( - () => buildMenuItems(gitStatusForActions, isGitActionRunning, isDefaultBranch), - [gitStatusForActions, isGitActionRunning, isDefaultBranch], + () => buildMenuItems(gitStatusForActions, isGitActionRunning), + [gitStatusForActions, isGitActionRunning], ); const quickAction = useMemo( () => resolveQuickAction(gitStatusForActions, isGitActionRunning, isDefaultBranch), @@ -245,26 +238,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions forcePushOnlyProgress = false, onConfirmed, skipDefaultBranchPrompt = false, + statusOverride, featureBranch = false, isDefaultBranchOverride, + progressToastId, }: { action: GitStackedAction; commitMessage?: string; forcePushOnlyProgress?: boolean; onConfirmed?: () => void; skipDefaultBranchPrompt?: boolean; + statusOverride?: GitStatusResult | null; featureBranch?: boolean; isDefaultBranchOverride?: boolean; + progressToastId?: GitActionToastId; }) => { - const actionStatus = gitStatusForActions; + const actionStatus = statusOverride ?? gitStatusForActions; const actionBranch = actionStatus?.branch ?? null; - const actionIsDefaultBranch = - isDefaultBranchOverride ?? (featureBranch ? false : isDefaultBranchName(actionBranch)); + const actionIsDefaultBranch = isDefaultBranchOverride ?? (featureBranch ? false : isDefaultBranch); const includesCommit = !forcePushOnlyProgress && (action === "commit" || !!actionStatus?.hasWorkingTreeChanges); if ( !skipDefaultBranchPrompt && - !featureBranch && requiresDefaultBranchConfirmation(action, actionIsDefaultBranch) && actionBranch ) { @@ -292,17 +287,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions featureBranch, ...(pushTarget ? { pushTarget } : {}), }); - const progressToastId = toastManager.add({ - type: "loading", - title: progressStages[0] ?? "Running git action...", - timeout: 0, - data: threadToastData, - }); + const resolvedProgressToastId = + progressToastId ?? + toastManager.add({ + type: "loading", + title: progressStages[0] ?? "Running git action...", + timeout: 0, + data: threadToastData, + }); + + if (progressToastId) { + toastManager.update(progressToastId, { + type: "loading", + title: progressStages[0] ?? "Running git action...", + timeout: 0, + data: threadToastData, + }); + } let stageIndex = 0; const stageInterval = setInterval(() => { stageIndex = Math.min(stageIndex + 1, progressStages.length - 1); - toastManager.update(progressToastId, { + toastManager.update(resolvedProgressToastId, { title: progressStages[stageIndex] ?? "Running git action...", type: "loading", timeout: 0, @@ -338,10 +344,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions result.push.status === "pushed" && !actionIsDefaultBranch; const closeResultToast = () => { - toastManager.close(progressToastId); + toastManager.close(resolvedProgressToastId); }; - toastManager.update(progressToastId, { + toastManager.update(resolvedProgressToastId, { type: "success", title: resultToast.title, description: resultToast.description, @@ -359,8 +365,8 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions action: "commit_push", forcePushOnlyProgress: true, onConfirmed: closeResultToast, - ...(featureBranch ? { skipDefaultBranchPrompt: true } : {}), - ...(featureBranch ? { isDefaultBranchOverride: false } : {}), + statusOverride: actionStatus, + isDefaultBranchOverride: actionIsDefaultBranch, }); }, }, @@ -386,8 +392,8 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions void runGitActionWithToast({ action: "commit_push_pr", forcePushOnlyProgress: true, - ...(featureBranch ? { skipDefaultBranchPrompt: true } : {}), - ...(featureBranch ? { isDefaultBranchOverride: false } : {}), + statusOverride: actionStatus, + isDefaultBranchOverride: actionIsDefaultBranch, }); }, }, @@ -396,7 +402,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions }); } catch (err) { stopProgressUpdates(); - toastManager.update(progressToastId, { + toastManager.update(resolvedProgressToastId, { type: "error", title: "Action failed", description: err instanceof Error ? err.message : "An error occurred.", @@ -406,7 +412,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions }, [ - isDefaultBranchName, + isDefaultBranch, runImmediateGitActionMutation, setPendingDefaultBranchAction, threadToastData, @@ -424,7 +430,6 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions forcePushOnlyProgress, ...(onConfirmed ? { onConfirmed } : {}), skipDefaultBranchPrompt: true, - isDefaultBranchOverride: true, }); }, [pendingDefaultBranchAction, runGitActionWithToast]); -- 2.54.0