| ... | @@ -57,6 +57,8 @@ interface PendingDefaultBranchAction { | ... | @@ -57,6 +57,8 @@ interface PendingDefaultBranchAction { |
| 57 | onConfirmed?: () => void; | 57 | onConfirmed?: () => void; |
| 58 | } | 58 | } |
| 59 | | 59 | |
| | 60 | type GitActionToastId = ReturnType<typeof toastManager.add>; |
| | 61 | |
| 60 | function getMenuActionDisabledReason( | 62 | function getMenuActionDisabledReason( |
| 61 | item: GitActionMenuItem, | 63 | item: GitActionMenuItem, |
| 62 | gitStatus: GitStatusResult | null, | 64 | gitStatus: GitStatusResult | null, |
| ... | @@ -180,19 +182,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -180,19 +182,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 180 | const current = branchList?.branches.find((branch) => branch.name === branchName); | 182 | const current = branchList?.branches.find((branch) => branch.name === branchName); |
| 181 | return current?.isDefault ?? (branchName === "main" || branchName === "master"); | 183 | return current?.isDefault ?? (branchName === "main" || branchName === "master"); |
| 182 | }, [branchList?.branches, gitStatusForActions?.branch]); | 184 | }, [branchList?.branches, gitStatusForActions?.branch]); |
| 183 | const isDefaultBranchName = useCallback( | | |
| 184 | (branchName: string | null | undefined) => { | | |
| 185 | if (!branchName) return false; | | |
| 186 | const defaultBranchName = branchList?.branches.find((branch) => branch.isDefault)?.name; | | |
| 187 | if (defaultBranchName) return branchName === defaultBranchName; | | |
| 188 | return branchName === "main" || branchName === "master"; | | |
| 189 | }, | | |
| 190 | [branchList?.branches], | | |
| 191 | ); | | |
| 192 | | 185 | |
| 193 | const gitActionMenuItems = useMemo( | 186 | const gitActionMenuItems = useMemo( |
| 194 | () => buildMenuItems(gitStatusForActions, isGitActionRunning, isDefaultBranch), | 187 | () => buildMenuItems(gitStatusForActions, isGitActionRunning), |
| 195 | [gitStatusForActions, isGitActionRunning, isDefaultBranch], | 188 | [gitStatusForActions, isGitActionRunning], |
| 196 | ); | 189 | ); |
| 197 | const quickAction = useMemo( | 190 | const quickAction = useMemo( |
| 198 | () => resolveQuickAction(gitStatusForActions, isGitActionRunning, isDefaultBranch), | 191 | () => resolveQuickAction(gitStatusForActions, isGitActionRunning, isDefaultBranch), |
| ... | @@ -245,26 +238,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -245,26 +238,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 245 | forcePushOnlyProgress = false, | 238 | forcePushOnlyProgress = false, |
| 246 | onConfirmed, | 239 | onConfirmed, |
| 247 | skipDefaultBranchPrompt = false, | 240 | skipDefaultBranchPrompt = false, |
| | 241 | statusOverride, |
| 248 | featureBranch = false, | 242 | featureBranch = false, |
| 249 | isDefaultBranchOverride, | 243 | isDefaultBranchOverride, |
| | 244 | progressToastId, |
| 250 | }: { | 245 | }: { |
| 251 | action: GitStackedAction; | 246 | action: GitStackedAction; |
| 252 | commitMessage?: string; | 247 | commitMessage?: string; |
| 253 | forcePushOnlyProgress?: boolean; | 248 | forcePushOnlyProgress?: boolean; |
| 254 | onConfirmed?: () => void; | 249 | onConfirmed?: () => void; |
| 255 | skipDefaultBranchPrompt?: boolean; | 250 | skipDefaultBranchPrompt?: boolean; |
| | 251 | statusOverride?: GitStatusResult | null; |
| 256 | featureBranch?: boolean; | 252 | featureBranch?: boolean; |
| 257 | isDefaultBranchOverride?: boolean; | 253 | isDefaultBranchOverride?: boolean; |
| | 254 | progressToastId?: GitActionToastId; |
| 258 | }) => { | 255 | }) => { |
| 259 | const actionStatus = gitStatusForActions; | 256 | const actionStatus = statusOverride ?? gitStatusForActions; |
| 260 | const actionBranch = actionStatus?.branch ?? null; | 257 | const actionBranch = actionStatus?.branch ?? null; |
| 261 | const actionIsDefaultBranch = | 258 | const actionIsDefaultBranch = isDefaultBranchOverride ?? (featureBranch ? false : isDefaultBranch); |
| 262 | isDefaultBranchOverride ?? (featureBranch ? false : isDefaultBranchName(actionBranch)); | | |
| 263 | const includesCommit = | 259 | const includesCommit = |
| 264 | !forcePushOnlyProgress && (action === "commit" || !!actionStatus?.hasWorkingTreeChanges); | 260 | !forcePushOnlyProgress && (action === "commit" || !!actionStatus?.hasWorkingTreeChanges); |
| 265 | if ( | 261 | if ( |
| 266 | !skipDefaultBranchPrompt && | 262 | !skipDefaultBranchPrompt && |
| 267 | !featureBranch && | | |
| 268 | requiresDefaultBranchConfirmation(action, actionIsDefaultBranch) && | 263 | requiresDefaultBranchConfirmation(action, actionIsDefaultBranch) && |
| 269 | actionBranch | 264 | actionBranch |
| 270 | ) { | 265 | ) { |
| ... | @@ -292,17 +287,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -292,17 +287,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 292 | featureBranch, | 287 | featureBranch, |
| 293 | ...(pushTarget ? { pushTarget } : {}), | 288 | ...(pushTarget ? { pushTarget } : {}), |
| 294 | }); | 289 | }); |
| 295 | const progressToastId = toastManager.add({ | 290 | const resolvedProgressToastId = |
| 296 | type: "loading", | 291 | progressToastId ?? |
| 297 | title: progressStages[0] ?? "Running git action...", | 292 | toastManager.add({ |
| 298 | timeout: 0, | 293 | type: "loading", |
| 299 | data: threadToastData, | 294 | title: progressStages[0] ?? "Running git action...", |
| 300 | }); | 295 | timeout: 0, |
| | 296 | data: threadToastData, |
| | 297 | }); |
| | 298 | |
| | 299 | if (progressToastId) { |
| | 300 | toastManager.update(progressToastId, { |
| | 301 | type: "loading", |
| | 302 | title: progressStages[0] ?? "Running git action...", |
| | 303 | timeout: 0, |
| | 304 | data: threadToastData, |
| | 305 | }); |
| | 306 | } |
| 301 | | 307 | |
| 302 | let stageIndex = 0; | 308 | let stageIndex = 0; |
| 303 | const stageInterval = setInterval(() => { | 309 | const stageInterval = setInterval(() => { |
| 304 | stageIndex = Math.min(stageIndex + 1, progressStages.length - 1); | 310 | stageIndex = Math.min(stageIndex + 1, progressStages.length - 1); |
| 305 | toastManager.update(progressToastId, { | 311 | toastManager.update(resolvedProgressToastId, { |
| 306 | title: progressStages[stageIndex] ?? "Running git action...", | 312 | title: progressStages[stageIndex] ?? "Running git action...", |
| 307 | type: "loading", | 313 | type: "loading", |
| 308 | timeout: 0, | 314 | timeout: 0, |
| ... | @@ -338,10 +344,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -338,10 +344,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 338 | result.push.status === "pushed" && | 344 | result.push.status === "pushed" && |
| 339 | !actionIsDefaultBranch; | 345 | !actionIsDefaultBranch; |
| 340 | const closeResultToast = () => { | 346 | const closeResultToast = () => { |
| 341 | toastManager.close(progressToastId); | 347 | toastManager.close(resolvedProgressToastId); |
| 342 | }; | 348 | }; |
| 343 | | 349 | |
| 344 | toastManager.update(progressToastId, { | 350 | toastManager.update(resolvedProgressToastId, { |
| 345 | type: "success", | 351 | type: "success", |
| 346 | title: resultToast.title, | 352 | title: resultToast.title, |
| 347 | description: resultToast.description, | 353 | description: resultToast.description, |
| ... | @@ -359,8 +365,8 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -359,8 +365,8 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 359 | action: "commit_push", | 365 | action: "commit_push", |
| 360 | forcePushOnlyProgress: true, | 366 | forcePushOnlyProgress: true, |
| 361 | onConfirmed: closeResultToast, | 367 | onConfirmed: closeResultToast, |
| 362 | ...(featureBranch ? { skipDefaultBranchPrompt: true } : {}), | 368 | statusOverride: actionStatus, |
| 363 | ...(featureBranch ? { isDefaultBranchOverride: false } : {}), | 369 | isDefaultBranchOverride: actionIsDefaultBranch, |
| 364 | }); | 370 | }); |
| 365 | }, | 371 | }, |
| 366 | }, | 372 | }, |
| ... | @@ -386,8 +392,8 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -386,8 +392,8 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 386 | void runGitActionWithToast({ | 392 | void runGitActionWithToast({ |
| 387 | action: "commit_push_pr", | 393 | action: "commit_push_pr", |
| 388 | forcePushOnlyProgress: true, | 394 | forcePushOnlyProgress: true, |
| 389 | ...(featureBranch ? { skipDefaultBranchPrompt: true } : {}), | 395 | statusOverride: actionStatus, |
| 390 | ...(featureBranch ? { isDefaultBranchOverride: false } : {}), | 396 | isDefaultBranchOverride: actionIsDefaultBranch, |
| 391 | }); | 397 | }); |
| 392 | }, | 398 | }, |
| 393 | }, | 399 | }, |
| ... | @@ -396,7 +402,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -396,7 +402,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 396 | }); | 402 | }); |
| 397 | } catch (err) { | 403 | } catch (err) { |
| 398 | stopProgressUpdates(); | 404 | stopProgressUpdates(); |
| 399 | toastManager.update(progressToastId, { | 405 | toastManager.update(resolvedProgressToastId, { |
| 400 | type: "error", | 406 | type: "error", |
| 401 | title: "Action failed", | 407 | title: "Action failed", |
| 402 | description: err instanceof Error ? err.message : "An error occurred.", | 408 | description: err instanceof Error ? err.message : "An error occurred.", |
| ... | @@ -406,7 +412,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -406,7 +412,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 406 | }, | 412 | }, |
| 407 | | 413 | |
| 408 | [ | 414 | [ |
| 409 | isDefaultBranchName, | 415 | isDefaultBranch, |
| 410 | runImmediateGitActionMutation, | 416 | runImmediateGitActionMutation, |
| 411 | setPendingDefaultBranchAction, | 417 | setPendingDefaultBranchAction, |
| 412 | threadToastData, | 418 | threadToastData, |
| ... | @@ -424,7 +430,6 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions | ... | @@ -424,7 +430,6 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions |
| 424 | forcePushOnlyProgress, | 430 | forcePushOnlyProgress, |
| 425 | ...(onConfirmed ? { onConfirmed } : {}), | 431 | ...(onConfirmed ? { onConfirmed } : {}), |
| 426 | skipDefaultBranchPrompt: true, | 432 | skipDefaultBranchPrompt: true, |
| 427 | isDefaultBranchOverride: true, | | |
| 428 | }); | 433 | }); |
| 429 | }, [pendingDefaultBranchAction, runGitActionWithToast]); | 434 | }, [pendingDefaultBranchAction, runGitActionWithToast]); |
| 430 | | 435 | |