Match intro "players joining" loading screen + i18n fix; checkpoint
- MatchIntroOverlay: UNO-style pre-game reveal — the 4 seats animate into the table (with "?" placeholders until each player's data streams in for live matches), a 3-2-1-GO countdown, then the table shows. Wired via game-store matchIntroPending/consumeIntro, rendered online-only in GameScreen. - Fix: intro.found / intro.getReady / intro.go existed only in the Persian dict; added the English strings (would have shown raw keys to EN users). - Checkpoint of the in-progress UI/social batch (CoinsPill, shop titles section, friend-request rate limit, etc.) — all green. Verified: tsc + next build + scripts/sim.ts + dotnet build server/Hokm.slnx all pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,47 @@ interface Props {
|
||||
front?: CardFront;
|
||||
}
|
||||
|
||||
/* Pip positions (x,y as fractions of the card) for number cards 2–10. Bottom-half
|
||||
pips (y>0.5) render rotated 180°, like a real deck — so each rank looks distinct. */
|
||||
const PL = 0.3, PC = 0.5, PR = 0.7;
|
||||
const PIP_LAYOUT: Record<number, [number, number][]> = {
|
||||
2: [[PC, 0.24], [PC, 0.76]],
|
||||
3: [[PC, 0.22], [PC, 0.5], [PC, 0.78]],
|
||||
4: [[PL, 0.26], [PR, 0.26], [PL, 0.74], [PR, 0.74]],
|
||||
5: [[PL, 0.26], [PR, 0.26], [PC, 0.5], [PL, 0.74], [PR, 0.74]],
|
||||
6: [[PL, 0.24], [PR, 0.24], [PL, 0.5], [PR, 0.5], [PL, 0.76], [PR, 0.76]],
|
||||
7: [[PL, 0.23], [PR, 0.23], [PC, 0.365], [PL, 0.5], [PR, 0.5], [PL, 0.77], [PR, 0.77]],
|
||||
8: [[PL, 0.23], [PR, 0.23], [PC, 0.365], [PL, 0.5], [PR, 0.5], [PC, 0.635], [PL, 0.77], [PR, 0.77]],
|
||||
9: [[PL, 0.22], [PR, 0.22], [PL, 0.41], [PR, 0.41], [PC, 0.5], [PL, 0.59], [PR, 0.59], [PL, 0.78], [PR, 0.78]],
|
||||
10: [[PL, 0.22], [PR, 0.22], [PC, 0.32], [PL, 0.41], [PR, 0.41], [PL, 0.59], [PR, 0.59], [PC, 0.68], [PL, 0.78], [PR, 0.78]],
|
||||
};
|
||||
|
||||
function Pips({ rank, symbol, color, w }: { rank: number; symbol: string; color: string; w: number }) {
|
||||
const layout = PIP_LAYOUT[rank];
|
||||
if (!layout) return null;
|
||||
const size = (rank >= 9 ? 0.165 : rank >= 7 ? 0.19 : 0.22) * w;
|
||||
return (
|
||||
<div className="absolute inset-0 pointer-events-none">
|
||||
{layout.map(([x, y], i) => (
|
||||
<span
|
||||
key={i}
|
||||
className="absolute font-bold"
|
||||
style={{
|
||||
left: `${x * 100}%`,
|
||||
top: `${y * 100}%`,
|
||||
transform: `translate(-50%,-50%)${y > 0.5 ? " rotate(180deg)" : ""}`,
|
||||
fontSize: size,
|
||||
lineHeight: 1,
|
||||
color,
|
||||
}}
|
||||
>
|
||||
{symbol}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function PlayingCard({
|
||||
card,
|
||||
faceDown,
|
||||
@@ -81,6 +122,7 @@ export function PlayingCard({
|
||||
const red = SUIT_IS_RED[card.suit];
|
||||
const symbol = SUIT_SYMBOL[card.suit];
|
||||
const label = rankLabel(card.rank);
|
||||
const rank = card.rank;
|
||||
|
||||
// UNO-style: suit-aware background
|
||||
const cardBg = front
|
||||
@@ -114,18 +156,21 @@ export function PlayingCard({
|
||||
<div style={{ color: pipColor, fontSize: "0.82em" }}>{symbol}</div>
|
||||
</div>
|
||||
|
||||
{/* Center symbol — large, bold, slightly shadowed */}
|
||||
<div
|
||||
className={cn("absolute inset-0 flex items-center justify-center font-black", s.center)}
|
||||
style={{
|
||||
color: inkColor,
|
||||
textShadow: red
|
||||
? "0 2px 10px rgba(210,40,40,0.18)"
|
||||
: "0 2px 10px rgba(28,28,56,0.12)",
|
||||
}}
|
||||
>
|
||||
{symbol}
|
||||
</div>
|
||||
{/* Center: pip layout for 2–10, big rank for J/Q/K, single big pip for Ace */}
|
||||
{rank >= 2 && rank <= 10 ? (
|
||||
<Pips rank={rank} symbol={symbol} color={pipColor} w={s.w} />
|
||||
) : rank === 14 ? (
|
||||
<div className="absolute inset-0 flex items-center justify-center font-black"
|
||||
style={{ color: pipColor, textShadow: "0 2px 10px rgba(0,0,0,0.12)" }}>
|
||||
<span style={{ fontSize: s.w * 0.54, lineHeight: 1 }}>{symbol}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center font-black"
|
||||
style={{ lineHeight: 0.9 }}>
|
||||
<span style={{ fontSize: s.w * 0.46, color: inkColor }}>{label}</span>
|
||||
<span style={{ fontSize: s.w * 0.27, color: pipColor, marginTop: s.w * -0.03 }}>{symbol}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Bottom-right corner (rotated 180°) */}
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user