feat(game): 添加钱包余额刷新功能
- 在桌面端和移动端头部组件中添加余额刷新按钮 - 实现 useWalletBalanceRefresh 钩子用于余额刷新逻辑 - 添加刷新图标并集成到钻石币显示区域 - 支持多语言本地化包括英语、印尼语、马来语和中文 - 优化消息广播组件的动画过渡效果 - 添加防重复提交机制避免并发刷新请求 - 集成加载状态显示和错误处理通知功能
This commit is contained in:
@@ -120,7 +120,7 @@ export function MessageBroadcast({
|
||||
src={broadcast}
|
||||
/>
|
||||
<div className="relative h-design-16 min-w-0 flex-1 overflow-hidden md:h-design-28">
|
||||
<AnimatePresence>
|
||||
<AnimatePresence mode="wait">
|
||||
{activeBroadcast ? (
|
||||
<motion.div
|
||||
aria-label={activeBroadcastLabel}
|
||||
@@ -136,7 +136,10 @@ export function MessageBroadcast({
|
||||
? { opacity: 1 }
|
||||
: { opacity: 1, x: '-108%' }
|
||||
}
|
||||
exit={{ opacity: 0 }}
|
||||
exit={{
|
||||
opacity: 0,
|
||||
transition: { duration: 0.15, ease: 'easeOut' },
|
||||
}}
|
||||
transition={{
|
||||
duration: prefersReducedMotion
|
||||
? 0.18
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Mail,
|
||||
Maximize,
|
||||
Minimize,
|
||||
RefreshCw,
|
||||
UserKey,
|
||||
UserRoundPlus,
|
||||
Volume2,
|
||||
@@ -17,6 +18,8 @@ import diamond from '@/assets/system/diamond.webp'
|
||||
import logo from '@/assets/system/logo.webp'
|
||||
import { SmartImage } from '@/components/smart-image.tsx'
|
||||
import { useHeaderClockLabel, useHeaderVm } from '@/hooks/use-header-vm'
|
||||
import { useWalletBalanceRefresh } from '@/hooks/use-wallet-balance-refresh'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useModalStore } from '@/store'
|
||||
|
||||
function HeaderClock() {
|
||||
@@ -60,6 +63,8 @@ function SignalBars({
|
||||
export function DesktopHeader() {
|
||||
const { t } = useTranslation()
|
||||
const setModalOpen = useModalStore((state) => state.setModalOpen)
|
||||
const { isRefreshingBalance, refreshWalletBalance } =
|
||||
useWalletBalanceRefresh()
|
||||
const {
|
||||
authStatus,
|
||||
currentLanguageLabel,
|
||||
@@ -217,10 +222,7 @@ export function DesktopHeader() {
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group relative flex items-center justify-center transition-transform duration-150"
|
||||
>
|
||||
<div className="group relative flex items-center justify-center">
|
||||
<SmartImage
|
||||
src={diamond}
|
||||
alt="diamond"
|
||||
@@ -234,14 +236,32 @@ export function DesktopHeader() {
|
||||
>
|
||||
<div className="truncate">{currentUser?.coin || '--'}</div>
|
||||
|
||||
<SmartImage
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('commonUi.actions.refreshBalance')}
|
||||
title={t('commonUi.actions.refreshBalance')}
|
||||
disabled={isRefreshingBalance}
|
||||
onClick={() => void refreshWalletBalance()}
|
||||
className="flex h-design-24 w-design-24 shrink-0 cursor-pointer items-center justify-center rounded-[3px] text-[#8DE4EA] transition-colors hover:bg-white/10 disabled:cursor-wait disabled:opacity-65"
|
||||
>
|
||||
<RefreshCw
|
||||
aria-hidden="true"
|
||||
className={cn(
|
||||
'h-design-16 w-design-16',
|
||||
isRefreshingBalance && 'animate-spin',
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenProcedures}
|
||||
className={'w-design-24 h-design-24 cursor-pointer'}
|
||||
alt={'add'}
|
||||
src={add}
|
||||
/>
|
||||
className="h-design-24 w-design-24 shrink-0 cursor-pointer"
|
||||
>
|
||||
<SmartImage className="h-full w-full" alt="add" src={add} />
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Info,
|
||||
Mail,
|
||||
RefreshCw,
|
||||
UserKey,
|
||||
UserRoundPlus,
|
||||
Volume2,
|
||||
@@ -15,6 +16,7 @@ import diamond from '@/assets/system/diamond.webp'
|
||||
import logo from '@/assets/system/logo.webp'
|
||||
import { SmartImage } from '@/components/smart-image.tsx'
|
||||
import { useHeaderClockLabel, useHeaderVm } from '@/hooks/use-header-vm'
|
||||
import { useWalletBalanceRefresh } from '@/hooks/use-wallet-balance-refresh'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useModalStore } from '@/store'
|
||||
|
||||
@@ -68,6 +70,8 @@ function SignalBars({
|
||||
export function MobileHeader() {
|
||||
const { t } = useTranslation()
|
||||
const setModalOpen = useModalStore((state) => state.setModalOpen)
|
||||
const { isRefreshingBalance, refreshWalletBalance } =
|
||||
useWalletBalanceRefresh()
|
||||
const {
|
||||
authStatus,
|
||||
currentLanguageLabel,
|
||||
@@ -133,11 +137,7 @@ export function MobileHeader() {
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenProcedures}
|
||||
className="group relative flex min-w-0 items-center justify-center transition-transform duration-150 hover:-translate-y-[1px] active:translate-y-[1px]"
|
||||
>
|
||||
<div className="group relative flex min-w-0 items-center justify-center">
|
||||
<SmartImage
|
||||
src={diamond}
|
||||
alt="diamond"
|
||||
@@ -150,14 +150,36 @@ export function MobileHeader() {
|
||||
<span className="min-w-0 truncate">
|
||||
{currentUser?.coin || '--'}
|
||||
</span>
|
||||
<SmartImage
|
||||
src={add}
|
||||
alt="add"
|
||||
priority
|
||||
<button
|
||||
type="button"
|
||||
aria-label={t('commonUi.actions.refreshBalance')}
|
||||
title={t('commonUi.actions.refreshBalance')}
|
||||
disabled={isRefreshingBalance}
|
||||
onClick={() => void refreshWalletBalance()}
|
||||
className="flex h-design-13 w-design-13 shrink-0 cursor-pointer items-center justify-center text-[#8DE4EA] disabled:cursor-wait disabled:opacity-65"
|
||||
>
|
||||
<RefreshCw
|
||||
aria-hidden="true"
|
||||
className={cn(
|
||||
'h-design-9 w-design-9',
|
||||
isRefreshingBalance && 'animate-spin',
|
||||
)}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenProcedures}
|
||||
className="h-design-13 w-design-13 shrink-0 cursor-pointer"
|
||||
/>
|
||||
>
|
||||
<SmartImage
|
||||
src={add}
|
||||
alt="add"
|
||||
priority
|
||||
className="h-full w-full"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-full shrink-0 items-center justify-end gap-design-8 px-design-9">
|
||||
|
||||
45
src/hooks/use-wallet-balance-refresh.ts
Normal file
45
src/hooks/use-wallet-balance-refresh.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { useCallback, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { getCurrentUserProfile } from '@/api'
|
||||
import { notify } from '@/lib/notify'
|
||||
import { useAuthStore } from '@/store'
|
||||
|
||||
export function useWalletBalanceRefresh() {
|
||||
const { t } = useTranslation()
|
||||
const setCurrentUser = useAuthStore((state) => state.setCurrentUser)
|
||||
const [isRefreshingBalance, setIsRefreshingBalance] = useState(false)
|
||||
const refreshPromiseRef = useRef<Promise<void> | null>(null)
|
||||
|
||||
const refreshWalletBalance = useCallback(() => {
|
||||
if (refreshPromiseRef.current) {
|
||||
return refreshPromiseRef.current
|
||||
}
|
||||
|
||||
setIsRefreshingBalance(true)
|
||||
|
||||
const refreshPromise = getCurrentUserProfile()
|
||||
.then((currentUser) => {
|
||||
setCurrentUser(currentUser)
|
||||
})
|
||||
.catch((error: unknown) => {
|
||||
notify.error(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: t('commonUi.toast.requestFailed'),
|
||||
)
|
||||
})
|
||||
.finally(() => {
|
||||
refreshPromiseRef.current = null
|
||||
setIsRefreshingBalance(false)
|
||||
})
|
||||
|
||||
refreshPromiseRef.current = refreshPromise
|
||||
|
||||
return refreshPromise
|
||||
}, [setCurrentUser, t])
|
||||
|
||||
return {
|
||||
isRefreshingBalance,
|
||||
refreshWalletBalance,
|
||||
}
|
||||
}
|
||||
@@ -479,6 +479,7 @@ export default {
|
||||
},
|
||||
commonUi: {
|
||||
actions: {
|
||||
refreshBalance: 'Refresh balance',
|
||||
submitting: TEXT_SUBMITTING,
|
||||
},
|
||||
dialog: {
|
||||
|
||||
@@ -478,6 +478,7 @@ export default {
|
||||
},
|
||||
commonUi: {
|
||||
actions: {
|
||||
refreshBalance: 'Segarkan saldo',
|
||||
submitting: TEXT_SUBMITTING,
|
||||
},
|
||||
dialog: {
|
||||
|
||||
@@ -481,6 +481,7 @@ export default {
|
||||
},
|
||||
commonUi: {
|
||||
actions: {
|
||||
refreshBalance: 'Segarkan baki',
|
||||
submitting: TEXT_SUBMITTING,
|
||||
},
|
||||
dialog: {
|
||||
|
||||
@@ -462,6 +462,7 @@ export default {
|
||||
},
|
||||
commonUi: {
|
||||
actions: {
|
||||
refreshBalance: '刷新余额',
|
||||
submitting: TEXT_SUBMITTING,
|
||||
},
|
||||
dialog: {
|
||||
|
||||
Reference in New Issue
Block a user