Skip to content

fix : correct concede message and resolve pre-existing ESLint errors in OnlineDebateRoom#346

Open
compiler041 wants to merge 1 commit intoAOSSIE-Org:mainfrom
compiler041:fix/concede-message-eslint-cleanup-v2
Open

fix : correct concede message and resolve pre-existing ESLint errors in OnlineDebateRoom#346
compiler041 wants to merge 1 commit intoAOSSIE-Org:mainfrom
compiler041:fix/concede-message-eslint-cleanup-v2

Conversation

@compiler041
Copy link
Copy Markdown
Contributor

@compiler041 compiler041 commented Mar 7, 2026

Summary

Fixes a bug where both users received "You win!" when one user conceded
the debate. Also resolves 13 pre-existing ESLint errors in the file.

Root Cause

The WebSocket concede event was broadcast to all participants without
checking who was the sender, causing the conceding user to also see "You win!".

Fix

Added data.userId !== currentUserIdRef.current check in case "concede"
WS handler so only the opponent sees "You win!". The conceding user already
sees "You have conceded" from handleConcede.

##Before:

image
Video.Project.7b.mp4

##After:
Screenshot 2026-03-07 140606

ESLint Cleanup (pre-existing errors)

  • Renamed match param to result in extractJSON to fix implicit any (ts7006)
  • Added : string type to m param in WS_BASE_URL replace callback
  • Removed unused error variable in startSpectatorOffer catch block
  • Removed unused err in case "answer" and case "candidate" catch blocks
  • Added comments to intentionally empty catch blocks
  • Copied spectatorPCsRef to local variable in cleanup to fix ref-in-cleanup warning
  • Removed 3 stale eslint-disable-next-line comments
    Addressed Issues:
    Fixes Concede message shown incorrectly + pre-existing ESLint errors in OnlineDebateRoom.tsx #344
    Checklist:
  • My PR addresses a single issue, fixes a single bug or makes a single improvement.
  • My code follows the project's code style and conventions
  • My changes generate no new warnings or errors
  • I have joined the Discord server and I will share a link to this PR there
  • I have read the Contribution Guidelines
  • Once I submit my PR, CodeRabbit AI will automatically review it and I will address CodeRabbit's comments.
    AI Usage:
  • This PR contains AI-generated code. I have read the AI Usage Policy and
    this PR complies with this policy. I have tested the code locally and I am
    responsible for it.

I have used the following AI models and tools: Claude (Anthropic) for
identifying ESLint issues and suggesting fixes. All changes have been
reviewed, tested locally, and I take full responsibility for them.

Summary by CodeRabbit

  • Bug Fixes

    • Corrected concede match behavior to display win notifications only to the opposing player.
  • Improvements

    • Enhanced WebSocket connection lifecycle management and spectator handling for improved stability.
    • Refined UI rendering and transcript updates for better performance.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 7, 2026

📝 Walkthrough

Walkthrough

This PR addresses a concede message display bug and various code quality improvements in OnlineDebateRoom.tsx. The primary fix ensures that only the opponent receives a "You win!" message when a user concedes, rather than both participants. Additional changes include ESLint cleanup, removal of unused variables, parameter renaming, and refactored WebSocket/spectator handling logic.

Changes

Cohort / File(s) Summary
OnlineDebateRoom Component
frontend/src/Pages/OnlineDebateRoom.tsx
Fixed concede behavior to display win message conditionally based on userId check; refactored extractJSON and WS_BASE_URL callback parameter names; removed unused error variables from catch blocks; enhanced WebSocket and spectator lifecycle cleanup; added missing ESLint dependency hints; adjusted speech/transcript handling and phase transition timing.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 A message misconstrued, now clearly defined,
Both users won't boast when they're left behind,
The loser concedes with grace and good cheer,
While cleanup and linting bring logic so clear!
Hop forward with confidence, the fix is just right! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the two main changes: fixing the concede message bug and resolving ESLint errors in OnlineDebateRoom, which directly match the PR's primary objectives.
Linked Issues check ✅ Passed The PR addresses all objectives from issue #344: fixes the concede message logic to show 'You win!' only to the opponent, and resolves 13 ESLint issues including unused variables, empty catch blocks, and type annotations.
Out of Scope Changes check ✅ Passed All changes are directly related to the objectives in issue #344. The modifications include only the concede message fix, ESLint error resolutions, and related refactors without introducing unrelated functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/Pages/OnlineDebateRoom.tsx (1)

