mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-10 15:34:36 +00:00
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:
@@ -26,9 +26,15 @@ vi.mock("../../../../src/client/components/ui/ActionButton", () => ({
|
||||
actionButton: vi.fn((props: unknown) => props),
|
||||
}));
|
||||
|
||||
vi.mock("../../../../src/client/InGameModal", () => ({
|
||||
showInGameConfirm: vi.fn(),
|
||||
showInGameAlert: vi.fn(),
|
||||
}));
|
||||
|
||||
import { actionButton } from "../../../../src/client/components/ui/ActionButton";
|
||||
import { PlayerModerationModal } from "../../../../src/client/hud/layers/PlayerModerationModal";
|
||||
import { PlayerPanel } from "../../../../src/client/hud/layers/PlayerPanel";
|
||||
import { showInGameConfirm } from "../../../../src/client/InGameModal";
|
||||
import { SendKickPlayerIntentEvent } from "../../../../src/client/Transport";
|
||||
import { PlayerView } from "../../../../src/client/view";
|
||||
import { PlayerType } from "../../../../src/core/game/Game";
|
||||
@@ -120,15 +126,12 @@ describe("PlayerPanel - kick player moderation", () => {
|
||||
});
|
||||
|
||||
describe("PlayerModerationModal - kick confirmation", () => {
|
||||
const originalConfirm = globalThis.confirm;
|
||||
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
globalThis.confirm = originalConfirm;
|
||||
});
|
||||
|
||||
test("emits SendKickPlayerIntentEvent and dispatches kicked when confirmed", () => {
|
||||
(globalThis as any).confirm = vi.fn(() => true);
|
||||
test("emits SendKickPlayerIntentEvent and dispatches kicked when confirmed", async () => {
|
||||
(showInGameConfirm as ReturnType<typeof vi.fn>).mockResolvedValue(true);
|
||||
|
||||
const modal = new PlayerModerationModal();
|
||||
const eventBus = { emit: vi.fn() };
|
||||
@@ -148,7 +151,7 @@ describe("PlayerModerationModal - kick confirmation", () => {
|
||||
const kickedListener = vi.fn();
|
||||
modal.addEventListener("kicked", kickedListener as any);
|
||||
|
||||
(modal as any).handleKickClick({ stopPropagation: vi.fn() });
|
||||
await (modal as any).handleKickClick({ stopPropagation: vi.fn() });
|
||||
|
||||
expect(eventBus.emit).toHaveBeenCalledTimes(1);
|
||||
const event = eventBus.emit.mock.calls[0][0] as SendKickPlayerIntentEvent;
|
||||
@@ -160,8 +163,8 @@ describe("PlayerModerationModal - kick confirmation", () => {
|
||||
expect(kickedEvent.detail).toEqual({ playerId: "2" });
|
||||
});
|
||||
|
||||
test("does not emit when confirmation is cancelled", () => {
|
||||
(globalThis as any).confirm = vi.fn(() => false);
|
||||
test("does not emit when confirmation is cancelled", async () => {
|
||||
(showInGameConfirm as ReturnType<typeof vi.fn>).mockResolvedValue(false);
|
||||
|
||||
const modal = new PlayerModerationModal();
|
||||
const eventBus = { emit: vi.fn() };
|
||||
@@ -181,7 +184,7 @@ describe("PlayerModerationModal - kick confirmation", () => {
|
||||
const kickedListener = vi.fn();
|
||||
modal.addEventListener("kicked", kickedListener as any);
|
||||
|
||||
(modal as any).handleKickClick({ stopPropagation: vi.fn() });
|
||||
await (modal as any).handleKickClick({ stopPropagation: vi.fn() });
|
||||
|
||||
expect(eventBus.emit).not.toHaveBeenCalled();
|
||||
expect(kickedListener).not.toHaveBeenCalled();
|
||||
|
||||
Reference in New Issue
Block a user