authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-13 15:20:00-08:00
committergravatar for jmarminge@gmail.comJulius Marminge <jmarminge@gmail.com> 2026-02-13 15:26:36-08:00
log9e3fa3e67f1642f43b89f6260b5b93d4295344b0
treefe171862269ceb37fe66a5f2ec26a8c773fc0e5c
parent38de3417b8fe79ff97711631718d0a4929b079a7

Fix Electron dev env and streamline Git action toast

- Remove `ELECTRON_RUN_AS_NODE` before spawning `electronmon` in desktop dev script - Replace detailed multi-step Git progress toast with a compact status message + optional Open PR action

2 files changed, 48 insertions(+), 94 deletions(-)

apps/desktop/scripts/dev-electron.mjs+4-1
......@@ -15,10 +15,13 @@ await waitOn({
1515});
1616
1717const command = process.platform === "win32" ? "electronmon.cmd" : "electronmon";
18const childEnv = { ...process.env };
19delete childEnv.ELECTRON_RUN_AS_NODE;
20
1821const child = spawn(command, ["dist-electron/main.js"], {
1922 stdio: "inherit",
2023 env: {
21 ...process.env,
24 ...childEnv,
2225 VITE_DEV_SERVER_URL: devServerUrl,
2326 },
2427});
apps/web/src/components/GitActionsControl.tsx+44-93
......@@ -8,11 +8,9 @@ import { queryOptions, useMutation, useQuery, useQueryClient } from "@tanstack/r
88import { useCallback, useEffect, useMemo, useRef, useState } from "react";
99import {
1010 CheckIcon,
11 CircleIcon,
1211 CloudUploadIcon,
1312 GitCommitIcon,
1413 Loader2Icon,
15 MinusIcon,
1614 XIcon,
1715} from "lucide-react";
1816import { GitHubIcon } from "./Icons";
......@@ -64,20 +62,11 @@ function GitActionIcon(props: { icon: GitActionIconName; disabled: boolean }) {
6462 return <GitHubIcon className={`h-5 w-5 shrink-0 ${toneClass}`} />;
6563}
6664
67function 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" />;
65function runningStepMessage(stepId: GitProgressStep["id"]): string {
66 if (stepId === "generate") return "Generating commit message...";
67 if (stepId === "commit") return "Committing changes...";
68 if (stepId === "push") return "Pushing branch...";
69 return "Preparing pull request...";
8170}
8271
8372function gitActionModalTitle(): string {
......@@ -315,6 +304,20 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp
315304 gitModalProgress.length > 0 ||
316305 gitModalError !== null ||
317306 gitModalResult !== null);
307 const activeGitProgressStep = useMemo(
308 () => gitModalProgress.find((step) => step.status === "running") ?? null,
309 [gitModalProgress],
310 );
311 const gitProgressToastStatus = isGitModalActionRunning
312 ? "running"
313 : gitModalError
314 ? "failed"
315 : "done";
316 const gitProgressToastMessage = isGitModalActionRunning
317 ? runningStepMessage(activeGitProgressStep?.id ?? "commit")
318 : gitModalError
319 ? "Git action failed."
320 : "Done.";
318321
319322 const refreshGitStatus = useCallback(async () => {
320323 if (!api || !gitCwd) return;
......@@ -803,92 +806,40 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp
803806
804807 {showGitProgressToast && (
805808 <div
806 className="fixed bottom-4 right-4 z-[90] w-[min(420px,calc(100vw-2rem))]"
809 className="fixed bottom-4 right-4 z-[90]"
807810 role="status"
808811 aria-live="polite"
809812 >
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" />
832 </button>
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 && (
874 <button
875 type="button"
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"
877 onClick={openPrFromToast}
878 disabled={isGitModalActionRunning}
879 >
880 Open PR
881 </button>
813 <div className="flex max-w-[calc(100vw-2rem)] items-center gap-2 rounded-xl border border-border bg-popover/95 px-3 py-2 shadow-xl backdrop-blur">
814 <span className="shrink-0">
815 {gitProgressToastStatus === "running" ? (
816 <Loader2Icon className="h-4 w-4 animate-spin text-foreground" />
817 ) : gitProgressToastStatus === "failed" ? (
818 <XIcon className="h-4 w-4 text-rose-500 dark:text-rose-300" />
819 ) : (
820 <CheckIcon className="h-4 w-4 text-emerald-600 dark:text-emerald-300" />
882821 )}
822 </span>
823 <span className="min-w-0 truncate text-sm text-foreground">{gitProgressToastMessage}</span>
824 {!isGitModalActionRunning && gitModalResult && gitProgressToastOpenPrUrl && (
883825 <button
884826 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}
827 className="rounded-md bg-foreground px-2.5 py-1 text-xs font-medium text-background transition-colors duration-150 hover:bg-foreground/90 disabled:cursor-not-allowed disabled:opacity-60"
828 onClick={openPrFromToast}
887829 disabled={isGitModalActionRunning}
888830 >
889 Done
831 Open PR
890832 </button>
891 </div>
833 )}
834 <button
835 type="button"
836 className="rounded p-1 text-muted-foreground/60 transition-colors duration-150 hover:bg-accent hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50"
837 onClick={dismissGitProgressToast}
838 disabled={isGitModalActionRunning}
839 aria-label="Dismiss git action progress toast"
840 >
841 <XIcon className="h-4 w-4" />
842 </button>
892843 </div>
893844 </div>
894845 )}