1409-1417: ⚠️ Potential issue | 🟠 Major

Remove fetchRoomParticipants from this effect's dependency array to prevent unnecessary WebSocket reconnections.

fetchRoomParticipants depends on currentUser, which changes when the user profile loads. Since currentUser is not stable, including fetchRoomParticipants in the dependency array causes this effect to re-run and recreate the WebSocket connection whenever the user data updates.

However, fetchRoomParticipants is only called inside rws.onopen (line 1120) within a delayed callback, where it will capture the latest version through closure. It does not need to be listed as a dependency.

If ESLint complains about the missing dependency, add an eslint-disable-next-line comment rather than including it in the array, or move the fetchRoomParticipants() call to a separate effect triggered by socket readiness.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/Pages/OnlineDebateRoom.tsx` around lines 1409 - 1417, Remove
fetchRoomParticipants from the effect dependency array that currently includes
cleanupSpectatorConnection, cleanupSpectatorConnectionsByBase,
fetchRoomParticipants, flushSpectatorOfferQueue, processSpectatorOfferRequest,
queueSpectatorOffer, and roomId to avoid unnecessary WebSocket reconnections;
fetchRoomParticipants is invoked inside rws.onopen (delayed callback) and will
capture the latest value via closure so it doesn't need to be a dependency—if
ESLint warns about the missing dependency, suppress it with an
eslint-disable-next-line comment on that effect rather than re-adding
fetchRoomParticipants, or alternatively move the fetchRoomParticipants() call
into a separate effect that runs when the socket is ready.
🧹 Nitpick comments (2)
frontend/src/Pages/OnlineDebateRoom.tsx (2)

133-140: Misleading comment: match was a local variable, not a parameter.

The comment on line 133 says "renamed 'match' param to '_match'" but:

  1. match was never a function parameter—it was the return value of fenceRegex.exec()
  2. The actual rename is from match to result (line 136), not _match

Consider updating the comment to accurately reflect the change:

📝 Suggested comment fix
-// FIX: renamed 'match' param to '_match' to avoid implicit any (ts7006)
+// FIX: renamed 'match' variable to 'result' to improve clarity
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/Pages/OnlineDebateRoom.tsx` around lines 133 - 140, Update the
misleading inline comment above extractJSON: it currently claims a rename of a
parameter 'match' to '_match', but there was no parameter—`match` was the local
result of fenceRegex.exec(); the code actually renamed that local to `result`.
Replace the comment with a short, accurate note referencing extractJSON and
fenceRegex (e.g., "renamed local match variable returned by fenceRegex.exec() to
`result` to avoid implicit any") or remove the comment entirely.

1536-1538: Comment is misleading—deps were not added, the rule was suppressed.

Line 1536-1537 states "added missing deps isMyTurn, localRole, currentUser?.id" but the actual fix is suppressing the exhaustive-deps warning (line 1537). The dependency array remains empty [] on line 1538.

Consider clarifying the comment:

📝 Suggested comment fix
-  // FIX: added missing deps isMyTurn, localRole, currentUser?.id to satisfy exhaustive-deps
+  // FIX: Intentionally empty deps - audio should initialize once on mount.
+  // Callbacks capture current values when invoked.
   // eslint-disable-next-line react-hooks/exhaustive-deps
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/Pages/OnlineDebateRoom.tsx` around lines 1536 - 1538, The
comment claims missing deps were added but the eslint rule was actually
disabled; update the code near the useEffect that references isMyTurn,
localRole, and currentUser?.id: either add these variables to the effect's
dependency array (so React's behavior is correct) or, if omission is
intentional, replace the misleading comment with a clear one that states the
effect intentionally omits isMyTurn, localRole, and currentUser?.id and why, and
keep the eslint-disable-next-line react-hooks/exhaustive-deps only when
justified; reference the useEffect containing isMyTurn, localRole,
currentUser?.id and the existing eslint-disable-next-line line when making the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/src/Pages/OnlineDebateRoom.tsx`:
- Around line 1247-1257: The concede handler currently compares data.userId
against currentUserIdRef.current which may be null during a race; add a
defensive null check (e.g., ensure Boolean(currentUserIdRef.current) or
currentUserIdRef.current != null) before performing the comparison so the branch
only runs when the current user ID is available; update the case "concede" logic
(where setDebatePhase(DebatePhase.Finished) and setPopup(...) are called) to
first guard on a non-null currentUserIdRef.current and then compare data.userId
!== currentUserIdRef.current.

---

Outside diff comments:
In `@frontend/src/Pages/OnlineDebateRoom.tsx`:
- Around line 1409-1417: Remove fetchRoomParticipants from the effect dependency
array that currently includes cleanupSpectatorConnection,
cleanupSpectatorConnectionsByBase, fetchRoomParticipants,
flushSpectatorOfferQueue, processSpectatorOfferRequest, queueSpectatorOffer, and
roomId to avoid unnecessary WebSocket reconnections; fetchRoomParticipants is
invoked inside rws.onopen (delayed callback) and will capture the latest value
via closure so it doesn't need to be a dependency—if ESLint warns about the
missing dependency, suppress it with an eslint-disable-next-line comment on that
effect rather than re-adding fetchRoomParticipants, or alternatively move the
fetchRoomParticipants() call into a separate effect that runs when the socket is
ready.

---

Nitpick comments:
In `@frontend/src/Pages/OnlineDebateRoom.tsx`:
- Around line 133-140: Update the misleading inline comment above extractJSON:
it currently claims a rename of a parameter 'match' to '_match', but there was
no parameter—`match` was the local result of fenceRegex.exec(); the code
actually renamed that local to `result`. Replace the comment with a short,
accurate note referencing extractJSON and fenceRegex (e.g., "renamed local match
variable returned by fenceRegex.exec() to `result` to avoid implicit any") or
remove the comment entirely.
- Around line 1536-1538: The comment claims missing deps were added but the
eslint rule was actually disabled; update the code near the useEffect that
references isMyTurn, localRole, and currentUser?.id: either add these variables
to the effect's dependency array (so React's behavior is correct) or, if
omission is intentional, replace the misleading comment with a clear one that
states the effect intentionally omits isMyTurn, localRole, and currentUser?.id
and why, and keep the eslint-disable-next-line react-hooks/exhaustive-deps only
when justified; reference the useEffect containing isMyTurn, localRole,
currentUser?.id and the existing eslint-disable-next-line line when making the
change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fbf27354-6e7a-4ae5-a425-8dacd6405ea9

📥 Commits

Reviewing files that changed from the base of the PR and between 90fb523 and e19718f.

📒 Files selected for processing (1)
  • frontend/src/Pages/OnlineDebateRoom.tsx

Comment on lines 1247 to 1257
case "concede":
setDebatePhase(DebatePhase.Finished);
setPopup({
show: true,
message: `${data.username || "Opponent"} has conceded the debate. You win!`,
isJudging: false,
});
// FIX: Only show "You win!" to the opponent, not the user who conceded
if (data.userId !== currentUserIdRef.current) {
setDebatePhase(DebatePhase.Finished);
setPopup({
show: true,
message: `${data.username || "Opponent"} has conceded the debate. You win!`,
isJudging: false,
});
}
break;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify if there are any other places where currentUserIdRef is used without null checks
rg -n 'currentUserIdRef\.current' --type=ts -C2

Repository: AOSSIE-Org/DebateAI

Length of output: 5228


🏁 Script executed:

#!/bin/bash
# Check the WebSocket setup and message handler initialization context
# Look for where concede messages are handled and what guards exist
sed -n '1200,1300p' frontend/src/Pages/OnlineDebateRoom.tsx | cat -n

Repository: AOSSIE-Org/DebateAI

Length of output: 4692


🏁 Script executed:

#!/bin/bash
# Check WebSocket initialization and connection setup
# Look for where message handlers are registered and currentUserIdRef setup timing
sed -n '250,400p' frontend/src/Pages/OnlineDebateRoom.tsx | cat -n

Repository: AOSSIE-Org/DebateAI

Length of output: 5541


🏁 Script executed:

#!/bin/bash
# Check the flow around WebSocket connection to see if there's any guard
# that prevents messages from being processed before currentUserIdRef is set
sed -n '700,900p' frontend/src/Pages/OnlineDebateRoom.tsx | cat -n

Repository: AOSSIE-Org/DebateAI

Length of output: 7623


🏁 Script executed:

#!/bin/bash
# Find where the message handler (onmessage) is set up for the WebSocket
rg -n 'onmessage|addEventListener.*message' frontend/src/Pages/OnlineDebateRoom.tsx -A5 -B2

Repository: AOSSIE-Org/DebateAI

Length of output: 337


🏁 Script executed:

#!/bin/bash
# Check how the WebSocket connection is initialized and what guards exist
rg -n 'new WebSocket|wsRef.current.*=' frontend/src/Pages/OnlineDebateRoom.tsx -A3 -B3

Repository: AOSSIE-Org/DebateAI

Length of output: 2339


Add a null check to guard against race condition in concede handler.

The fix correctly filters so only the opponent sees "You win!", but currentUserIdRef.current may be null if a concede message arrives before the user's profile loads. In that case, data.userId !== null would be true, incorrectly showing "You win!" to the wrong participant. Add a defensive null check:

Suggested fix
 case "concede":
   // FIX: Only show "You win!" to the opponent, not the user who conceded
-  if (data.userId !== currentUserIdRef.current) {
+  if (currentUserIdRef.current && data.userId !== currentUserIdRef.current) {
     setDebatePhase(DebatePhase.Finished);
     setPopup({
       show: true,
       message: `${data.username || "Opponent"} has conceded the debate. You win!`,
       isJudging: false,
     });
   }
   break;

This pattern is already used elsewhere in the file (line 141: Boolean(currentUserIdRef.current)) and in sibling functions for defensive checks after extracting ref values.

📝 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.

Suggested change
case "concede":
setDebatePhase(DebatePhase.Finished);
setPopup({
show: true,
message: `${data.username || "Opponent"} has conceded the debate. You win!`,
isJudging: false,
});
// FIX: Only show "You win!" to the opponent, not the user who conceded
if (data.userId !== currentUserIdRef.current) {
setDebatePhase(DebatePhase.Finished);
setPopup({
show: true,
message: `${data.username || "Opponent"} has conceded the debate. You win!`,
isJudging: false,
});
}
break;
case "concede":
// FIX: Only show "You win!" to the opponent, not the user who conceded
if (currentUserIdRef.current && data.userId !== currentUserIdRef.current) {
setDebatePhase(DebatePhase.Finished);
setPopup({
show: true,
message: `${data.username || "Opponent"} has conceded the debate. You win!`,
isJudging: false,
});
}
break;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/Pages/OnlineDebateRoom.tsx` around lines 1247 - 1257, The
concede handler currently compares data.userId against currentUserIdRef.current
which may be null during a race; add a defensive null check (e.g., ensure
Boolean(currentUserIdRef.current) or currentUserIdRef.current != null) before
performing the comparison so the branch only runs when the current user ID is
available; update the case "concede" logic (where
setDebatePhase(DebatePhase.Finished) and setPopup(...) are called) to first
guard on a non-null currentUserIdRef.current and then compare data.userId !==
currentUserIdRef.current.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Concede message shown incorrectly + pre-existing ESLint errors in OnlineDebateRoom.tsx

1 participant