Game: landscape-first table with rotate-phone prompt + orientation lock
CI/CD / CI - API (dotnet build + engine sim) (push) Successful in 1m14s
CI/CD / CI - Web (tsc + next build) (push) Successful in 1m9s
CI/CD / Deploy - local stack (db + server + web) (push) Successful in 59s

Hokm plays best wide (UNO-style). On phones held in portrait, the game screen
shows a "rotate your phone" overlay (with a play-anyway escape hatch so OS
rotation-lock can't trap anyone). Best-effort screen.orientation.lock('landscape')
on Android/PWA; iOS/desktop reject it harmlessly. i18n rotate.* (fa+en).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-10 23:53:21 +03:30
parent c1ecdff729
commit e8b3172197
3 changed files with 82 additions and 0 deletions
+18
View File
@@ -5,6 +5,7 @@ import { useEffect, useRef, useState } from "react";
import { GameTable } from "@/components/GameTable";
import { PostMatchRewardsModal } from "@/components/online/PostMatchRewardsModal";
import { MatchIntroOverlay } from "@/components/online/MatchIntroOverlay";
import { RotatePrompt } from "@/components/online/RotatePrompt";
import { useGameStore } from "@/lib/game-store";
import { useSessionStore } from "@/lib/session-store";
import { useUIStore } from "@/lib/ui-store";
@@ -58,6 +59,20 @@ export function GameScreen() {
};
}, []);
// Landscape-first table: best-effort lock to landscape on Android/PWA (iOS &
// desktop reject it — harmless). Restored to portrait/auto when leaving.
useEffect(() => {
const o = (screen as unknown as { orientation?: { lock?: (m: string) => Promise<void>; unlock?: () => void } }).orientation;
o?.lock?.("landscape").catch(() => {});
return () => {
try {
o?.unlock?.();
} catch {
/* unsupported — ignore */
}
};
}, []);
const notifyAchievements = (r: RewardResult) => {
for (const a of r.newAchievements)
pushNotification({
@@ -142,6 +157,9 @@ export function GameScreen() {
onForfeit={canForfeit ? () => useGameStore.getState().forfeit() : undefined}
/>
{/* Landscape-first: nudge to rotate when held in portrait on a phone */}
<RotatePrompt />
{/* UNO-style "players joining the table" intro (online matches, once) */}
<AnimatePresence>
{introPending && mode === "online" && (