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

Addresses four requests from the CrazyGames platform team.
Supersedes #4520 (closed when its branch was renamed to `crazygames`).

## 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
The `showInGameConfirm()` / `showInGameAlert()` helpers (promise-based,
callable from non-Lit contexts like WebSocket/popstate handlers) drive
the existing shared `<confirm-dialog>` component, so styling stays
consistent with the rest of the app. 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 helpers report `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 (shared `<confirm-dialog>`, danger/warning variants), resolve their
promises, and tear down their portal.
- 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](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Evan
2026-07-08 12:02:37 -07:00
committed by GitHub
co-authored by Claude Opus 4.8
parent f78b5c42c9
commit d3ad1f51bd
11 changed files with 137 additions and 50 deletions
+5 -2
View File
@@ -6,6 +6,7 @@ import { GameType } from "../../../core/game/Game";
import "../../components/DoomsdayClockPanel";
import { Controller } from "../../Controller";
import { crazyGamesSDK } from "../../CrazyGamesSDK";
import { showInGameConfirm } from "../../InGameModal";
import { TogglePauseIntentEvent } from "../../InputHandler";
import { PauseGameIntentEvent, SendWinnerEvent } from "../../Transport";
import { translateText } from "../../Utils";
@@ -45,6 +46,8 @@ export class GameRightSidebar extends LitElement implements Controller {
@state()
private timer: number = 0;
// CrazyGames provides its own fullscreen control in the game frame, so hide ours.
private readonly onCrazyGames = crazyGamesSDK.isOnCrazyGames();
private hasWinner = false;
private isLobbyCreator = false;
private spawnBarVisible = false;
@@ -194,7 +197,7 @@ export class GameRightSidebar extends LitElement implements Controller {
private async onExitButtonClick() {
const isAlive = this.game.myPlayer()?.isAlive();
if (isAlive) {
const isConfirmed = confirm(
const isConfirmed = await showInGameConfirm(
translateText("help_modal.exit_confirmation"),
);
if (!isConfirmed) return;
@@ -250,7 +253,7 @@ export class GameRightSidebar extends LitElement implements Controller {
<img src=${settingsIcon} alt="settings" width="20" height="20" />
</div>
${document.fullscreenEnabled
${document.fullscreenEnabled && !this.onCrazyGames
? html`<div
class="cursor-pointer"
@click=${this.onFullscreenButtonClick}
+10 -5
View File
@@ -167,12 +167,17 @@ export class GraphicsSettingsModal extends LitElement implements Controller {
}
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();
}
// Only pause the simulation itself when we own the pause (singleplayer or
// lobby creator).
if (this.shouldPause && !this.wasPausedWhenOpened) {
if (pause) {
crazyGamesSDK.gameplayStop();
} else {
crazyGamesSDK.gameplayStart();
}
this.eventBus.emit(new PauseGameIntentEvent(pause));
}
}
@@ -4,6 +4,7 @@ import { assetUrl } from "../../../core/AssetUrls";
import { EventBus } from "../../../core/EventBus";
import { PlayerType } from "../../../core/game/Game";
import { actionButton } from "../../components/ui/ActionButton";
import { showInGameConfirm } from "../../InGameModal";
import { SendKickPlayerIntentEvent } from "../../Transport";
import { translateText } from "../../Utils";
import { PlayerView } from "../../view";
@@ -52,7 +53,7 @@ export class PlayerModerationModal extends LitElement {
);
}
private handleKickClick = (e: MouseEvent) => {
private handleKickClick = async (e: MouseEvent) => {
e.stopPropagation();
const my = this.myPlayer;
@@ -66,7 +67,7 @@ export class PlayerModerationModal extends LitElement {
const targetClientID = other.clientID();
if (!targetClientID || targetClientID.length === 0) return;
const confirmed = confirm(
const confirmed = await showInGameConfirm(
translateText("player_panel.kick_confirm", { name: other.displayName() }),
);
if (!confirmed) return;
+10 -5
View File
@@ -108,12 +108,17 @@ export class SettingsModal extends LitElement implements Controller {
}
private pauseGame(pause: boolean) {
// CrazyGames: report gameplay as stopped whenever the 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();
}
// Only pause the simulation itself when we own the pause (singleplayer or
// lobby creator).
if (this.shouldPause && !this.wasPausedWhenOpened) {
if (pause) {
crazyGamesSDK.gameplayStop();
} else {
crazyGamesSDK.gameplayStart();
}
this.eventBus.emit(new PauseGameIntentEvent(pause));
}
}