Skip to content

Move leaderboard#3909

Draft
evanpelle wants to merge 1 commit into
v31from
move-leaderboard
Draft

Move leaderboard#3909
evanpelle wants to merge 1 commit into
v31from
move-leaderboard

Conversation

@evanpelle
Copy link
Copy Markdown
Collaborator

If this PR fixes an issue, link it below. If not, delete these two lines.
Resolves #(issue number)

Description:

Describe the PR.

Please complete the following:

  • I have added screenshots for all UI updates
  • I process any text displayed to the user through translateText() and I've added it to the en.json file
  • I have added relevant tests to the test directory
  • I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced

Please put your Discord username so you can be contacted if a bug or regression is found:

DISCORD_USERNAME

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3e209184-c34b-4ce9-a51d-f5850db17975

📥 Commits

Reviewing files that changed from the base of the PR and between f311ee9 and ee0c995.

📒 Files selected for processing (9)
  • index.html
  • src/client/graphics/GameRenderer.ts
  • src/client/graphics/layers/GameLeftSidebar.ts
  • src/client/graphics/layers/GameMenu.ts
  • src/client/graphics/layers/GameRightSidebar.ts
  • src/client/graphics/layers/Leaderboard.ts
  • src/client/graphics/layers/PlayerInfoOverlay.ts
  • src/client/graphics/layers/ReplayPanel.ts
  • src/client/graphics/layers/TeamStats.ts
💤 Files with no reviewable changes (2)
  • src/client/graphics/layers/GameRightSidebar.ts
  • src/client/graphics/layers/GameLeftSidebar.ts
✅ Files skipped from review due to trivial changes (1)
  • src/client/graphics/layers/TeamStats.ts
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/client/graphics/layers/PlayerInfoOverlay.ts
  • src/client/graphics/layers/ReplayPanel.ts
  • src/client/graphics/GameRenderer.ts
  • index.html
  • src/client/graphics/layers/GameMenu.ts
  • src/client/graphics/layers/Leaderboard.ts

Walkthrough

Consolidates left/right in-game sidebars into a single game-menu component, updates DOM to use a top HUD grid, removes game-left-sidebar and game-right-sidebar, wires game-menu into the renderer, and standardizes several Lit reactive properties across overlays and panels.

Changes

UI Consolidation & Refactor

Layer / File(s) Summary
Top HUD DOM + mount point
index.html
Replaced previous top-right sidebar block with a fixed top HUD container using the bottom HUD's 3-column grid; mounts only game-menu in the right column; moved performance-overlay and player-info-overlay into overlays section.
New GameMenu layer
src/client/graphics/layers/GameMenu.ts
Adds game-menu LitElement with reactive state for mode/visibility/timer/winner/team, subscribes to spawn/immunity/winner events, computes countdown (respects maxTimerValue and spawn-phase turns), toggles leaderboards/replay/pause/settings/exit, updates parent offset, and forwards tick() to leader-board, team-stats, and replay-panel when present.
Renderer wiring
src/client/graphics/GameRenderer.ts
Imports and queries game-menu, validates it as GameMenu, assigns game and eventBus, and includes gameMenu in renderer layers; removed prior wiring for left/right sidebars and separate replay panel wiring.
Removed sidebar layers
src/client/graphics/layers/GameLeftSidebar.ts, src/client/graphics/layers/GameRightSidebar.ts
Deleted GameLeftSidebar and GameRightSidebar LitElement layers including their event subscriptions, tick/timer logic, UI rendering, and margin offset handling.
Leaderboard header & reactive props
src/client/graphics/layers/Leaderboard.ts
Converted game and eventBus to @property({ attribute: false }); willUpdate() now recalculates leaderboard when visible and game exists; header layout changed to use icon images and adjusted grid sizing.
ReplayPanel event wiring change
src/client/graphics/layers/ReplayPanel.ts
Made game and eventBus Lit properties; moved EventBus subscription from init() into willUpdate() guarded by a _eventBusSubscribed flag; init() is now empty.
TeamStats reactive props
src/client/graphics/layers/TeamStats.ts
Converted game and eventBus to Lit @property({ attribute: false }) with non-null assertions; no behavioral change.
PlayerInfoOverlay responsive tweak
src/client/graphics/layers/PlayerInfoOverlay.ts
Adjusted responsive positioning from sm:* to lg:*, added sm:right-auto, and changed inner panel rounding to rounded-b-lg.
sequenceDiagram
    participant Renderer as Renderer
    participant GameMenu as GameMenu
    participant Leaderboard as Leaderboard
    participant ReplayPanel as ReplayPanel
    participant TeamStats as TeamStats
    participant EventBus as EventBus

    Renderer->>GameMenu: Query element & assign<br/>`game`, `eventBus`
    GameMenu->>EventBus: Subscribe (SpawnBarVisible,<br/>ImmunityBarVisible, SendWinner)
    GameMenu->>Leaderboard: Reference & forward tick()
    GameMenu->>ReplayPanel: Reference & forward tick()
    GameMenu->>TeamStats: Reference & forward tick()

    rect rgba(100, 150, 200, 0.5)
    Note over GameMenu: Tick loop — compute timer,<br/>team color, visibility
    end

    rect rgba(100, 150, 200, 0.5)
    Note over GameMenu: User actions — pause/play,<br/>replay toggle, settings, exit
    GameMenu->>EventBus: Emit events (Pause, ShowReplayPanel, ShowSettingsModal)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

