refactor(game): 优化游戏组件并实现国际化支持
- 在AppBootResourceGate组件中集成react-i18next实现资源加载文本的国际化 - 修改DesktopAnimal组件中的loading dots key以提高渲染性能 - 在DesktopControl组件中添加useRef和useEffect钩子管理定时器清理逻辑 - 将DesktopTitle组件重构为MessageBroadcast组件并增强其响应式设计 - 更新DesktopSupportModal组件中的客户服务文本为国际化格式 - 在AuthSession模块中实现本地存储数据清理时保留关键偏好设置 - 调整多个游戏组件的样式类以改进移动端适配效果 - 移除未使用的桌面提取功能相关代码文件 - 更新GitNexus索引统计数据反映最新的代码变更
This commit is contained in:
@@ -5,7 +5,6 @@ import {
|
||||
UserRoundPlus,
|
||||
Volume2,
|
||||
VolumeX,
|
||||
Wifi,
|
||||
} from 'lucide-react'
|
||||
import { motion } from 'motion/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -14,6 +13,7 @@ import chatImage from '@/assets/system/chat.webp'
|
||||
import diamond from '@/assets/system/diamond.webp'
|
||||
import logo from '@/assets/system/logo.webp'
|
||||
import { SmartImage } from '@/components/smart-image.tsx'
|
||||
import { MessageBroadcast } from '@/features/game/components/desktop/desktop-title.tsx'
|
||||
import { useHeaderClockLabel, useHeaderVm } from '@/hooks/use-header-vm'
|
||||
import { useModalStore } from '@/store'
|
||||
|
||||
@@ -27,6 +27,43 @@ function MobileHeaderClock() {
|
||||
)
|
||||
}
|
||||
|
||||
function SignalBars({
|
||||
activeBars,
|
||||
toneClassName,
|
||||
}: {
|
||||
activeBars: number
|
||||
toneClassName: string
|
||||
}) {
|
||||
const barHeights = [
|
||||
'h-[calc(var(--design-unit)*4)]',
|
||||
'h-[calc(var(--design-unit)*6)]',
|
||||
'h-[calc(var(--design-unit)*8)]',
|
||||
'h-[calc(var(--design-unit)*10)]',
|
||||
] as const
|
||||
|
||||
return (
|
||||
<div
|
||||
className="flex h-design-11 w-design-16 items-end gap-[1px]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
{barHeights.map((heightClassName, index) => {
|
||||
const isActive = index < activeBars
|
||||
|
||||
return (
|
||||
<div
|
||||
key={heightClassName}
|
||||
className={[
|
||||
'w-[calc(var(--design-unit)*2)] rounded-t-[1px] transition-colors',
|
||||
heightClassName,
|
||||
isActive ? `bg-current ${toneClassName}` : 'bg-white/18',
|
||||
].join(' ')}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function MobileHeader() {
|
||||
const { t } = useTranslation()
|
||||
const setModalOpen = useModalStore((state) => state.setModalOpen)
|
||||
@@ -53,9 +90,9 @@ export function MobileHeader() {
|
||||
'common-neon-inset flex h-design-19 items-center justify-end !rounded-[3px] !py-0 text-design-7 leading-none transition-[opacity,transform] duration-150 group-hover:opacity-90 group-active:scale-[0.98]'
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-30 h-design-62">
|
||||
<div className="border-b-2 border-[#787553] bg-[#020B14] flex h-design-33 w-full items-center">
|
||||
<div className="flex h-design-23 w-design-130 shrink-0 items-center justify-center border-r border-[rgba(128,223,231,0.45)] px-design-10">
|
||||
<header className="relative z-30 h-design-72">
|
||||
<div className="border-b-2 border-[#787553] bg-[#020B14] flex h-design-33 w-full items-center px-design-10">
|
||||
<div className="flex h-design-23 w-design-130 pr-design-10 shrink-0 items-center justify-center border-r border-[rgba(128,223,231,0.45)]">
|
||||
<SmartImage
|
||||
src={logo}
|
||||
alt="logo"
|
||||
@@ -64,21 +101,6 @@ export function MobileHeader() {
|
||||
imgClassName="object-contain"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenLanguage}
|
||||
className={`${actionButtonClassName} !px-design-10 justify-between`}
|
||||
>
|
||||
<SmartImage
|
||||
src={currentLanguageOption.icon}
|
||||
alt={currentLanguageLabel}
|
||||
className="h-design-14 w-design-14 shrink-0 rounded-full"
|
||||
imgClassName="object-cover"
|
||||
/>
|
||||
<div className="min-w-0 truncate">{currentLanguageLabel}</div>
|
||||
</button>
|
||||
|
||||
{authStatus === 'authenticated' ? (
|
||||
<div className="flex h-full min-w-0 flex-1 items-center justify-end gap-design-7 px-design-9">
|
||||
<button
|
||||
@@ -159,17 +181,32 @@ export function MobileHeader() {
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<motion.button
|
||||
type="button"
|
||||
onClick={() => setModalOpen('desktopSupport', true)}
|
||||
whileTap={{
|
||||
scale: 0.95,
|
||||
}}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
>
|
||||
<SmartImage
|
||||
className={'h-design-20 w-design-20 cursor-pointer'}
|
||||
alt={'chatImage'}
|
||||
src={chatImage}
|
||||
/>
|
||||
</motion.button>
|
||||
</div>
|
||||
|
||||
<div className={'w-full px-design-10 '}>
|
||||
<div className="flex h-design-29 w-full items-center gap-design-5 my-design-5 rounded-sm border-[#0A353E] border-1">
|
||||
<div className="flex h-design-19 w-design-43 shrink-0 items-center justify-center gap-design-5 !rounded-[3px] !px-design-6 !py-0">
|
||||
<Wifi
|
||||
aria-hidden="true"
|
||||
color="currentColor"
|
||||
strokeWidth={2.4}
|
||||
className={`${signalPresentation.toneClassName} h-design-10 w-design-10 shrink-0`}
|
||||
/>
|
||||
<div className="flex h-design-19 w-design-43 shrink-0 items-center justify-center !rounded-[3px] !px-design-6 !py-0">
|
||||
<div className={signalPresentation.toneClassName}>
|
||||
<SignalBars
|
||||
activeBars={signalPresentation.activeBars}
|
||||
toneClassName={signalPresentation.toneClassName}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={`${signalPresentation.toneClassName} whitespace-nowrap text-design-7 font-bold leading-none`}
|
||||
>
|
||||
@@ -178,7 +215,7 @@ export function MobileHeader() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex h-full w-design-66 shrink-0 flex-col items-start justify-center border-r border-[rgba(128,223,231,0.32)] pr-design-7 text-design-7 leading-none">
|
||||
<div className="flex flex-col h-full w-design-66 shrink-0 items-center justify-center border-r border-[rgba(128,223,231,0.32)] pr-design-7 text-design-7 leading-none">
|
||||
<div className="text-[#B4E4E9]">
|
||||
{t('gameDesktop.header.systemTime')}
|
||||
</div>
|
||||
@@ -188,7 +225,7 @@ export function MobileHeader() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenRules}
|
||||
className={`${actionButtonClassName} !px-design-10`}
|
||||
className={`${actionButtonClassName} !px-design-8`}
|
||||
>
|
||||
<Info className="h-design-8 w-design-8 shrink-0" color="#57B8BF" />
|
||||
<div className="min-w-0 truncate">
|
||||
@@ -199,7 +236,7 @@ export function MobileHeader() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenNotice}
|
||||
className={`${actionButtonClassName} !px-design-10`}
|
||||
className={`${actionButtonClassName} !px-design-8`}
|
||||
>
|
||||
<Mail className="h-design-8 w-design-8 shrink-0" color="#57B8BF" />
|
||||
<div className="min-w-0 truncate">
|
||||
@@ -210,7 +247,7 @@ export function MobileHeader() {
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleSoundEnabled}
|
||||
className={`${actionButtonClassName} !px-design-10`}
|
||||
className={`${actionButtonClassName} !px-design-8`}
|
||||
>
|
||||
{isSoundEnabled ? (
|
||||
<Volume2
|
||||
@@ -227,21 +264,19 @@ export function MobileHeader() {
|
||||
{t('gameDesktop.header.bgm')}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<motion.button
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setModalOpen('desktopSupport', true)}
|
||||
whileTap={{
|
||||
scale: 0.95,
|
||||
}}
|
||||
whileHover={{ scale: 1.05 }}
|
||||
onClick={onOpenLanguage}
|
||||
className={`${actionButtonClassName} !px-design-8 justify-between`}
|
||||
>
|
||||
<SmartImage
|
||||
className={'h-design-20 w-design-20 cursor-pointer'}
|
||||
alt={'chatImage'}
|
||||
src={chatImage}
|
||||
src={currentLanguageOption.icon}
|
||||
alt={currentLanguageLabel}
|
||||
className="h-design-14 w-design-14 shrink-0 rounded-full"
|
||||
imgClassName="object-cover"
|
||||
/>
|
||||
</motion.button>
|
||||
<div className="min-w-0 truncate">{currentLanguageLabel}</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user