| ... | @@ -64,6 +64,22 @@ function GitActionIcon(props: { icon: GitActionIconName; disabled: boolean }) { | ... | @@ -64,6 +64,22 @@ function GitActionIcon(props: { icon: GitActionIconName; disabled: boolean }) { |
| 64 | return <GitHubIcon className={`h-5 w-5 shrink-0 ${toneClass}`} />; | 64 | return <GitHubIcon className={`h-5 w-5 shrink-0 ${toneClass}`} />; |
| 65 | } | 65 | } |
| 66 | | 66 | |
| | 67 | function GitProgressStatusIcon(props: { status: GitProgressStepStatus }) { |
| | 68 | if (props.status === "running") { |
| | 69 | return <Loader2Icon className="h-4 w-4 animate-spin text-foreground" />; |
| | 70 | } |
| | 71 | if (props.status === "completed") { |
| | 72 | return <CheckIcon className="h-4 w-4 text-emerald-600 dark:text-emerald-300" />; |
| | 73 | } |
| | 74 | if (props.status === "skipped") { |
| | 75 | return <MinusIcon className="h-4 w-4 text-muted-foreground/70" />; |
| | 76 | } |
| | 77 | if (props.status === "failed") { |
| | 78 | return <XIcon className="h-4 w-4 text-rose-500 dark:text-rose-300" />; |
| | 79 | } |
| | 80 | return <CircleIcon className="h-4 w-4 text-muted-foreground/60" />; |
| | 81 | } |
| | 82 | |
| 67 | function gitActionModalTitle(): string { | 83 | function gitActionModalTitle(): string { |
| 68 | return "Commit your changes"; | 84 | return "Commit your changes"; |
| 69 | } | 85 | } |
| ... | @@ -249,6 +265,7 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -249,6 +265,7 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 249 | const [gitModalProgress, setGitModalProgress] = useState<GitProgressStep[]>([]); | 265 | const [gitModalProgress, setGitModalProgress] = useState<GitProgressStep[]>([]); |
| 250 | const [gitModalError, setGitModalError] = useState<string | null>(null); | 266 | const [gitModalError, setGitModalError] = useState<string | null>(null); |
| 251 | const [gitModalResult, setGitModalResult] = useState<GitRunStackedActionResult | null>(null); | 267 | const [gitModalResult, setGitModalResult] = useState<GitRunStackedActionResult | null>(null); |
| | 268 | const [isGitProgressToastVisible, setIsGitProgressToastVisible] = useState(false); |
| 252 | const gitMenuRef = useRef<HTMLDivElement>(null); | 269 | const gitMenuRef = useRef<HTMLDivElement>(null); |
| 253 | | 270 | |
| 254 | const { data: gitStatus = null, error: gitStatusError } = useQuery( | 271 | const { data: gitStatus = null, error: gitStatusError } = useQuery( |
| ... | @@ -291,10 +308,13 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -291,10 +308,13 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 291 | [gitModalActionOptions, gitModalSelectedAction], | 308 | [gitModalActionOptions, gitModalSelectedAction], |
| 292 | ); | 309 | ); |
| 293 | const visibleGitActionError = gitActionError ?? gitStatusError?.message; | 310 | const visibleGitActionError = gitActionError ?? gitStatusError?.message; |
| 294 | const gitModalOpenPrUrl = gitModalResult?.pr.url ?? gitStatus?.openPr?.url ?? null; | 311 | const gitProgressToastOpenPrUrl = gitModalResult?.pr.url ?? gitStatus?.openPr?.url ?? null; |
| 295 | const gitModalHasProgress = gitModalProgress.length > 0; | 312 | const showGitProgressToast = |
| 296 | const gitModalSelectionMode = !gitModalHasProgress && gitModalResult === null; | 313 | isGitProgressToastVisible && |
| 297 | const gitModalSteps = gitModalProgress; | 314 | (isGitModalActionRunning || |
| | 315 | gitModalProgress.length > 0 || |
| | 316 | gitModalError !== null || |
| | 317 | gitModalResult !== null); |
| 298 | | 318 | |
| 299 | const refreshGitStatus = useCallback(async () => { | 319 | const refreshGitStatus = useCallback(async () => { |
| 300 | if (!api || !gitCwd) return; | 320 | if (!api || !gitCwd) return; |
| ... | @@ -307,6 +327,7 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -307,6 +327,7 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 307 | setIsGitModalOpen(true); | 327 | setIsGitModalOpen(true); |
| 308 | setGitModalSelectedAction("commit"); | 328 | setGitModalSelectedAction("commit"); |
| 309 | setGitModalCommitMessage(""); | 329 | setGitModalCommitMessage(""); |
| | 330 | setIsGitProgressToastVisible(false); |
| 310 | setGitModalProgress([]); | 331 | setGitModalProgress([]); |
| 311 | setGitModalError(null); | 332 | setGitModalError(null); |
| 312 | setGitModalResult(null); | 333 | setGitModalResult(null); |
| ... | @@ -318,9 +339,6 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -318,9 +339,6 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 318 | setIsGitModalOpen(false); | 339 | setIsGitModalOpen(false); |
| 319 | setGitModalSelectedAction("commit"); | 340 | setGitModalSelectedAction("commit"); |
| 320 | setGitModalCommitMessage(""); | 341 | setGitModalCommitMessage(""); |
| 321 | setGitModalProgress([]); | | |
| 322 | setGitModalError(null); | | |
| 323 | setGitModalResult(null); | | |
| 324 | }, [isGitActionRunning]); | 342 | }, [isGitActionRunning]); |
| 325 | | 343 | |
| 326 | const runGitActionImmediately = useCallback( | 344 | const runGitActionImmediately = useCallback( |
| ... | @@ -349,28 +367,39 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -349,28 +367,39 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 349 | }); | 367 | }); |
| 350 | }, [api, gitStatus?.openPr?.url]); | 368 | }, [api, gitStatus?.openPr?.url]); |
| 351 | | 369 | |
| 352 | const openPrFromModal = useCallback(() => { | 370 | const openPrFromToast = useCallback(() => { |
| 353 | if (!api) { | 371 | if (!api) { |
| 354 | setGitModalError("Link opening is unavailable."); | 372 | setGitModalError("Link opening is unavailable."); |
| 355 | return; | 373 | return; |
| 356 | } | 374 | } |
| 357 | | 375 | |
| 358 | const prUrl = gitModalOpenPrUrl; | 376 | const prUrl = gitProgressToastOpenPrUrl; |
| 359 | if (!prUrl) return; | 377 | if (!prUrl) return; |
| 360 | | 378 | |
| 361 | void api.shell.openExternal(prUrl).catch((error) => { | 379 | void api.shell.openExternal(prUrl).catch((error) => { |
| 362 | setGitModalError(error instanceof Error ? error.message : "Unable to open PR link."); | 380 | setGitModalError(error instanceof Error ? error.message : "Unable to open PR link."); |
| 363 | }); | 381 | }); |
| 364 | }, [api, gitModalOpenPrUrl]); | 382 | }, [api, gitProgressToastOpenPrUrl]); |
| | 383 | |
| | 384 | const dismissGitProgressToast = useCallback(() => { |
| | 385 | if (isGitModalActionRunning) return; |
| | 386 | setIsGitProgressToastVisible(false); |
| | 387 | setGitModalProgress([]); |
| | 388 | setGitModalError(null); |
| | 389 | setGitModalResult(null); |
| | 390 | }, [isGitModalActionRunning]); |
| 365 | | 391 | |
| 366 | const runGitAction = useCallback(async () => { | 392 | const runGitAction = useCallback(async () => { |
| 367 | if (!api || !gitCwd || !isGitModalOpen) return; | 393 | if (!api || !gitCwd) return; |
| 368 | if (!selectedGitModalActionOption || selectedGitModalActionOption.disabled) return; | 394 | if (!selectedGitModalActionOption || selectedGitModalActionOption.disabled) return; |
| 369 | const actionCwd = gitCwd; | 395 | const actionCwd = gitCwd; |
| 370 | const action = selectedGitModalActionOption.action; | 396 | const action = selectedGitModalActionOption.action; |
| 371 | const commitMessage = gitModalCommitMessage.trim(); | 397 | const commitMessage = gitModalCommitMessage.trim(); |
| 372 | const includeGeneratedCommitMessage = commitMessage.length === 0; | 398 | const includeGeneratedCommitMessage = commitMessage.length === 0; |
| 373 | | 399 | |
| | 400 | setIsGitMenuOpen(false); |
| | 401 | setIsGitModalOpen(false); |
| | 402 | setIsGitProgressToastVisible(true); |
| 374 | setIsGitModalActionRunning(true); | 403 | setIsGitModalActionRunning(true); |
| 375 | setGitModalError(null); | 404 | setGitModalError(null); |
| 376 | setGitActionError(null); | 405 | setGitActionError(null); |
| ... | @@ -488,7 +517,6 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -488,7 +517,6 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 488 | api, | 517 | api, |
| 489 | gitCwd, | 518 | gitCwd, |
| 490 | gitModalCommitMessage, | 519 | gitModalCommitMessage, |
| 491 | isGitModalOpen, | | |
| 492 | refreshGitStatus, | 520 | refreshGitStatus, |
| 493 | selectedGitModalActionOption, | 521 | selectedGitModalActionOption, |
| 494 | ]); | 522 | ]); |
| ... | @@ -497,6 +525,7 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -497,6 +525,7 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 497 | setGitActionError(null); | 525 | setGitActionError(null); |
| 498 | setGitModalError(null); | 526 | setGitModalError(null); |
| 499 | setIsGitModalOpen(false); | 527 | setIsGitModalOpen(false); |
| | 528 | setIsGitProgressToastVisible(false); |
| 500 | setGitModalSelectedAction("commit"); | 529 | setGitModalSelectedAction("commit"); |
| 501 | setGitModalCommitMessage(""); | 530 | setGitModalCommitMessage(""); |
| 502 | setGitModalProgress([]); | 531 | setGitModalProgress([]); |
| ... | @@ -690,92 +719,57 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -690,92 +719,57 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 690 | placeholder="Leave blank to autogenerate a commit message" | 719 | placeholder="Leave blank to autogenerate a commit message" |
| 691 | value={gitModalCommitMessage} | 720 | value={gitModalCommitMessage} |
| 692 | onChange={(event) => setGitModalCommitMessage(event.target.value)} | 721 | onChange={(event) => setGitModalCommitMessage(event.target.value)} |
| 693 | disabled={!gitModalSelectionMode || isGitActionRunning} | 722 | disabled={isGitActionRunning} |
| 694 | /> | 723 | /> |
| 695 | </div> | 724 | </div> |
| 696 | <div className="mt-6"> | 725 | <div className="mt-6"> |
| 697 | <p className="text-sm font-medium text-foreground">Next steps</p> | 726 | <p className="text-sm font-medium text-foreground">Next steps</p> |
| 698 | <div className="mt-2 overflow-hidden rounded-2xl border border-border"> | 727 | <div className="mt-2 overflow-hidden rounded-2xl border border-border"> |
| 699 | {gitModalSelectionMode && | 728 | {gitModalActionOptions.map((option, index) => { |
| 700 | gitModalActionOptions.map((option, index) => { | 729 | const borderClass = |
| 701 | const borderClass = | 730 | index < gitModalActionOptions.length - 1 ? "border-b border-border/70" : ""; |
| 702 | index < gitModalActionOptions.length - 1 ? "border-b border-border/70" : ""; | 731 | const selected = option.action === gitModalSelectedAction && !option.disabled; |
| 703 | const selected = option.action === gitModalSelectedAction && !option.disabled; | 732 | const disabled = option.disabled || isGitActionRunning; |
| 704 | const disabled = option.disabled || isGitActionRunning; | 733 | |
| 705 | | 734 | return ( |
| 706 | return ( | 735 | <button |
| 707 | <button | 736 | key={option.action} |
| 708 | key={option.action} | 737 | type="button" |
| 709 | type="button" | 738 | className={`flex w-full items-start gap-3 px-4 py-3 text-left transition-colors duration-150 ${borderClass} ${ |
| 710 | className={`flex w-full items-start gap-3 px-4 py-3 text-left transition-colors duration-150 ${borderClass} ${ | 739 | selected |
| 711 | selected | 740 | ? "bg-accent/55" |
| 712 | ? "bg-accent/55" | 741 | : disabled |
| 713 | : disabled | 742 | ? "bg-card/25" |
| 714 | ? "bg-card/25" | 743 | : "bg-card/45 hover:bg-accent/35" |
| 715 | : "bg-card/45 hover:bg-accent/35" | 744 | } disabled:cursor-not-allowed`} |
| 716 | } disabled:cursor-not-allowed`} | 745 | disabled={disabled} |
| 717 | disabled={disabled} | 746 | onClick={() => { |
| 718 | onClick={() => { | 747 | setGitModalSelectedAction(option.action); |
| 719 | setGitModalSelectedAction(option.action); | 748 | }} |
| 720 | }} | 749 | > |
| 721 | > | 750 | <span className="mt-0.5"> |
| 722 | <span className="mt-0.5"> | 751 | <GitActionIcon icon={option.icon} disabled={option.disabled} /> |
| 723 | <GitActionIcon icon={option.icon} disabled={option.disabled} /> | 752 | </span> |
| 724 | </span> | 753 | <div className="min-w-0 flex-1"> |
| 725 | <div className="min-w-0 flex-1"> | 754 | <p |
| | 755 | className={`text-sm ${disabled ? "text-muted-foreground/60" : "text-foreground"}`} |
| | 756 | > |
| | 757 | {option.label} |
| | 758 | </p> |
| | 759 | {option.detail && ( |
| 726 | <p | 760 | <p |
| 727 | className={`text-sm ${disabled ? "text-muted-foreground/60" : "text-foreground"}`} | 761 | className={`mt-0.5 text-xs ${disabled ? "text-muted-foreground/55" : "text-muted-foreground/70"}`} |
| 728 | > | 762 | > |
| 729 | {option.label} | 763 | {option.detail} |
| 730 | </p> | 764 | </p> |
| 731 | {option.detail && ( | 765 | )} |
| 732 | <p | | |
| 733 | className={`mt-0.5 text-xs ${disabled ? "text-muted-foreground/55" : "text-muted-foreground/70"}`} | | |
| 734 | > | | |
| 735 | {option.detail} | | |
| 736 | </p> | | |
| 737 | )} | | |
| 738 | </div> | | |
| 739 | {selected && !disabled ? ( | | |
| 740 | <CheckIcon className="mt-0.5 h-4 w-4 shrink-0 text-foreground" /> | | |
| 741 | ) : null} | | |
| 742 | </button> | | |
| 743 | ); | | |
| 744 | })} | | |
| 745 | {!gitModalSelectionMode && | | |
| 746 | gitModalSteps.map((step, index) => { | | |
| 747 | const borderClass = | | |
| 748 | index < gitModalSteps.length - 1 ? "border-b border-border/70" : ""; | | |
| 749 | | | |
| 750 | return ( | | |
| 751 | <div | | |
| 752 | key={step.id} | | |
| 753 | className={`flex items-start gap-3 bg-card/45 px-4 py-3 ${borderClass}`} | | |
| 754 | > | | |
| 755 | <span className="mt-0.5"> | | |
| 756 | {step.status === "running" ? ( | | |
| 757 | <Loader2Icon className="h-4 w-4 animate-spin text-foreground" /> | | |
| 758 | ) : step.status === "completed" ? ( | | |
| 759 | <CheckIcon className="h-4 w-4 text-emerald-600 dark:text-emerald-300" /> | | |
| 760 | ) : step.status === "skipped" ? ( | | |
| 761 | <MinusIcon className="h-4 w-4 text-muted-foreground/70" /> | | |
| 762 | ) : step.status === "failed" ? ( | | |
| 763 | <XIcon className="h-4 w-4 text-rose-500 dark:text-rose-300" /> | | |
| 764 | ) : ( | | |
| 765 | <CircleIcon className="h-4 w-4 text-muted-foreground/60" /> | | |
| 766 | )} | | |
| 767 | </span> | | |
| 768 | <div className="min-w-0"> | | |
| 769 | <p className="text-sm text-foreground">{step.label}</p> | | |
| 770 | {step.status === "failed" && step.detail && ( | | |
| 771 | <p className="mt-0.5 text-xs text-rose-500 dark:text-rose-300"> | | |
| 772 | {step.detail} | | |
| 773 | </p> | | |
| 774 | )} | | |
| 775 | </div> | | |
| 776 | </div> | 766 | </div> |
| 777 | ); | 767 | {selected && !disabled ? ( |
| 778 | })} | 768 | <CheckIcon className="mt-0.5 h-4 w-4 shrink-0 text-foreground" /> |
| | 769 | ) : null} |
| | 770 | </button> |
| | 771 | ); |
| | 772 | })} |
| 779 | </div> | 773 | </div> |
| 780 | </div> | 774 | </div> |
| 781 | {(gitModalError ?? visibleGitActionError) && ( | 775 | {(gitModalError ?? visibleGitActionError) && ( |
| ... | @@ -784,44 +778,116 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp | ... | @@ -784,44 +778,116 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp |
| 784 | </div> | 778 | </div> |
| 785 | )} | 779 | )} |
| 786 | <div className="mt-6 flex justify-end gap-2"> | 780 | <div className="mt-6 flex justify-end gap-2"> |
| 787 | {gitModalResult && gitModalOpenPrUrl && ( | | |
| 788 | <button | | |
| 789 | type="button" | | |
| 790 | className="rounded-xl border border-border px-4 py-2 text-sm text-foreground transition-colors duration-150 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60" | | |
| 791 | onClick={openPrFromModal} | | |
| 792 | disabled={isGitActionRunning} | | |
| 793 | > | | |
| 794 | Open PR | | |
| 795 | </button> | | |
| 796 | )} | | |
| 797 | <button | 781 | <button |
| 798 | type="button" | 782 | type="button" |
| 799 | className={ | 783 | className="rounded-xl border border-border px-4 py-2 text-sm text-foreground transition-colors duration-150 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60" |
| 800 | gitModalResult | | |
| 801 | ? "rounded-xl bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors duration-150 hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60" | | |
| 802 | : "rounded-xl border border-border px-4 py-2 text-sm text-foreground transition-colors duration-150 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60" | | |
| 803 | } | | |
| 804 | onClick={closeGitActionModal} | 784 | onClick={closeGitActionModal} |
| 805 | disabled={isGitActionRunning} | 785 | disabled={isGitActionRunning} |
| 806 | > | 786 | > |
| 807 | {gitModalResult ? "Done" : "Cancel"} | 787 | Cancel |
| | 788 | </button> |
| | 789 | <button |
| | 790 | type="button" |
| | 791 | className="rounded-xl bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors duration-150 hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60" |
| | 792 | onClick={() => { |
| | 793 | void runGitAction(); |
| | 794 | }} |
| | 795 | disabled={isGitActionRunning || !selectedGitModalActionOption} |
| | 796 | > |
| | 797 | {runActionLabel(gitModalSelectedAction)} |
| | 798 | </button> |
| | 799 | </div> |
| | 800 | </div> |
| | 801 | </div> |
| | 802 | )} |
| | 803 | |
| | 804 | {showGitProgressToast && ( |
| | 805 | <div |
| | 806 | className="fixed bottom-4 right-4 z-[90] w-[min(420px,calc(100vw-2rem))]" |
| | 807 | role="status" |
| | 808 | aria-live="polite" |
| | 809 | > |
| | 810 | <div className="rounded-2xl border border-border bg-popover/95 p-4 shadow-2xl backdrop-blur"> |
| | 811 | <div className="flex items-start justify-between gap-3"> |
| | 812 | <div className="min-w-0"> |
| | 813 | <p className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground/65"> |
| | 814 | Git actions |
| | 815 | </p> |
| | 816 | <p className="mt-1 text-sm font-medium text-foreground"> |
| | 817 | {isGitModalActionRunning |
| | 818 | ? "Running action..." |
| | 819 | : gitModalError |
| | 820 | ? "Action failed" |
| | 821 | : "Action complete"} |
| | 822 | </p> |
| | 823 | </div> |
| | 824 | <button |
| | 825 | type="button" |
| | 826 | className="rounded-md p-1 text-muted-foreground/60 transition-colors duration-150 hover:bg-accent hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50" |
| | 827 | onClick={dismissGitProgressToast} |
| | 828 | disabled={isGitModalActionRunning} |
| | 829 | aria-label="Dismiss git action progress toast" |
| | 830 | > |
| | 831 | <XIcon className="h-4 w-4" /> |
| 808 | </button> | 832 | </button> |
| 809 | {!gitModalResult && ( | 833 | </div> |
| | 834 | {gitModalProgress.length > 0 && ( |
| | 835 | <div className="mt-3 overflow-hidden rounded-xl border border-border/80"> |
| | 836 | {gitModalProgress.map((step, index) => { |
| | 837 | const borderClass = |
| | 838 | index < gitModalProgress.length - 1 ? "border-b border-border/70" : ""; |
| | 839 | |
| | 840 | return ( |
| | 841 | <div |
| | 842 | key={step.id} |
| | 843 | className={`flex items-start gap-3 bg-card/45 px-3.5 py-2.5 ${borderClass}`} |
| | 844 | > |
| | 845 | <span className="mt-0.5"> |
| | 846 | <GitProgressStatusIcon status={step.status} /> |
| | 847 | </span> |
| | 848 | <div className="min-w-0"> |
| | 849 | <p className="text-sm text-foreground">{step.label}</p> |
| | 850 | {step.detail && ( |
| | 851 | <p |
| | 852 | className={`mt-0.5 text-xs ${ |
| | 853 | step.status === "failed" |
| | 854 | ? "text-rose-500 dark:text-rose-300" |
| | 855 | : "text-muted-foreground/70" |
| | 856 | }`} |
| | 857 | > |
| | 858 | {step.detail} |
| | 859 | </p> |
| | 860 | )} |
| | 861 | </div> |
| | 862 | </div> |
| | 863 | ); |
| | 864 | })} |
| | 865 | </div> |
| | 866 | )} |
| | 867 | {gitModalError && ( |
| | 868 | <div className="mt-3 rounded-lg border border-rose-300/50 bg-rose-500/10 px-3 py-2 text-xs text-rose-600 dark:text-rose-200"> |
| | 869 | {gitModalError} |
| | 870 | </div> |
| | 871 | )} |
| | 872 | <div className="mt-3 flex justify-end gap-2"> |
| | 873 | {!isGitModalActionRunning && gitModalResult && gitProgressToastOpenPrUrl && ( |
| 810 | <button | 874 | <button |
| 811 | type="button" | 875 | type="button" |
| 812 | className="rounded-xl bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors duration-150 hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60" | 876 | className="rounded-xl border border-border px-4 py-2 text-sm text-foreground transition-colors duration-150 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-60" |
| 813 | onClick={() => { | 877 | onClick={openPrFromToast} |
| 814 | void runGitAction(); | 878 | disabled={isGitModalActionRunning} |
| 815 | }} | | |
| 816 | disabled={isGitActionRunning || !selectedGitModalActionOption} | | |
| 817 | > | 879 | > |
| 818 | {isGitActionRunning | 880 | Open PR |
| 819 | ? "Running..." | | |
| 820 | : gitModalSelectionMode | | |
| 821 | ? "Continue" | | |
| 822 | : runActionLabel(gitModalSelectedAction)} | | |
| 823 | </button> | 881 | </button> |
| 824 | )} | 882 | )} |
| | 883 | <button |
| | 884 | type="button" |
| | 885 | className="rounded-xl bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors duration-150 hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60" |
| | 886 | onClick={dismissGitProgressToast} |
| | 887 | disabled={isGitModalActionRunning} |
| | 888 | > |
| | 889 | Done |
| | 890 | </button> |
| 825 | </div> | 891 | </div> |
| 826 | </div> | 892 | </div> |
| 827 | </div> | 893 | </div> |