UI/UX

Suggested reviewers

  • scottanderson

Poem

Sidebars folded into a single view,
GameMenu calls the shots and cues.
Timers, replays, teams aligned —
Top HUD holds the new design. 🎮✨

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description contains only the repository template with placeholder checklist items and no substantive explanation of the code changes or objectives. Replace the template with a meaningful description explaining the UI restructuring: what components were moved, why the reorganization improves the layout, and any behavioral changes to document for reviewers.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Move leaderboard' is vague and does not clearly describe the primary changes in the pull request, which involve restructuring the UI layout by moving multiple components including the leaderboard into a new GameMenu sidebar. Provide a more specific title that captures the main architectural change, such as 'Refactor UI layout: consolidate sidebar controls into GameMenu' or 'Restructure in-game menu to new top HUD layout'.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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


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.

@openfrontio openfrontio Bot had a problem deploying to staging May 12, 2026 14:59 Failure
@openfrontio openfrontio Bot had a problem deploying to staging May 12, 2026 16:40 Failure
Copy link
Copy Markdown
Contributor

@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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/client/graphics/GameRenderer.ts`:
- Around line 88-92: The code logs when the queried gameMenu is missing/wrong
type but continues and dereferences it; update the guard in GameRenderer so
after checking "if (!gameMenu || !(gameMenu instanceof GameMenu))" you exit
early (return or throw) to avoid null dereference instead of just logging,
ensuring subsequent assignments to gameMenu.game and gameMenu.eventBus only run
when gameMenu is a valid GameMenu instance.

In `@src/client/graphics/layers/GameMenu.ts`:
- Around line 281-283: The menu contains hard-coded user-visible strings and
fallback alt text that must be localized: replace occurrences of "settings",
"exit", "replay", "play/pause" and any inline fallback alt strings (e.g.,
"Player Leaderboard Icon") in GameMenu.ts with calls to translateText(...) and
add matching keys to resources/lang/en.json; update the JSX/templating in the
GameMenu component (search for the strings around the render methods and the
elements referenced by the comment ranges ~281-333 and ~388-401) to call
translateText("menu.settings"), translateText("menu.exit"),
translateText("menu.replay"), translateText("menu.play_pause") (or similar
descriptive keys) and ensure each key exists in resources/lang/en.json with an
English value.
- Line 18: Replace direct Vite asset imports in GameMenu.ts (e.g., exitIcon
import) with the assetUrl() helper calls used elsewhere (call
assetUrl("images/ExitIconWhite.svg") and similarly for other icons referenced in
the file) so assets resolve via the manifest/CDN; also replace hardcoded alt
strings at the render sites (currently "settings", "exit", "replay",
"play/pause") with translateText(...) calls that mirror the existing pattern
used at lines ~281–283 and ~311–313 (provide a fallback string as the second
argument to translateText where appropriate). Ensure you update the import usage
locations to use the returned URL from assetUrl and keep existing variable names
in GameMenu.ts.

In `@src/client/graphics/layers/Leaderboard.ts`:
- Around line 49-52: willUpdate() currently calls updateLeaderboard()
unconditionally when visible is true, causing updateLeaderboard() to change the
players property and call requestUpdate(), which produces an infinite update
loop; fix it by only invoking updateLeaderboard() from willUpdate when the
relevant reactive properties actually changed — check the _changed map for
'visible' or 'game' (the same property keys used by the component) and call
updateLeaderboard() only if one of those keys is present; leave tick() and
setSort() as-is since they already trigger updates appropriately.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ff2dab67-11a3-4656-b38e-f087cc186cf9

📥 Commits

Reviewing files that changed from the base of the PR and between aeb8d60 and a93fc22.

📒 Files selected for processing (9)
  • index.html
  • src/client/graphics/GameRenderer.ts
  • src/client/graphics/layers/GameLeftSidebar.ts
  • src/client/graphics/layers/GameMenu.ts
  • src/client/graphics/layers/GameRightSidebar.ts
  • src/client/graphics/layers/Leaderboard.ts
  • src/client/graphics/layers/PlayerInfoOverlay.ts
  • src/client/graphics/layers/ReplayPanel.ts
  • src/client/graphics/layers/TeamStats.ts
💤 Files with no reviewable changes (2)
  • src/client/graphics/layers/GameRightSidebar.ts
  • src/client/graphics/layers/GameLeftSidebar.ts

Comment on lines +88 to +92
if (!gameMenu || !(gameMenu instanceof GameMenu)) {
console.error("GameMenu element not found in the DOM");
}
leaderboard.eventBus = eventBus;
leaderboard.game = game;

const gameLeftSidebar = document.querySelector(
"game-left-sidebar",
) as GameLeftSidebar;
if (!gameLeftSidebar || !(gameLeftSidebar instanceof GameLeftSidebar)) {
console.error("GameLeftSidebar element not found in the DOM");
}
gameLeftSidebar.game = game;
gameLeftSidebar.eventBus = eventBus;

const teamStats = document.querySelector("team-stats") as TeamStats;
if (!teamStats || !(teamStats instanceof TeamStats)) {
console.error("TeamStats element not found in the DOM");
}
teamStats.eventBus = eventBus;
teamStats.game = game;
gameMenu.game = game;
gameMenu.eventBus = eventBus;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Stop after failed game-menu lookup to avoid null dereference.

The current guard only logs, but code still assigns gameMenu.game/gameMenu.eventBus. If the element is missing or wrong type, this will throw.

Proposed fix
   const gameMenu = document.querySelector("game-menu") as GameMenu;
   if (!gameMenu || !(gameMenu instanceof GameMenu)) {
-    console.error("GameMenu element not found in the DOM");
+    throw new Error("GameMenu element not found in the DOM");
   }
   gameMenu.game = game;
   gameMenu.eventBus = eventBus;
📝 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
if (!gameMenu || !(gameMenu instanceof GameMenu)) {
console.error("GameMenu element not found in the DOM");
}
leaderboard.eventBus = eventBus;
leaderboard.game = game;
const gameLeftSidebar = document.querySelector(
"game-left-sidebar",
) as GameLeftSidebar;
if (!gameLeftSidebar || !(gameLeftSidebar instanceof GameLeftSidebar)) {
console.error("GameLeftSidebar element not found in the DOM");
}
gameLeftSidebar.game = game;
gameLeftSidebar.eventBus = eventBus;
const teamStats = document.querySelector("team-stats") as TeamStats;
if (!teamStats || !(teamStats instanceof TeamStats)) {
console.error("TeamStats element not found in the DOM");
}
teamStats.eventBus = eventBus;
teamStats.game = game;
gameMenu.game = game;
gameMenu.eventBus = eventBus;
const gameMenu = document.querySelector("game-menu") as GameMenu;
if (!gameMenu || !(gameMenu instanceof GameMenu)) {
throw new Error("GameMenu element not found in the DOM");
}
gameMenu.game = game;
gameMenu.eventBus = eventBus;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/graphics/GameRenderer.ts` around lines 88 - 92, The code logs when
the queried gameMenu is missing/wrong type but continues and dereferences it;
update the guard in GameRenderer so after checking "if (!gameMenu || !(gameMenu
instanceof GameMenu))" you exit early (return or throw) to avoid null
dereference instead of just logging, ensuring subsequent assignments to
gameMenu.game and gameMenu.eventBus only run when gameMenu is a valid GameMenu
instance.

