Fix some card UX.
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import type { Dispatch, SetStateAction } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
import type { BattleEvent, Card, ClientMessage, GameView } from '../types'
|
||||
import { CardView } from './CardView'
|
||||
import { CardView, CardZoom } from './CardView'
|
||||
import { DiceRoll, ROLL_MS } from './DiceRoll'
|
||||
import { SPEED_OPTIONS, useBattleSpeed } from '../useBattleSpeed'
|
||||
import { useMediaQuery } from '../useMediaQuery'
|
||||
|
||||
// How long a settled rock roll (and its damage) stays on screen before the
|
||||
// battle advances to the next step.
|
||||
@@ -313,6 +314,25 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
|
||||
// paused freezes auto-advance so the player can walk the log manually.
|
||||
const [paused, setPaused] = useState(false)
|
||||
|
||||
// Phone tap-to-magnify: tapping a pet/food opens a big readable copy (phones
|
||||
// can't hover to preview). Opening it pauses the replay; closing it resumes
|
||||
// only if the replay was actually playing when we tapped, so a manual pause
|
||||
// (or a finished battle) stays put.
|
||||
const isPhone = useMediaQuery('(max-width: 600px)')
|
||||
const [zoom, setZoom] = useState<{ card: Card; bonus: number; damage: number; dead: boolean } | null>(
|
||||
null,
|
||||
)
|
||||
const resumeAfterZoom = useRef(false)
|
||||
const openZoom = (z: { card: Card; bonus?: number; damage?: number; dead?: boolean }) => {
|
||||
resumeAfterZoom.current = !paused && !done
|
||||
setPaused(true)
|
||||
setZoom({ card: z.card, bonus: z.bonus ?? 0, damage: z.damage ?? 0, dead: !!z.dead })
|
||||
}
|
||||
const closeZoom = () => {
|
||||
setZoom(null)
|
||||
if (resumeAfterZoom.current) setPaused(false)
|
||||
}
|
||||
|
||||
// A rock event on screen scrambles its dice first; only once they settle do
|
||||
// we apply the damage and reveal the result.
|
||||
const showingRock = !done && lastEvent?.type === 'rock'
|
||||
@@ -485,7 +505,11 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
|
||||
}`}
|
||||
style={{ zIndex: i + 1 }}
|
||||
>
|
||||
<CardView card={f} size="sm" />
|
||||
<CardView
|
||||
card={f}
|
||||
size="sm"
|
||||
onClick={isPhone ? () => openZoom({ card: f }) : undefined}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -512,6 +536,17 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
|
||||
bonus={s.unit.bonus}
|
||||
damage={s.unit.damage}
|
||||
dead={s.unit.dying}
|
||||
onClick={
|
||||
isPhone
|
||||
? () =>
|
||||
openZoom({
|
||||
card: s.unit!.card,
|
||||
bonus: s.unit!.bonus,
|
||||
damage: s.unit!.damage,
|
||||
dead: s.unit!.dying,
|
||||
})
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
{(s.unit.spooked > 0 || s.unit.exposed > 0) && (
|
||||
<div className="ailment-badges">
|
||||
@@ -717,6 +752,16 @@ export function BattlePhase({ view, send, step, setStep }: Props) {
|
||||
</div>,
|
||||
document.body,
|
||||
)}
|
||||
|
||||
{zoom && (
|
||||
<CardZoom
|
||||
card={zoom.card}
|
||||
bonus={zoom.bonus}
|
||||
damage={zoom.damage}
|
||||
dead={zoom.dead}
|
||||
onClose={closeZoom}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user