auto-claude: 203-fix-pr-review-ui-update-issue (#1732)

* auto-claude: subtask-1-1 - Add explicit state refresh/event emission after PR review operations

- Added IPC event emission (sendComplete) after postPRReview operation to immediately update renderer state
- Added IPC event emission after markReviewPosted operation
- Added IPC event emission after deletePRReview operation
- Ensures UI updates immediately after PR review state changes without requiring navigation

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: extract sendReviewStateUpdate helper and fix error masking (qa-requested)

Address PR review findings:
- Extract duplicated 17-line IPC notification block into sendReviewStateUpdate helper (DRY)
- Wrap UI update in separate try-catch to prevent masking successful primary operations
- Add debug logging when getReviewResult returns null after file write

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Test User <test@example.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Andy
2026-02-09 10:27:28 +01:00
committed by GitHub
parent 57e38a692c
commit 7589f8e4f4
@@ -1355,7 +1355,44 @@ function getReviewResult(project: Project, prNumber: number): PRReviewResult | n
}
}
// IPC communication helpers removed - using createIPCCommunicators instead
/**
* Send a PR review state update event to the renderer to refresh the UI immediately.
* Used after operations that modify review state (post, mark posted, delete).
*/
function sendReviewStateUpdate(
project: Project,
prNumber: number,
projectId: string,
getMainWindow: () => BrowserWindow | null,
context: string
): void {
try {
const updatedResult = getReviewResult(project, prNumber);
if (!updatedResult) {
debugLog("Could not retrieve updated review result for UI notification", { prNumber, context });
return;
}
const mainWindow = getMainWindow();
if (!mainWindow) return;
const { sendComplete } = createIPCCommunicators<PRReviewProgress, PRReviewResult>(
mainWindow,
{
progress: IPC_CHANNELS.GITHUB_PR_REVIEW_PROGRESS,
error: IPC_CHANNELS.GITHUB_PR_REVIEW_ERROR,
complete: IPC_CHANNELS.GITHUB_PR_REVIEW_COMPLETE,
},
projectId
);
sendComplete(updatedResult);
debugLog(`Sent PR review state update ${context}`, { prNumber });
} catch (uiError) {
debugLog("Failed to send UI update (non-critical)", {
prNumber,
context,
error: uiError instanceof Error ? uiError.message : uiError,
});
}
}
/**
* Get GitHub PR model and thinking settings from app settings
@@ -2102,6 +2139,9 @@ export function registerPRHandlers(getMainWindow: () => BrowserWindow | null): v
debugLog("Review result file not found or unreadable, skipping update", { prNumber });
}
// Send state update event to refresh UI immediately (non-blocking)
sendReviewStateUpdate(project, prNumber, projectId, getMainWindow, "after posting");
return true;
} catch (error) {
debugLog("Failed to post review", {
@@ -2138,6 +2178,9 @@ export function registerPRHandlers(getMainWindow: () => BrowserWindow | null): v
fs.writeFileSync(reviewPath, JSON.stringify(data, null, 2), "utf-8");
debugLog("Marked review as posted", { prNumber });
// Send state update event to refresh UI immediately (non-blocking)
sendReviewStateUpdate(project, prNumber, projectId, getMainWindow, "after marking posted");
return true;
} catch (error) {
// Handle file not found (ENOENT) separately for clearer logging
@@ -2253,6 +2296,9 @@ export function registerPRHandlers(getMainWindow: () => BrowserWindow | null): v
debugLog("Review result file not found or unreadable, skipping update", { prNumber });
}
// Send state update event to refresh UI immediately (non-blocking)
sendReviewStateUpdate(project, prNumber, projectId, getMainWindow, "after deletion");
return true;
} catch (error) {
debugLog("Failed to delete review", {