Comment thread src/client/graphics/layers/GameMenu.ts Outdated
import { ShowSettingsModalEvent } from "./SettingsModal";
import { SpawnBarVisibleEvent } from "./SpawnTimer";
import { TeamStats } from "./TeamStats";
import exitIcon from "/images/ExitIconWhite.svg?url";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether the referenced file exists and find the correct icon path/name.
fd -i 'ExitIconWhite.svg'
fd -i 'ExitIcon*.svg'
rg -n 'ExitIconWhite.svg|ExitIcon' src/client

Repository: openfrontio/OpenFrontIO

Length of output: 410


🏁 Script executed:

# Find assetUrl function definition
rg -n "assetUrl" src/client --type ts --type tsx -A 2 -B 2

Repository: openfrontio/OpenFrontIO

Length of output: 95


🏁 Script executed:

# Check GameMenu.ts for all imports and hardcoded strings
fd -e ts -e tsx | xargs grep -l "GameMenu" | head -5
cat -n src/client/graphics/layers/GameMenu.ts

Repository: openfrontio/OpenFrontIO

Length of output: 15797


🏁 Script executed:

rg -n "assetUrl" src/client --type ts -A 5 -B 2 | head -50

Repository: openfrontio/OpenFrontIO

Length of output: 3216


🏁 Script executed:

