Repository navigation
Move git action progress to toast and stop auto-opening PR pages - #38
Conversation
- Keep the git action modal in selection mode while actions run in a dismissible progress toast - Remove automatic `gh pr view --web` calls; only return PR metadata and open links on explicit user action - Update server/web tests to assert no implicit PR browser open behavior
Move git action progress to a global toast in
|
WalkthroughRemoves automatic browser-opening for existing or newly created PRs, updates server git manager and tests accordingly, and refactors the Git actions UI to surface progress via a consolidated toast (with new progress state and messages) instead of inline modal steps. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Greptile OverviewGreptile SummaryRefactored git action UX to show progress in a persistent toast instead of blocking the modal, and removed automatic browser opening of PR pages. The modal now closes immediately when an action starts, displaying real-time progress in a fixed toast that allows users to explicitly choose to open PR links. Server-side Confidence Score: 5/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant Modal as GitActionsControl Modal
participant Toast as Progress Toast
participant Server as GitManager
participant GH as GitHub CLI
User->>Modal: Open & select action
User->>Modal: Click "Continue"
Modal->>Modal: Close modal
Modal->>Toast: Show toast with initial steps
Toast->>Server: runStackedAction()
alt Create/Open PR
Server->>GH: gh pr list (check existing)
alt PR exists
GH-->>Server: Return PR metadata
Note over Server: Skip gh pr view --web
Server-->>Toast: Return opened_existing + metadata
else PR doesn't exist
Server->>GH: gh pr create
GH-->>Server: PR created
Note over Server: Skip gh pr view --web
Server-->>Toast: Return created + metadata
end
end
Toast->>Toast: Update step statuses
Toast->>User: Show "Open PR" button
User->>Toast: Click "Open PR" (optional)
Toast->>GH: Open URL in browser
User->>Toast: Click "Done"
Toast->>Toast: Dismiss toast
Last reviewed commit: f4b1f43 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@apps/web/src/components/GitActionsControl.tsx`:
- Around line 783-798: The Run button is not disabled when the chosen action
option itself is disabled; update the button and the action entrypoint to guard
against disabled selections. Modify the Run button's disabled expression to
include the selected option's disabled flag (e.g.,
selectedGitModalActionOption?.disabled or gitModalSelectedAction?.disabled) in
addition to isGitActionRunning and selection presence, and also add an early
return guard in runGitAction() that checks the selected option's disabled flag
before proceeding so clicks/no-ops can't trigger when an option is disabled.
🧹 Nitpick comments (1)
apps/web/src/components/GitActionsControl.tsx (1)
392-403: UseuseTransitionfor tracking async action pending state instead of manual state management.Replace
isGitModalActionRunningstate withuseTransitionto automatically track the pending state of the async action. This eliminates manual state bookkeeping and leverages React 19's built-in pattern for async operations.When implementing, note that
dismissGitProgressToastwill need to be updated to access the pending state fromuseTransitionrather than as a separate state dependency.♻️ Suggested refactor (partial)
-import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState, useTransition } from "react"; ... -const [isGitModalActionRunning, setIsGitModalActionRunning] = useState(false); +const [isGitModalActionRunning, startGitActionTransition] = useTransition(); ... -const runGitAction = useCallback(async () => { +const runGitAction = useCallback(() => { if (!api || !gitCwd) return; if (!selectedGitModalActionOption || selectedGitModalActionOption.disabled) return; + startGitActionTransition(async () => { ... - setIsGitModalActionRunning(true); ... - } finally { - setIsGitModalActionRunning(false); - await refreshGitStatus().catch(() => undefined); - } + } finally { + await refreshGitStatus().catch(() => undefined); + } + }); -}, [api, gitCwd, gitModalCommitMessage, refreshGitStatus, selectedGitModalActionOption]); +}, [api, gitCwd, gitModalCommitMessage, refreshGitStatus, selectedGitModalActionOption, startGitActionTransition]);
| 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" | ||
| onClick={closeGitActionModal} | ||
| disabled={isGitActionRunning} | ||
| > | ||
| {gitModalResult ? "Done" : "Cancel"} | ||
| Cancel | ||
| </button> | ||
| <button | ||
| type="button" | ||
| 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" | ||
| onClick={() => { | ||
| void runGitAction(); | ||
| }} | ||
| disabled={isGitActionRunning || !selectedGitModalActionOption} | ||
| > | ||
| {runActionLabel(gitModalSelectedAction)} | ||
| </button> |
There was a problem hiding this comment.
Disable “Run” when the selected option is disabled.
Line 795 only disables on running/missing selection, but Line 394 still no-ops when the selected option is disabled, which feels broken.
🐛 Suggested fix
- disabled={isGitActionRunning || !selectedGitModalActionOption}
+ disabled={
+ isGitActionRunning ||
+ !selectedGitModalActionOption ||
+ selectedGitModalActionOption.disabled
+ }🤖 Prompt for AI Agents
In `@apps/web/src/components/GitActionsControl.tsx` around lines 783 - 798, The
Run button is not disabled when the chosen action option itself is disabled;
update the button and the action entrypoint to guard against disabled
selections. Modify the Run button's disabled expression to include the selected
option's disabled flag (e.g., selectedGitModalActionOption?.disabled or
gitModalSelectedAction?.disabled) in addition to isGitActionRunning and
selection presence, and also add an early return guard in runGitAction() that
checks the selected option's disabled flag before proceeding so clicks/no-ops
can't trigger when an option is disabled.
- 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
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@apps/web/src/components/GitActionsControl.tsx`:
- Around line 311-320: The toast always shows a generic "Git action failed."
even when gitModalError contains the real error; update the logic that builds
gitProgressToastMessage (and optionally gitProgressToastStatus) to surface the
actual error text from gitModalError (e.g., use gitModalError.message or
String(gitModalError)) instead of the hardcoded message; adjust the ternary
around isGitModalActionRunning / gitModalError that references
gitProgressToastMessage and gitProgressToastStatus so openPrFromToast failures
display the real error while preserving running state via
isGitModalActionRunning and using runningStepMessage(activeGitProgressStep?.id
?? "commit") when appropriate.
🧹 Nitpick comments (1)
apps/web/src/components/GitActionsControl.tsx (1)
783-799: Avoiddisabledon buttons; usearia-disabled+ click guards.This keeps buttons accessible and avoids tooltip breakage. Consider replacing
disabledwitharia-disabledand guarding inonClick.♿ Suggested refactor
- <button + <button type="button" - 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" - onClick={closeGitActionModal} - disabled={isGitActionRunning} + className={`rounded-xl border border-border px-4 py-2 text-sm text-foreground transition-colors duration-150 hover:bg-accent ${ + isGitActionRunning ? "cursor-not-allowed opacity-60" : "" + }`} + aria-disabled={isGitActionRunning} + onClick={() => { + if (isGitActionRunning) return; + closeGitActionModal(); + }} > Cancel </button> - <button + <button type="button" - 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" - onClick={() => { - void runGitAction(); - }} - disabled={isGitActionRunning || !selectedGitModalActionOption} + className={`rounded-xl bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors duration-150 hover:bg-foreground/90 ${ + isGitActionRunning || !selectedGitModalActionOption ? "cursor-not-allowed opacity-60" : "" + }`} + aria-disabled={isGitActionRunning || !selectedGitModalActionOption} + onClick={() => { + if (isGitActionRunning || !selectedGitModalActionOption) return; + void runGitAction(); + }} > {runActionLabel(gitModalSelectedAction)} </button>Based on learnings: Avoid using disabled props on buttons as they harm accessibility and break tooltips. Instead, use styling (e.g., opacity, hover states) and handle the disabled state through click handlers.
| const gitProgressToastStatus = isGitModalActionRunning | ||
| ? "running" | ||
| : gitModalError | ||
| ? "failed" | ||
| : "done"; | ||
| const gitProgressToastMessage = isGitModalActionRunning | ||
| ? runningStepMessage(activeGitProgressStep?.id ?? "commit") | ||
| : gitModalError | ||
| ? "Git action failed." | ||
| : "Done."; |
There was a problem hiding this comment.
Toast error text should surface the actual error.
If openPrFromToast fails, gitModalError is set but the toast always shows “Git action failed.”, which is misleading. Use the actual error message to avoid false failure reporting.
🛠️ Suggested change
- const gitProgressToastMessage = isGitModalActionRunning
- ? runningStepMessage(activeGitProgressStep?.id ?? "commit")
- : gitModalError
- ? "Git action failed."
- : "Done.";
+ const gitProgressToastMessage = isGitModalActionRunning
+ ? runningStepMessage(activeGitProgressStep?.id ?? "commit")
+ : gitModalError
+ ? gitModalError
+ : "Done.";📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const gitProgressToastStatus = isGitModalActionRunning | |
| ? "running" | |
| : gitModalError | |
| ? "failed" | |
| : "done"; | |
| const gitProgressToastMessage = isGitModalActionRunning | |
| ? runningStepMessage(activeGitProgressStep?.id ?? "commit") | |
| : gitModalError | |
| ? "Git action failed." | |
| : "Done."; | |
| const gitProgressToastStatus = isGitModalActionRunning | |
| ? "running" | |
| : gitModalError | |
| ? "failed" | |
| : "done"; | |
| const gitProgressToastMessage = isGitModalActionRunning | |
| ? runningStepMessage(activeGitProgressStep?.id ?? "commit") | |
| : gitModalError | |
| ? gitModalError | |
| : "Done."; |
🤖 Prompt for AI Agents
In `@apps/web/src/components/GitActionsControl.tsx` around lines 311 - 320, The
toast always shows a generic "Git action failed." even when gitModalError
contains the real error; update the logic that builds gitProgressToastMessage
(and optionally gitProgressToastStatus) to surface the actual error text from
gitModalError (e.g., use gitModalError.message or String(gitModalError)) instead
of the hardcoded message; adjust the ternary around isGitModalActionRunning /
gitModalError that references gitProgressToastMessage and gitProgressToastStatus
so openPrFromToast failures display the real error while preserving running
state via isGitModalActionRunning and using
runningStepMessage(activeGitProgressStep?.id ?? "commit") when appropriate.
`projects.readFile` answers with the path it actually read, which is not always the path that was asked for: a workspace that keeps its repositories in subdirectories has no file at the path a mention names, and the server resolves it into the checkout that does. The panel kept addressing the file by the path that was clicked, so a save went to that path instead — creating a stray file at the workspace root while the file on screen stayed untouched. Move the open surface onto the resolved path instead, keeping its reveal line and tab position, and close it when the destination is already open. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…rator merge anyway (pingdotgg#38)
Composer: Up/Down by shown lines, click to place the caret, drag to select
Range personal f93ae9c + origin/main 6497246, merge base 611132c. 57 conflicts (52 content, 3 modify/delete, 2 rename/delete), 192 upstream renames. Shape: upstream moved every provider but Codex and Claude into packages (provider-core/acp/acp-registry/cursor/grok/opencode/pi/muse/testing), drivers read settings through ProviderHost, and pingdotgg#17300 dropped the legacy providers settings map. Resolutions: - Fork-only files re-pointed at moved modules by package specifier (git rename map). - Legacy providers map: upstream's migration taken; fork patch mirrors and their tests (configDirPath, outputStyle, Codex setupMode) removed; trust rule follows upstream's decode. - Scoped settings: upstream's per-environment failure messages replace the fork's refusal copy. - Composer: upstream's Compact/Full chip and measured resting padding; fork send/stop row, offline-queue label and threadPanelSummary kept; attention dot dropped with upstream. - Migrations: upstream 059/060 applied as ids 68/69; preview-migration test stays rejected. - AuthPairingLinks: upstream pingdotgg#16730 fixed the boolean bind itself; fork patch retired. - ClaudeDriver offer-to-compact setting reads host.settings; tests build on ProviderHostLive. - OpenCodeRuntime back to upstream's inline encoder; fork diagnosticsJson.ts deleted. - Find-highlight cases (pingdotgg#10439) split into a jsdom file, as upstream runs them. - UsageService v4-upgrade test awaits its second persist (temp-dir removal race). Invariants: all re-probed; pingdotgg#38 caught resolveClaudeCatalogContextWindow losing export again. Sweeps (mid-merge): resurrected 4, dropped 283, fork-loss 370, both-kept 0; after filtering relocations, every residual line tied to a resolution (resurrected: 2 lockfile, 2 upstream test lines ported to the fork's fold-aware toggle helper). Gate: pnpm verify EXIT=0, 23/23 test packages, 25,310 tests, 0 failed (Node 24.16). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Summary
gh pr view --webbehavior so existing/new PRs are reported but not auto-opened.pr view.Testing
apps/server/src/gitManager.test.ts:opened_existingmetadata and does not callgh pr view.gh pr viewafter creation.Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Tests