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({...@@ -15,10 +15,13 @@ await waitOn({
15});15});
1616
17const command = process.platform === "win32" ? "electronmon.cmd" : "electronmon";17const command = process.platform === "win32" ? "electronmon.cmd" : "electronmon";
18const childEnv = { ...process.env };
19delete childEnv.ELECTRON_RUN_AS_NODE;
20
18const child = spawn(command, ["dist-electron/main.js"], {21const child = spawn(command, ["dist-electron/main.js"], {
19 stdio: "inherit",22 stdio: "inherit",
20 env: {23 env: {
21 ...process.env,24 ...childEnv,
22 VITE_DEV_SERVER_URL: devServerUrl,25 VITE_DEV_SERVER_URL: devServerUrl,
23 },26 },
24});27});
apps/web/src/components/GitActionsControl.tsx+44-93
...@@ -8,11 +8,9 @@ import { queryOptions, useMutation, useQuery, useQueryClient } from "@tanstack/r...@@ -8,11 +8,9 @@ import { queryOptions, useMutation, useQuery, useQueryClient } from "@tanstack/r
8import { useCallback, useEffect, useMemo, useRef, useState } from "react";8import { useCallback, useEffect, useMemo, useRef, useState } from "react";
9import {9import {
10 CheckIcon,10 CheckIcon,
11 CircleIcon,
12 CloudUploadIcon,11 CloudUploadIcon,
13 GitCommitIcon,12 GitCommitIcon,
14 Loader2Icon,13 Loader2Icon,
15 MinusIcon,
16 XIcon,14 XIcon,
17} from "lucide-react";15} from "lucide-react";
18import { GitHubIcon } from "./Icons";16import { GitHubIcon } from "./Icons";
...@@ -64,20 +62,11 @@ function GitActionIcon(props: { icon: GitActionIconName; disabled: boolean }) {...@@ -64,20 +62,11 @@ function GitActionIcon(props: { icon: GitActionIconName; disabled: boolean }) {
64 return <GitHubIcon className={`h-5 w-5 shrink-0 ${toneClass}`} />;62 return <GitHubIcon className={`h-5 w-5 shrink-0 ${toneClass}`} />;
65}63}
6664
67function GitProgressStatusIcon(props: { status: GitProgressStepStatus }) {65function runningStepMessage(stepId: GitProgressStep["id"]): string {
68 if (props.status === "running") {66 if (stepId === "generate") return "Generating commit message...";
69 return <Loader2Icon className="h-4 w-4 animate-spin text-foreground" />;67 if (stepId === "commit") return "Committing changes...";
70 }68 if (stepId === "push") return "Pushing branch...";
71 if (props.status === "completed") {69 return "Preparing pull request...";
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}70}
8271
83function gitActionModalTitle(): string {72function gitActionModalTitle(): string {
...@@ -315,6 +304,20 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp...@@ -315,6 +304,20 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp
315 gitModalProgress.length > 0 ||304 gitModalProgress.length > 0 ||
316 gitModalError !== null ||305 gitModalError !== null ||
317 gitModalResult !== null);306 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
319 const refreshGitStatus = useCallback(async () => {322 const refreshGitStatus = useCallback(async () => {
320 if (!api || !gitCwd) return;323 if (!api || !gitCwd) return;
...@@ -803,92 +806,40 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp...@@ -803,92 +806,40 @@ export default function GitActionsControl({ api, gitCwd }: GitActionsControlProp
803806
804 {showGitProgressToast && (807 {showGitProgressToast && (
805 <div808 <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]"
807 role="status"810 role="status"
808 aria-live="polite"811 aria-live="polite"
809 >812 >
810 <div className="rounded-2xl border border-border bg-popover/95 p-4 shadow-2xl backdrop-blur">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">
811 <div className="flex items-start justify-between gap-3">814 <span className="shrink-0">
812 <div className="min-w-0">815 {gitProgressToastStatus === "running" ? (
813 <p className="text-[11px] uppercase tracking-[0.14em] text-muted-foreground/65">816 <Loader2Icon className="h-4 w-4 animate-spin text-foreground" />
814 Git actions817 ) : gitProgressToastStatus === "failed" ? (
815 </p>818 <XIcon className="h-4 w-4 text-rose-500 dark:text-rose-300" />
816 <p className="mt-1 text-sm font-medium text-foreground">819 ) : (
817 {isGitModalActionRunning820 <CheckIcon className="h-4 w-4 text-emerald-600 dark:text-emerald-300" />
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>
882 )}821 )}
822 </span>
823 <span className="min-w-0 truncate text-sm text-foreground">{gitProgressToastMessage}</span>
824 {!isGitModalActionRunning && gitModalResult && gitProgressToastOpenPrUrl && (
883 <button825 <button
884 type="button"826 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"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"
886 onClick={dismissGitProgressToast}828 onClick={openPrFromToast}
887 disabled={isGitModalActionRunning}829 disabled={isGitModalActionRunning}
888 >830 >
889 Done831 Open PR
890 </button>832 </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>
892 </div>843 </div>
893 </div>844 </div>
894 )}845 )}