cat -n src/core/AssetUrls.ts

Repository: openfrontio/OpenFrontIO

Length of output: 4231


Use assetUrl() helper for icon imports instead of direct Vite imports; fix hardcoded alt text.

Import pattern at line 18 (and lines 19–26) doesn't match the codebase convention. Use assetUrl("images/ExitIconWhite.svg") like SettingsModal.ts and PlayerModerationModal.ts do. Direct Vite imports bypass the asset manifest and CDN base URL system, preventing proper asset resolution during build and deployment.

Also, lines 328, 332, 388, and 400 have hardcoded alt text ("settings", "exit", "replay", "play/pause") that must go through translateText() per the i18n guideline. Lines 281–282 and 311–313 show the correct pattern with fallbacks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/graphics/layers/GameMenu.ts` at line 18, Replace direct Vite asset
imports in GameMenu.ts (e.g., exitIcon import) with the assetUrl() helper calls
used elsewhere (call assetUrl("images/ExitIconWhite.svg") and similarly for
other icons referenced in the file) so assets resolve via the manifest/CDN; also
replace hardcoded alt strings at the render sites (currently "settings", "exit",
"replay", "play/pause") with translateText(...) calls that mirror the existing
pattern used at lines ~281–283 and ~311–313 (provide a fallback string as the
second argument to translateText where appropriate). Ensure you update the
import usage locations to use the returned URL from assetUrl and keep existing
variable names in GameMenu.ts.

Comment on lines +281 to +283
alt=${translateText("help_modal.icon_alt_player_leaderboard") ||
"Player Leaderboard Icon"}
width="20"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Localize all new menu labels/alt text through translateText().

Several user-visible strings are hardcoded (e.g., "settings", "exit", "replay", "play/pause" and fallback English alt text). Please route all of them through translateText() and ensure matching resources/lang/en.json keys exist.

As per coding guidelines: "All user-visible text must go through translateText() function with corresponding entries in resources/lang/en.json".

Also applies to: 311-313, 328-333, 388-401

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/graphics/layers/GameMenu.ts` around lines 281 - 283, The menu
contains hard-coded user-visible strings and fallback alt text that must be
localized: replace occurrences of "settings", "exit", "replay", "play/pause" and
any inline fallback alt strings (e.g., "Player Leaderboard Icon") in GameMenu.ts
with calls to translateText(...) and add matching keys to
resources/lang/en.json; update the JSX/templating in the GameMenu component
(search for the strings around the render methods and the elements referenced by
the comment ranges ~281-333 and ~388-401) to call
translateText("menu.settings"), translateText("menu.exit"),
translateText("menu.replay"), translateText("menu.play_pause") (or similar
descriptive keys) and ensure each key exists in resources/lang/en.json with an
English value.

