Files
36-character-flower/src/features/game/components/desktop/desktop-status.tsx
JiaJun c841eb6688 fix(game): 关闭桌面端连续效果预览强制显示
- 将 FORCE_DESKTOP_STREAK_EFFECT_PREVIEW 常量设置为 false
- 禁用桌面端连续效果的强制预览模式
2026-07-16 14:47:48 +08:00

242 lines
9.9 KiB
TypeScript

import { motion, useReducedMotion } from 'motion/react'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import streakBg from '@/assets/game/pc-streak.webp'
import down5Animation from '@/assets/lottie/down5.json'
import diamond from '@/assets/system/diamond.webp'
import fire from '@/assets/system/fire.webp'
import lock from '@/assets/system/lock.webp'
import statusCenter from '@/assets/system/status-center.webp'
import statusLine from '@/assets/system/status-line.webp'
import { JackpotPoolTicker } from '@/components/jackpot-pool-ticker.tsx'
import { LottiePlayer } from '@/components/lottie-player.tsx'
import { MessageBroadcast } from '@/components/message-broadcast.tsx'
import { SmartBackground } from '@/components/smart-background.tsx'
import { SmartImage } from '@/components/smart-image.tsx'
import { DesktopCountdown } from '@/features/game/components/desktop/desktop-countdown.tsx'
import { useGameStatusVm } from '@/hooks/use-game-status-vm.ts'
import { cn } from '@/lib/utils.ts'
const FORCE_DESKTOP_STREAK_EFFECT_PREVIEW = false
export function DesktopStatusLine() {
const { t } = useTranslation()
const prefersReducedMotion = useReducedMotion()
const {
countdownMs,
limitLabel,
oddsLabel,
phaseLabel,
phaseToneClassName,
roundId,
streakLabel,
streakValue,
} = useGameStatusVm()
const [remainingMs, setRemainingMs] = useState(countdownMs)
const showWarningCountdown = remainingMs <= 5000 && remainingMs > 0
const showStreakLimitOnly =
FORCE_DESKTOP_STREAK_EFFECT_PREVIEW ||
(typeof streakValue === 'number' && streakValue > 1)
const countdownClassName = useMemo(
() =>
showWarningCountdown
? 'text-design-64 scale-[1.2] text-[#FF5A5A] [text-shadow:0_0_calc(var(--design-unit)*10)_rgba(255,90,90,0.85),0_0_calc(var(--design-unit)*22)_rgba(255,90,90,0.32)]'
: 'text-design-64 scale-[1.2] text-[#4BFFFE] [text-shadow:0_0_calc(var(--design-unit)*10)_rgba(75,255,254,0.85),0_0_calc(var(--design-unit)*22)_rgba(75,255,254,0.32)]',
[showWarningCountdown],
)
return (
<div className="relative w-full text-design-22">
<div className="flex w-full items-start gap-design-14 px-design-16">
<div className="flex min-w-0 flex-1 flex-col">
<div className="mb-design-10 w-full">
<MessageBroadcast showJackpotPool={false} />
</div>
<SmartBackground
src={statusLine}
size="100% 100%"
className="flex h-design-75 w-full items-center justify-center bg-center bg-no-repeat"
>
{/* 状态栏左侧 */}
<div
className={
'relative flex h-full w-design-760 shrink-0 items-center justify-center gap-design-64 overflow-visible'
}
>
{showStreakLimitOnly && (
<div
className={
'pointer-events-none absolute bg-center bg-no-repeat'
}
style={{
top: 'calc(var(--design-unit)*-14)',
right: 'calc(var(--design-unit)*-190)',
bottom: 'calc(var(--design-unit)*-1)',
left: 0,
backgroundImage: `url(${streakBg})`,
backgroundPosition: 'center',
backgroundSize: '113% 150%',
}}
/>
)}
{!showStreakLimitOnly && (
<>
<div
className={
'shrink-0 whitespace-nowrap font-bold text-[#CBD3D5]'
}
>
{t('gameDesktop.status.odds')}:{' '}
<span className={'text-[#E3D171]'}>{oddsLabel}</span>
</div>
<div
className={
'flex shrink-0 items-center gap-design-5 whitespace-nowrap font-bold text-[#CBD3D5]'
}
>
<SmartImage
className={'w-design-37 h-design-47'}
alt={'fire'}
src={fire}
/>
<div>
{t('gameDesktop.status.streak')}:{' '}
<span
className={
'bg-gradient-to-b from-[#EBA661] to-[#FCC785] bg-clip-text text-transparent'
}
>
{streakLabel}
</span>
</div>
</div>
</>
)}
<div
className={
'relative z-20 flex shrink-0 items-center gap-design-5 whitespace-nowrap font-bold text-[#CBD3D5]'
}
>
<SmartImage
className={'w-design-25 h-design-33'}
alt={'lock'}
src={lock}
/>
<div className={'flex items-center gap-design-10'}>
<div>{t('gameDesktop.status.limit')}:</div>
<div className={'flex items-center gap-design-5'}>
<SmartImage
className={'w-design-35 h-design-35'}
alt={'diamond'}
src={diamond}
/>
<div>{limitLabel}</div>
</div>
</div>
</div>
</div>
<div className="relative z-20 flex h-[105px] w-design-360 items-center justify-center">
<SmartBackground
src={statusCenter}
className="pointer-events-none absolute inset-0 bg-no-repeat bg-center bg-contain transition-opacity duration-500 ease-out"
size="contain"
style={{
opacity: showWarningCountdown ? 0.18 : 1,
transform: showWarningCountdown ? 'scale(0.985)' : 'scale(1)',
}}
/>
<div
className="pointer-events-none absolute inset-0 overflow-visible transition-all duration-500 ease-out"
style={{
opacity: showWarningCountdown ? 1 : 0,
transform: showWarningCountdown
? 'scale(1.1) translateY(calc(var(--design-unit)*1))'
: 'scale(1.02) translateY(0)',
}}
>
<LottiePlayer
animationData={down5Animation}
className="h-full w-full"
loop
autoplay
/>
</div>
<DesktopCountdown
initialMs={countdownMs}
onRemainingMsChange={setRemainingMs}
className={countdownClassName}
/>
</div>
<div className="grid min-w-0 w-design-374 shrink-0 grid-cols-[minmax(0,0.78fr)_minmax(0,1.22fr)] items-center justify-items-stretch pl-design-6 pr-design-16">
<div className="flex min-w-0 items-center justify-center gap-design-6">
<span className="relative flex h-design-24 w-design-24 items-center justify-center">
<motion.span
aria-hidden="true"
className="absolute h-design-24 w-design-24 rounded-full bg-[rgba(120,255,127,0.22)] blur-[calc(var(--design-unit)*3)]"
animate={
prefersReducedMotion
? undefined
: {
opacity: [0.36, 0.88, 0.42],
scale: [0.9, 1.28, 0.98],
}
}
transition={
prefersReducedMotion
? undefined
: {
duration: 1.25,
ease: 'easeInOut',
repeat: Number.POSITIVE_INFINITY,
}
}
/>
<motion.span
aria-hidden="true"
className="relative h-design-14 w-design-14 rounded-full bg-[#78FF7F] shadow-[0_0_calc(var(--design-unit)*8)_rgba(120,255,127,0.78),0_0_calc(var(--design-unit)*16)_rgba(120,255,127,0.34)]"
animate={
prefersReducedMotion
? undefined
: { opacity: [0.78, 1, 0.86], scale: [0.96, 1.12, 1] }
}
transition={
prefersReducedMotion
? undefined
: {
duration: 1.25,
ease: 'easeInOut',
repeat: Number.POSITIVE_INFINITY,
}
}
/>
</span>
<div
className={cn(
phaseToneClassName,
'font-black tracking-[0.08em] [text-shadow:0_0_calc(var(--design-unit)*10)_rgba(120,255,127,0.44)]',
)}
>
{phaseLabel}
</div>
</div>
<div className="flex min-w-0 items-baseline justify-center gap-design-5 font-bold leading-none">
<span className="text-design-20 tracking-[0.06em] text-[#9FBAC0]">
{t('gameDesktop.status.roundId')}:
</span>
<span className="min-w-0 truncate text-design-24 font-black tracking-[0.06em] text-[#E7FFFF] [text-shadow:0_0_calc(var(--design-unit)*9)_rgba(75,255,254,0.38)]">
{roundId}
</span>
</div>
</div>
</SmartBackground>
</div>
<JackpotPoolTicker className="mt-design-0" variant="hud" />
</div>
</div>
)
}