authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-03-01 19:29:40-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-03-01 20:06:01-08:00
loga8059dc2c0341e72efab496c88b15b8dadac71e2
treeca0ab25f65fa8a2e5e5b113ba41e9959acb47f7f
parentbe873bca3e75d6fb983593d1daeee98d97498bc2

fix: reuse git action toast after feature-branch checkout

Co-authored-by: codex <codex@users.noreply.github.com>

1 files changed, 39 insertions(+), 22 deletions(-)

apps/web/src/components/GitActionsControl.tsx+39-22
...@@ -58,6 +58,8 @@ interface PendingDefaultBranchAction {...@@ -58,6 +58,8 @@ interface PendingDefaultBranchAction {
58 onConfirmed?: () => void;58 onConfirmed?: () => void;
59}59}
6060
61type GitActionToastId = ReturnType<typeof toastManager.add>;
62
61function getMenuActionDisabledReason(63function getMenuActionDisabledReason(
62 item: GitActionMenuItem,64 item: GitActionMenuItem,
63 gitStatus: GitStatusResult | null,65 gitStatus: GitStatusResult | null,
...@@ -245,6 +247,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions...@@ -245,6 +247,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions
245 skipDefaultBranchPrompt = false,247 skipDefaultBranchPrompt = false,
246 statusOverride,248 statusOverride,
247 isDefaultBranchOverride,249 isDefaultBranchOverride,
250 progressToastId,
248 }: {251 }: {
249 action: GitStackedAction;252 action: GitStackedAction;
250 commitMessage?: string;253 commitMessage?: string;
...@@ -253,6 +256,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions...@@ -253,6 +256,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions
253 skipDefaultBranchPrompt?: boolean;256 skipDefaultBranchPrompt?: boolean;
254 statusOverride?: GitStatusResult | null;257 statusOverride?: GitStatusResult | null;
255 isDefaultBranchOverride?: boolean;258 isDefaultBranchOverride?: boolean;
259 progressToastId?: GitActionToastId;
256 }) => {260 }) => {
257 const actionStatus = statusOverride ?? gitStatusForActions;261 const actionStatus = statusOverride ?? gitStatusForActions;
258 const actionIsDefaultBranch = isDefaultBranchOverride ?? isDefaultBranch;262 const actionIsDefaultBranch = isDefaultBranchOverride ?? isDefaultBranch;
...@@ -284,17 +288,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions...@@ -284,17 +288,28 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions
284 forcePushOnly: forcePushOnlyProgress,288 forcePushOnly: forcePushOnlyProgress,
285 ...(pushTarget ? { pushTarget } : {}),289 ...(pushTarget ? { pushTarget } : {}),
286 });290 });
287 const progressToastId = toastManager.add({291 const resolvedProgressToastId =
288 type: "loading",292 progressToastId ??
289 title: progressStages[0] ?? "Running git action...",293 toastManager.add({
290 timeout: 0,294 type: "loading",
291 data: threadToastData,295 title: progressStages[0] ?? "Running git action...",
292 });296 timeout: 0,
297 data: threadToastData,
298 });
299
300 if (progressToastId) {
301 toastManager.update(progressToastId, {
302 type: "loading",
303 title: progressStages[0] ?? "Running git action...",
304 timeout: 0,
305 data: threadToastData,
306 });
307 }
293308
294 let stageIndex = 0;309 let stageIndex = 0;
295 const stageInterval = setInterval(() => {310 const stageInterval = setInterval(() => {
296 stageIndex = Math.min(stageIndex + 1, progressStages.length - 1);311 stageIndex = Math.min(stageIndex + 1, progressStages.length - 1);
297 toastManager.update(progressToastId, {312 toastManager.update(resolvedProgressToastId, {
298 title: progressStages[stageIndex] ?? "Running git action...",313 title: progressStages[stageIndex] ?? "Running git action...",
299 type: "loading",314 type: "loading",
300 timeout: 0,315 timeout: 0,
...@@ -329,10 +344,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions...@@ -329,10 +344,10 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions
329 result.push.status === "pushed" &&344 result.push.status === "pushed" &&
330 !actionIsDefaultBranch;345 !actionIsDefaultBranch;
331 const closeResultToast = () => {346 const closeResultToast = () => {
332 toastManager.close(progressToastId);347 toastManager.close(resolvedProgressToastId);
333 };348 };
334349
335 toastManager.update(progressToastId, {350 toastManager.update(resolvedProgressToastId, {
336 type: "success",351 type: "success",
337 title: resultToast.title,352 title: resultToast.title,
338 description: resultToast.description,353 description: resultToast.description,
...@@ -386,7 +401,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions...@@ -386,7 +401,7 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions
386 });401 });
387 } catch (err) {402 } catch (err) {
388 stopProgressUpdates();403 stopProgressUpdates();
389 toastManager.update(progressToastId, {404 toastManager.update(resolvedProgressToastId, {
390 type: "error",405 type: "error",
391 title: "Action failed",406 title: "Action failed",
392 description: err instanceof Error ? err.message : "An error occurred.",407 description: err instanceof Error ? err.message : "An error occurred.",
...@@ -429,17 +444,11 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions...@@ -429,17 +444,11 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions
429 );444 );
430445
431 const checkoutPromise = createBranchAndCheckoutMutation.mutateAsync(branchName);446 const checkoutPromise = createBranchAndCheckoutMutation.mutateAsync(branchName);
432 toastManager.promise(checkoutPromise, {447 const checkoutToastId = toastManager.add({
433 loading: { title: `Creating ${branchName}...`, data: threadToastData },448 type: "loading",
434 success: () => ({449 title: `Creating ${branchName}...`,
435 title: `Checked out ${branchName}`,450 timeout: 0,
436 data: threadToastData,451 data: threadToastData,
437 }),
438 error: (error) => ({
439 title: "Failed to checkout feature branch",
440 description: error instanceof Error ? error.message : "An error occurred.",
441 data: threadToastData,
442 }),
443 });452 });
444453
445 void checkoutPromise454 void checkoutPromise
...@@ -459,9 +468,17 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions...@@ -459,9 +468,17 @@ export default function GitActionsControl({ gitCwd, activeThreadId }: GitActions
459 skipDefaultBranchPrompt: true,468 skipDefaultBranchPrompt: true,
460 statusOverride,469 statusOverride,
461 isDefaultBranchOverride: false,470 isDefaultBranchOverride: false,
471 progressToastId: checkoutToastId,
462 });472 });
463 })473 })
464 .catch(() => undefined);474 .catch((error) => {
475 toastManager.update(checkoutToastId, {
476 type: "error",
477 title: "Failed to checkout feature branch",
478 description: error instanceof Error ? error.message : "An error occurred.",
479 data: threadToastData,
480 });
481 });
465 },482 },
466 [483 [
467 branchList?.branches,484 branchList?.branches,