Comment on lines +49 to 52
willUpdate(_changed: Map<string, unknown>) {
if (this.visible && this.game !== null) {
this.updateLeaderboard();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

head -160 src/client/graphics/layers/Leaderboard.ts | tail -n +40

Repository: openfrontio/OpenFrontIO

Length of output: 3328


🏁 Script executed:

wc -l src/client/graphics/layers/Leaderboard.ts

Repository: openfrontio/OpenFrontIO

Length of output: 113


🏁 Script executed:

sed -n '145,160p' src/client/graphics/layers/Leaderboard.ts

Repository: openfrontio/OpenFrontIO

Length of output: 478


🏁 Script executed:

grep -n "requestUpdate\|willUpdate" src/client/graphics/layers/Leaderboard.ts

Repository: openfrontio/OpenFrontIO

Length of output: 147


Stop infinite update loop in willUpdate() when leaderboard is visible.

willUpdate() calls updateLeaderboard() every time Lit schedules an update while the leaderboard is visible. Inside updateLeaderboard(), you modify the players property and call requestUpdate(), which schedules a new update cycle. This creates a continuous feedback loop that will degrade performance.

Only run updateLeaderboard() when the visible or game properties actually change:

Proposed fix
-  willUpdate(_changed: Map<string, unknown>) {
-    if (this.visible && this.game !== null) {
+  willUpdate(changed: Map<string, unknown>) {
+    if (
+      this.visible &&
+      this.game !== null &&
+      (changed.has("visible") || changed.has("game"))
+    ) {
       this.updateLeaderboard();
     }
   }

The tick() method and setSort() already call updateLeaderboard() directly when appropriate, so they do not need changes.

📝 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
willUpdate(_changed: Map<string, unknown>) {
if (this.visible && this.game !== null) {
this.updateLeaderboard();
}
willUpdate(changed: Map<string, unknown>) {
if (
this.visible &&
this.game !== null &&
(changed.has("visible") || changed.has("game"))
) {
this.updateLeaderboard();
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/graphics/layers/Leaderboard.ts` around lines 49 - 52, willUpdate()
currently calls updateLeaderboard() unconditionally when visible is true,
causing updateLeaderboard() to change the players property and call
requestUpdate(), which produces an infinite update loop; fix it by only invoking
updateLeaderboard() from willUpdate when the relevant reactive properties
actually changed — check the _changed map for 'visible' or 'game' (the same
property keys used by the component) and call updateLeaderboard() only if one of
those keys is present; leave tick() and setSort() as-is since they already
trigger updates appropriately.

@github-project-automation github-project-automation Bot moved this from Triage to Development in OpenFront Release Management May 12, 2026
@openfrontio openfrontio Bot had a problem deploying to staging May 12, 2026 16:48 Failure
Copy link
Copy Markdown
Contributor

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

♻️ Duplicate comments (1)
src/client/graphics/layers/Leaderboard.ts (1)

49-52: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Stop infinite update loop in willUpdate() when leaderboard is visible.

This issue was previously flagged: willUpdate() calls updateLeaderboard() unconditionally when visible, but updateLeaderboard() calls requestUpdate() at line 157, creating a continuous feedback loop.

Check the _changed parameter to only run updateLeaderboard() when visible or game actually changed:

Proposed fix
-  willUpdate(_changed: Map<string, unknown>) {
-    if (this.visible && this.game !== null) {
+  willUpdate(changed: Map<string, unknown>) {
+    if (
+      this.visible &&
+      this.game !== null &&
+      (changed.has("visible") || changed.has("game"))
+    ) {
       this.updateLeaderboard();
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/client/graphics/layers/Leaderboard.ts` around lines 49 - 52, willUpdate
currently calls updateLeaderboard whenever the component is visible which causes
an infinite loop because updateLeaderboard calls requestUpdate; modify
willUpdate to inspect the _changed map and only call updateLeaderboard when the
"visible" or "game" keys actually changed (e.g., check _changed.has('visible')
|| _changed.has('game') ) so you avoid triggering updateLeaderboard on every
update and break the feedback loop between willUpdate and requestUpdate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/client/graphics/layers/Leaderboard.ts`:
- Around line 49-52: willUpdate currently calls updateLeaderboard whenever the
component is visible which causes an infinite loop because updateLeaderboard
calls requestUpdate; modify willUpdate to inspect the _changed map and only call
updateLeaderboard when the "visible" or "game" keys actually changed (e.g.,
check _changed.has('visible') || _changed.has('game') ) so you avoid triggering
updateLeaderboard on every update and break the feedback loop between willUpdate
and requestUpdate.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4bbe8952-66bb-471c-8aa2-b5015645c122

📥 Commits

Reviewing files that changed from the base of the PR and between a93fc22 and f311ee9.

📒 Files selected for processing (9)
  • index.html
  • src/client/graphics/GameRenderer.ts
  • src/client/graphics/layers/GameLeftSidebar.ts
  • src/client/graphics/layers/GameMenu.ts
  • src/client/graphics/layers/GameRightSidebar.ts
  • src/client/graphics/layers/Leaderboard.ts
  • src/client/graphics/layers/PlayerInfoOverlay.ts
  • src/client/graphics/layers/ReplayPanel.ts
  • src/client/graphics/layers/TeamStats.ts
💤 Files with no reviewable changes (2)
  • src/client/graphics/layers/GameRightSidebar.ts
  • src/client/graphics/layers/GameLeftSidebar.ts
✅ Files skipped from review due to trivial changes (1)
  • src/client/graphics/layers/PlayerInfoOverlay.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/client/graphics/layers/ReplayPanel.ts
  • src/client/graphics/GameRenderer.ts
  • src/client/graphics/layers/TeamStats.ts
  • index.html
  • src/client/graphics/layers/GameMenu.ts

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

Labels

None yet

Projects

Status: Development

Development

Successfully merging this pull request may close these issues.

1 participant