Repository navigation
feat(code): unify user-scoped GitHub connect into a shared hook - #1996
Conversation
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/code/src/renderer/features/integrations/hooks/useGithubUserConnect.ts:89-93
**`toast.error` fires unconditionally regardless of connection state**
`onError` calls `toast.error(message)` even when `state === "idle"`. For `GitHubConnectionBanner` — which is mounted in the persistent inbox UI — this means that if a stale pending error callback is consumed on mount via `consumePendingCallback` (e.g. left over from a previous connect attempt in another session), the user will see an unexpected error toast with no obvious cause. The original banner didn't use `useGitHubIntegrationCallback` at all, so this is a new behaviour for that consumer.
Guard the toast (and optionally the full `onError` body) behind a state check:
```typescript
onError: (message) => {
stopPolling();
if (stateRef.current === "connecting") {
toast.error(message);
}
setState("idle");
},
```
### Issue 2 of 2
apps/code/src/renderer/features/integrations/hooks/useGithubUserConnect.ts:114-119
**Redundant `projectId !== null` guard**
`projectId !== null` is already guaranteed at this point — the `connect` callback returns early on line 103 if `projectId === null`. The extra check is superfluous and contradicts the simplicity rule of "no superfluous parts".
```typescript
if (IS_DEV) {
pollTimerRef.current = setInterval(
() => invalidate(projectId),
POLL_INTERVAL_MS,
);
}
```
Reviews (1): Last reviewed commit: "feat(code): unify user-scoped GitHub con..." | Re-trigger Greptile |
| onError: (message) => { | ||
| stopPolling(); | ||
| setState("idle"); | ||
| toast.error(message); | ||
| }, |
There was a problem hiding this comment.
toast.error fires unconditionally regardless of connection state
onError calls toast.error(message) even when state === "idle". For GitHubConnectionBanner — which is mounted in the persistent inbox UI — this means that if a stale pending error callback is consumed on mount via consumePendingCallback (e.g. left over from a previous connect attempt in another session), the user will see an unexpected error toast with no obvious cause. The original banner didn't use useGitHubIntegrationCallback at all, so this is a new behaviour for that consumer.
Guard the toast (and optionally the full onError body) behind a state check:
onError: (message) => {
stopPolling();
if (stateRef.current === "connecting") {
toast.error(message);
}
setState("idle");
},Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/integrations/hooks/useGithubUserConnect.ts
Line: 89-93
Comment:
**`toast.error` fires unconditionally regardless of connection state**
`onError` calls `toast.error(message)` even when `state === "idle"`. For `GitHubConnectionBanner` — which is mounted in the persistent inbox UI — this means that if a stale pending error callback is consumed on mount via `consumePendingCallback` (e.g. left over from a previous connect attempt in another session), the user will see an unexpected error toast with no obvious cause. The original banner didn't use `useGitHubIntegrationCallback` at all, so this is a new behaviour for that consumer.
Guard the toast (and optionally the full `onError` body) behind a state check:
```typescript
onError: (message) => {
stopPolling();
if (stateRef.current === "connecting") {
toast.error(message);
}
setState("idle");
},
```
How can I resolve this? If you propose a fix, please make it concise.| if (IS_DEV && projectId !== null) { | ||
| pollTimerRef.current = setInterval( | ||
| () => invalidate(projectId), | ||
| POLL_INTERVAL_MS, | ||
| ); | ||
| } |
There was a problem hiding this comment.
Redundant
projectId !== null guard
projectId !== null is already guaranteed at this point — the connect callback returns early on line 103 if projectId === null. The extra check is superfluous and contradicts the simplicity rule of "no superfluous parts".
if (IS_DEV) {
pollTimerRef.current = setInterval(
() => invalidate(projectId),
POLL_INTERVAL_MS,
);
}Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/integrations/hooks/useGithubUserConnect.ts
Line: 114-119
Comment:
**Redundant `projectId !== null` guard**
`projectId !== null` is already guaranteed at this point — the `connect` callback returns early on line 103 if `projectId === null`. The extra check is superfluous and contradicts the simplicity rule of "no superfluous parts".
```typescript
if (IS_DEV) {
pollTimerRef.current = setInterval(
() => invalidate(projectId),
POLL_INTERVAL_MS,
);
}
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
4c4c4e4 to
025691b
Compare
025691b to
46ab5f9
Compare

Problem
The GitHub user connect logic was duplicated across
GitHubConnectionBannerandGitIntegrationStep, making it harder to maintain and reason about. Each component independently managed connection state, polling timers, timeout handling, query invalidation, and the window-focus refetch fallback.Changes
Extracts all GitHub user connect logic into a new
useGithubUserConnecthook that encapsulates:idle,connecting,timed-out)useGitHubIntegrationCallbackintegration for deep-link success/error handlingGitHubConnectionBannerandGitIntegrationStepare updated to use the new hook, removing their inline implementations. TheisConnectingGithubfield andsetConnectingGithubaction are removed from the onboarding store since connection state is now owned by the hook.