Skip to content

fix(crazygames): guest username on logout, hide fullscreen, in-game pop-ups#4520

Closed
evanpelle wants to merge 2 commits into
mainfrom
crazygames-fixes-username-fullscreen-popups
Closed

fix(crazygames): guest username on logout, hide fullscreen, in-game pop-ups#4520
evanpelle wants to merge 2 commits into
mainfrom
crazygames-fixes-username-fullscreen-popups

Conversation

@evanpelle

Copy link
Copy Markdown
Collaborator

Addresses four requests from the CrazyGames platform team.

1. Username reverts to guest on CrazyGames logout

When a player logged into their CrazyGames account and then logged out, the username stayed the CrazyGames name. It now reverts to a fresh guest (AnonXXX) name. A crazyGamesLoggedIn flag guards this so it only fires on a real login→logout transition (not on the initial "not logged in" state, which would otherwise wipe a stored name).

2. Fullscreen button hidden on CrazyGames

CrazyGames provides its own fullscreen control in the game frame, so our in-game fullscreen button is now hidden when running on CrazyGames (and unchanged everywhere else).

3. Native browser prompts → in-game pop-ups

New InGameModal provides promise-based showInGameConfirm() / showInGameAlert() rendered as a real in-game modal (styled to match the Settings modal). Every native confirm()/alert() shown during gameplay now uses it:

  • Exit-game confirmation (right sidebar + browser-back path)
  • Kick-player confirmation
  • Host-left notice (dispatches leave-lobby only after dismiss, preserving the old blocking UX)
  • Connection-refused notice (also removes a stale // TODO: make this a modal)

4. gameplayStop when Settings menu / pop-up is open

  • The pop-up itself reports gameplayStop() while shown and gameplayStart() on dismiss.
  • Settings + Graphics Settings modals now report gameplayStop whenever the menu is open — previously it only fired when the modal also paused the sim (singleplayer / lobby-creator), so regular multiplayer players never triggered it. Also fixes graphics-settings so gameplay resumes correctly on close for those players.

Scope

Per request, this covers in-game dialogs only. The main-menu native alerts (store/checkout, account, subscriptions, friends, login) were intentionally left as-is.

Testing

  • tsc --noEmit, eslint, and prettier --check all pass.
  • Verified the confirm and alert pop-ups render correctly in the running app, and Cancel resolves the promise to false and dismisses the overlay.
  • CrazyGames-iframe-only behaviors (username revert, gameplayStop, fullscreen hiding) are verified by code inspection — they require running inside the actual CrazyGames frame.

🤖 Generated with Claude Code

…op-ups

Addresses four CrazyGames platform requests:

- Username reverts to a fresh guest (AnonXXX) name when the player logs
  out of their CrazyGames account, instead of keeping the account name.
- Hide our in-game fullscreen button on CrazyGames (the frame provides one).
- Replace native browser confirm()/alert() dialogs shown during gameplay
  with an in-game pop-up (new InGameModal): exit-game confirmation, kick
  confirmation, host-left, and connection-refused.
- Report gameplayStop to CrazyGames whenever the Settings menu or a pop-up
  is open (previously only when it also paused the sim), resuming on close.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Replaces native alert and confirm dialogs with shared in-game dialog helpers, updates several caller flows to use them, and adjusts CrazyGames gameplay pause, fullscreen, and username logout handling.

Changes

In-game dialogs and CrazyGames flow

Layer / File(s) Summary
In-game dialog helper
src/client/InGameModal.ts
Replaces the modal element with a helper that mounts confirm-dialog, pauses and resumes gameplay around the dialog, and exports confirm and alert variants.
Dialog callers and leave flow
src/client/ClientGameRunner.ts, src/client/Main.ts, src/client/Transport.ts, src/client/hud/layers/GameRightSidebar.ts, src/client/hud/layers/PlayerModerationModal.ts
Switches host-left, connection-refused, leave-game, exit, and kick flows from native dialogs to the shared in-game helpers, including the async leave-game path in Main.
Pause, sidebar, and username state
src/client/hud/layers/GraphicsSettingsModal.ts, src/client/hud/layers/SettingsModal.ts, src/client/hud/layers/GameRightSidebar.ts, src/client/UsernameInput.ts
Updates CrazyGames pause reporting in both settings modals, hides fullscreen controls on CrazyGames, and adds logout handling that restores an anonymous username after CrazyGames sign-out.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • openfrontio/OpenFrontIO#1472: Both PRs modify src/client/Transport.ts WebSocket close handling for code 1002, replacing a plain alert with showInGameAlert(...).
  • openfrontio/OpenFrontIO#4449: Both PRs change leave/close confirmation from native confirm(...) to an async in-game confirmation flow.

Suggested labels: UI/UX

Poem

A modal blooms בתוך the play,
old browser boxes drift away.
Confirm, alert, and leave in tune,
while gameplay pauses for a moon. 🌙

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main changes: CrazyGames logout username reset, fullscreen hiding, and in-game pop-ups.
Description check ✅ Passed The description clearly describes the CrazyGames UI, username, and gameplay-reporting changes in this patch.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.

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.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
src/client/hud/layers/SettingsModal.ts (1)

110-124: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Same duplicated logic as GraphicsSettingsModal.pauseGame.

See the extraction suggestion left on src/client/hud/layers/GraphicsSettingsModal.ts (lines 169-183) — this block is identical and would benefit from sharing a single helper.

🤖 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/hud/layers/SettingsModal.ts` around lines 110 - 124, The pauseGame
logic in SettingsModal duplicates the same behavior already implemented in
GraphicsSettingsModal.pauseGame, so extract the shared CrazyGames/eventBus pause
handling into a common helper and have both modals call it. Keep the helper
focused on the pause/resume flow driven by pause, wasPausedWhenOpened,
shouldPause, crazyGamesSDK, and eventBus so the two classes share one source of
truth.
src/client/hud/layers/GraphicsSettingsModal.ts (1)

169-183: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Correct fix, but duplicated verbatim in SettingsModal.ts.

The CrazyGames reporting logic (decoupling gameplayStop/gameplayStart from shouldPause) is correct and matches the PR intent. However this exact 15-line block is copy-pasted into SettingsModal.pauseGame (lines 110-124). Any future tweak to this logic risks drifting between the two files. Consider extracting it into a small shared helper (e.g. in CrazyGamesSDK.ts or a shared util) that both modals call.

♻️ Example extraction
// CrazyGamesSDK.ts (or a small shared helper module)
export function reportCrazyGamesPause(pause: boolean, wasPausedWhenOpened: boolean) {
  if (pause) {
    crazyGamesSDK.gameplayStop();
  } else if (!wasPausedWhenOpened) {
    crazyGamesSDK.gameplayStart();
  }
}
   private pauseGame(pause: boolean) {
-    // CrazyGames: report gameplay as stopped whenever this settings menu is open,
-    // and resumed when it closes — unless the game was already paused when opened.
-    if (pause) {
-      crazyGamesSDK.gameplayStop();
-    } else if (!this.wasPausedWhenOpened) {
-      crazyGamesSDK.gameplayStart();
-    }
+    reportCrazyGamesPause(pause, this.wasPausedWhenOpened);

     // Only pause the simulation itself when we own the pause (singleplayer or
     // lobby creator).
     if (this.shouldPause && !this.wasPausedWhenOpened) {
       this.eventBus.emit(new PauseGameIntentEvent(pause));
     }
   }
🤖 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/hud/layers/GraphicsSettingsModal.ts` around lines 169 - 183, The
CrazyGames pause/reporting logic in GraphicsSettingsModal.pauseGame is correct,
but it is duplicated verbatim in SettingsModal.pauseGame, so future changes may
drift between the two. Extract the shared gameplayStop/gameplayStart behavior
into a small helper (for example in CrazyGamesSDK or a shared util) and have
both pauseGame methods call it, keeping only the modal-specific
PauseGameIntentEvent logic in each class.
🤖 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/InGameModal.ts`:
- Around line 92-107: Add the missing translation entries used by InGameModal so
translateText("common.cancel"), translateText("common.confirm"), and
translateText("common.close") resolve correctly. Update the English resource
data in resources/lang/en.json to include these new common keys with appropriate
button labels, keeping them alongside the existing common translations so the
InGameModal button text remains localized.

In `@src/client/Transport.ts`:
- Line 391: The showInGameAlert call in Transport.ts is using a hardcoded
English message, so replace the inline string with a translateText() lookup and
add the matching connection_error.refused entry in resources/lang/en.json. Keep
the dynamic event.reason part in the translated message and update the Transport
connection error handling path to use the localized text consistently with the
other converted call sites.

---

Nitpick comments:
In `@src/client/hud/layers/GraphicsSettingsModal.ts`:
- Around line 169-183: The CrazyGames pause/reporting logic in
GraphicsSettingsModal.pauseGame is correct, but it is duplicated verbatim in
SettingsModal.pauseGame, so future changes may drift between the two. Extract
the shared gameplayStop/gameplayStart behavior into a small helper (for example
in CrazyGamesSDK or a shared util) and have both pauseGame methods call it,
keeping only the modal-specific PauseGameIntentEvent logic in each class.

In `@src/client/hud/layers/SettingsModal.ts`:
- Around line 110-124: The pauseGame logic in SettingsModal duplicates the same
behavior already implemented in GraphicsSettingsModal.pauseGame, so extract the
shared CrazyGames/eventBus pause handling into a common helper and have both
modals call it. Keep the helper focused on the pause/resume flow driven by
pause, wasPausedWhenOpened, shouldPause, crazyGamesSDK, and eventBus so the two
classes share one source of truth.
🪄 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: 27670e41-ce46-4f48-8362-8ad5a5260913

📥 Commits

Reviewing files that changed from the base of the PR and between 0859efc and 47825b2.

📒 Files selected for processing (9)
  • src/client/ClientGameRunner.ts
  • src/client/InGameModal.ts
  • src/client/Main.ts
  • src/client/Transport.ts
  • src/client/UsernameInput.ts
  • src/client/hud/layers/GameRightSidebar.ts
  • src/client/hud/layers/GraphicsSettingsModal.ts
  • src/client/hud/layers/PlayerModerationModal.ts
  • src/client/hud/layers/SettingsModal.ts

Comment thread src/client/InGameModal.ts Outdated
Comment on lines +92 to +107
${this.showCancel
? html`<button
class="px-4 py-2 rounded-md text-sm font-medium text-white bg-slate-600 hover:bg-slate-500 transition-colors"
@click=${() => this.close(false)}
>
${translateText("common.cancel")}
</button>`
: null}
<button
class="px-4 py-2 rounded-md text-sm font-medium text-white bg-blue-600 hover:bg-blue-500 transition-colors"
@click=${() => this.close(true)}
>
${this.showCancel
? translateText("common.confirm")
: translateText("common.close")}
</button>

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -t f 'en.json' resources/lang | xargs -I{} sh -c 'echo "--- {} ---"; jq -e ".\"common.cancel\", .\"common.confirm\", .\"common.close\"" {}'

Repository: openfrontio/OpenFrontIO

Length of output: 211


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== translateText key usage in src/client/InGameModal.ts =="
sed -n '80,115p' src/client/InGameModal.ts

echo
echo "== matching keys in resources/lang/en.json =="
rg -n '"common\.(cancel|confirm|close)"' resources/lang/en.json || true

echo
echo "== surrounding common keys in resources/lang/en.json =="
rg -n '"common\.' resources/lang/en.json | head -n 40

Repository: openfrontio/OpenFrontIO

Length of output: 1596


Add the new translation keys to resources/lang/en.json The buttons now call translateText("common.cancel"), translateText("common.confirm"), and translateText("common.close"), but those entries are missing from the English resource file.

🤖 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/InGameModal.ts` around lines 92 - 107, Add the missing translation
entries used by InGameModal so translateText("common.cancel"),
translateText("common.confirm"), and translateText("common.close") resolve
correctly. Update the English resource data in resources/lang/en.json to include
these new common keys with appropriate button labels, keeping them alongside the
existing common translations so the InGameModal button text remains localized.

Source: Coding guidelines

Comment thread src/client/Transport.ts
if (event.code === 1002) {
// TODO: make this a modal
alert(`connection refused: ${event.reason}`);
showInGameAlert(`connection refused: ${event.reason}`);

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Untranslated user-facing string.

`connection refused: ${event.reason}` is hardcoded English and bypasses translateText(). As per coding guidelines, src/client/**/*.{ts,tsx}: "All user-visible text must go through translateText() function with corresponding entries in resources/lang/en.json." Every other call site converted in this PR (ClientGameRunner, Main, GameRightSidebar, PlayerModerationModal) correctly wraps its message in translateText().

🌐 Proposed fix
-        showInGameAlert(`connection refused: ${event.reason}`);
+        showInGameAlert(
+          translateText("connection_error.refused", { reason: event.reason }),
+        );

(Add a matching connection_error.refused entry to resources/lang/en.json.)

📝 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
showInGameAlert(`connection refused: ${event.reason}`);
showInGameAlert(
translateText("connection_error.refused", { reason: event.reason }),
);
🤖 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/Transport.ts` at line 391, The showInGameAlert call in
Transport.ts is using a hardcoded English message, so replace the inline string
with a translateText() lookup and add the matching connection_error.refused
entry in resources/lang/en.json. Keep the dynamic event.reason part in the
translated message and update the Transport connection error handling path to
use the localized text consistently with the other converted call sites.

Source: Coding guidelines

@github-project-automation github-project-automation Bot moved this from Triage to Development in OpenFront Release Management Jul 7, 2026
Instead of a hand-rolled modal, the showInGameConfirm/showInGameAlert
helpers now drive the existing <confirm-dialog> component so the styling
stays consistent with the rest of the app. Keeps the promise-based API
(callable from non-Lit contexts) and the gameplayStop/Start reporting.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 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/InGameModal.ts`:
- Around line 16-32: The showDialog flow currently resumes gameplay as soon as
any single modal closes, which can incorrectly unpause while another dialog is
still open. Update the InGameModal showDialog logic to track the number of open
dialogs with a shared ref-count, incrementing when a dialog is appended and
decrementing in the confirm/cancel completion path before calling
gameplayStart(). Use the existing showDialog, done, and
crazyGamesSDK.gameplayStop/gameplayStart symbols to keep gameplay paused until
the last visible modal is removed.
🪄 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: 829da905-e5a3-44e7-934e-66f1993f6094

📥 Commits

Reviewing files that changed from the base of the PR and between 47825b2 and 223b218.

📒 Files selected for processing (1)
  • src/client/InGameModal.ts

Comment thread src/client/InGameModal.ts
Comment on lines +16 to +32
function showDialog(props: Partial<ConfirmDialog>): Promise<boolean> {
const dialog = document.createElement("confirm-dialog") as ConfirmDialog;
Object.assign(dialog, props);

crazyGamesSDK.gameplayStop();
document.body.appendChild(dialog);

return new Promise<boolean>((resolve) => {
const done = (result: boolean) => {
dialog.remove();
crazyGamesSDK.gameplayStart();
resolve(result);
};
dialog.addEventListener("confirm", () => done(true));
dialog.addEventListener("cancel", () => done(false));
});
}

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -nP '\bshowInGame(Confirm|Alert)\s*\(' src/client -C2

Repository: openfrontio/OpenFrontIO

Length of output: 2901


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## InGameModal.ts\n'
sed -n '1,120p' src/client/InGameModal.ts | cat -n

printf '\n## Caller snippets\n'
sed -n '380,430p' src/client/Transport.ts | cat -n
printf '\n'
sed -n '590,630p' src/client/Main.ts | cat -n
printf '\n'
sed -n '210,235p' src/client/ClientGameRunner.ts | cat -n
printf '\n'
sed -n '60,85p' src/client/hud/layers/PlayerModerationModal.ts | cat -n
printf '\n'
sed -n '190,210p' src/client/hud/layers/GameRightSidebar.ts | cat -n

Repository: openfrontio/OpenFrontIO

Length of output: 8339


Ref-count in-game dialogs before resuming gameplay. These dialogs can come from separate flows, so closing one can call gameplayStart() while another is still visible. A small open-dialog counter here would keep gameplay paused until the last modal closes.

🤖 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/InGameModal.ts` around lines 16 - 32, The showDialog flow
currently resumes gameplay as soon as any single modal closes, which can
incorrectly unpause while another dialog is still open. Update the InGameModal
showDialog logic to track the number of open dialogs with a shared ref-count,
incrementing when a dialog is appended and decrementing in the confirm/cancel
completion path before calling gameplayStart(). Use the existing showDialog,
done, and crazyGamesSDK.gameplayStop/gameplayStart symbols to keep gameplay
paused until the last visible modal is removed.

@evanpelle evanpelle closed this Jul 8, 2026
@evanpelle evanpelle deleted the crazygames-fixes-username-fullscreen-popups branch July 8, 2026 17:26
@github-project-automation github-project-automation Bot moved this from Development to Complete in OpenFront Release Management Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Complete

Development

Successfully merging this pull request may close these issues.

1 participant