diff --git a/src/features/game/components/desktop/desktop-animal.tsx b/src/features/game/components/desktop/desktop-animal.tsx index 4958585..545d650 100644 --- a/src/features/game/components/desktop/desktop-animal.tsx +++ b/src/features/game/components/desktop/desktop-animal.tsx @@ -7,6 +7,7 @@ import diamondIcon from '@/assets/system/diamond.webp' import { SmartImage } from '@/components/smart-image' import { DesktopAnimalOverlay } from '@/features/game/components/desktop/desktop-animal-overlay.tsx' import { AnimalSpriteImage } from '@/features/game/components/shared/animal-sprite-image' +import { LongPressProgress } from '@/features/game/components/shared/long-press-progress' import { RoundBettingStartAlert } from '@/features/game/components/shared/round-betting-start-alert.tsx' import { FLOWER_IMAGE_LIST } from '@/features/game/shared' import { useAnimalVm } from '@/hooks/use-animal-vm' @@ -83,10 +84,17 @@ export function DesktopAnimal({ ) const { cellWarning, + handleClearCell, + handleLongPressCancel, + handleLongPressEnd, + handleLongPressMove, + handleLongPressStart, handleSelect, handleStart, isRealtimeConnecting, lockInteraction, + longPressCellId, + longPressDurationMs, marqueeId, selectionByCell, showStandbyState, @@ -212,6 +220,17 @@ export function DesktopAnimal({ type="button" disabled={lockInteraction || showStopOverlay} onClick={() => handleSelect(item.id)} + onContextMenu={(event) => event.preventDefault()} + onKeyDown={(event) => { + if (event.key === 'Delete' || event.key === 'Backspace') { + event.preventDefault() + handleClearCell(item.id) + } + }} + onPointerCancel={handleLongPressCancel} + onPointerDown={(event) => handleLongPressStart(item.id, event)} + onPointerMove={handleLongPressMove} + onPointerUp={handleLongPressEnd} animate={ showCellWarning ? { @@ -372,6 +391,12 @@ export function DesktopAnimal({ ) : null} + {longPressCellId === item.id ? ( + + ) : null} ) })} diff --git a/src/features/game/components/desktop/desktop-control.tsx b/src/features/game/components/desktop/desktop-control.tsx index 57b3820..8b9bbc9 100644 --- a/src/features/game/components/desktop/desktop-control.tsx +++ b/src/features/game/components/desktop/desktop-control.tsx @@ -1,7 +1,6 @@ import { motion } from 'motion/react' import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import reduce from '@/assets/game/add.webp' import arrow from '@/assets/game/arrow.webp' import chipBg from '@/assets/game/chip-bg.webp' import chipLineBg from '@/assets/game/chip-line-bg.webp' @@ -10,7 +9,6 @@ import confirmBg from '@/assets/game/confirm-bg.webp' import confirmRedBg from '@/assets/game/confirm-red-bg.png' import controlBg from '@/assets/game/control-bg.png' import leftBottomBg from '@/assets/game/left-bg.webp' -import add from '@/assets/game/reduce.webp' import totalBg from '@/assets/game/total-bg.webp' import diamond from '@/assets/system/diamond.webp' import { SmartBackground } from '@/components/smart-background.tsx' @@ -27,8 +25,6 @@ export function DesktopControl() { acceptingBets, actionsEnabled, canClear, - canDecreaseBetQuantity, - canIncreaseBetQuantity, chips, confirmLabel, confirmState, @@ -37,11 +33,8 @@ export function DesktopControl() { onChipSelect, onConfirm, onClearSelections, - onDecreaseBetQuantity, - onIncreaseBetQuantity, onOpenAutoSetting, onRepeatSelections, - selectedBetQuantityLabel, selectedChipId, selectedCountLabel, totalBetAmountLabel, @@ -181,7 +174,7 @@ export function DesktopControl() { src={chipLineBg} size="100% 100%" className={ - 'flex min-w-0 flex-1 items-center gap-design-10 overflow-visible' + 'flex min-w-0 flex-1 items-center justify-between overflow-visible' } > {chips.map((chip) => { @@ -338,52 +331,6 @@ export function DesktopControl() { ) })} - -
- -
- {selectedBetQuantityLabel} -
- -
handleSelect(item.id)} + onContextMenu={(event) => event.preventDefault()} + onDragStart={(event) => event.preventDefault()} + onKeyDown={(event) => { + if (event.key === 'Delete' || event.key === 'Backspace') { + event.preventDefault() + handleClearCell(item.id) + } + }} + onPointerCancel={handleLongPressCancel} + onPointerDown={(event) => handleLongPressStart(item.id, event)} + onPointerMove={handleLongPressMove} + onPointerUp={handleLongPressEnd} animate={ showCellWarning ? { @@ -238,7 +258,7 @@ export function MobileAnimal({ : { duration: 0.16, ease: 'easeOut' } } className={cn( - 'relative flex h-design-36 flex-col items-center justify-center rounded-[calc(var(--design-unit)*6)] border border-transparent transition-[transform,border-color,box-shadow,opacity] duration-150', + 'mobile-animal-touch-target relative flex h-design-36 flex-col items-center justify-center rounded-[calc(var(--design-unit)*6)] border border-transparent transition-[transform,border-color,box-shadow,opacity] duration-150', !isRevealActive && 'overflow-hidden', lockInteraction ? 'cursor-not-allowed opacity-90' @@ -376,6 +396,13 @@ export function MobileAnimal({ ) : null} + {longPressCellId === item.id ? ( + + ) : null} ) })} diff --git a/src/features/game/components/mobile/mobile-control.tsx b/src/features/game/components/mobile/mobile-control.tsx index f23ef2c..95c361f 100644 --- a/src/features/game/components/mobile/mobile-control.tsx +++ b/src/features/game/components/mobile/mobile-control.tsx @@ -1,17 +1,14 @@ import { motion } from 'motion/react' import { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import reduce from '@/assets/game/add.webp' import chipBg from '@/assets/game/chip-bg.webp' import chipLineBg from '@/assets/game/chip-line-bg.webp' import chipLock from '@/assets/game/chip-lock.webp' import confirmRedBg from '@/assets/game/confirm-red-bg.png' import controlBg from '@/assets/game/control-bg.png' import leftBottomBg from '@/assets/game/left-bg.webp' -import mobileAddReduceBg from '@/assets/game/mobile-add-reduce-bg.webp' import mobileConfirmBg from '@/assets/game/mobile-contro-comfirm.webp' import mobileTotalBg from '@/assets/game/mobile-control-number.webp' -import add from '@/assets/game/reduce.webp' import diamond from '@/assets/system/diamond.webp' import { SmartBackground } from '@/components/smart-background.tsx' import { SmartImage } from '@/components/smart-image.tsx' @@ -27,8 +24,6 @@ export function MobileControl() { acceptingBets, actionsEnabled, canClear, - canDecreaseBetQuantity, - canIncreaseBetQuantity, chips, confirmLabel, confirmState, @@ -37,11 +32,8 @@ export function MobileControl() { onChipSelect, onConfirm, onClearSelections, - onDecreaseBetQuantity, - onIncreaseBetQuantity, onOpenAutoSetting, onRepeatSelections, - selectedBetQuantityLabel, selectedChipId, selectedCountLabel, totalBetAmountLabel, @@ -154,7 +146,7 @@ export function MobileControl() { {chips.map((chip) => { const isSelected = chip.id === selectedChipId @@ -287,50 +279,6 @@ export function MobileControl() { })} - - - -
- {selectedBetQuantityLabel} -
- -
diff --git a/src/features/game/components/mobile/mobile-status.tsx b/src/features/game/components/mobile/mobile-status.tsx index 8490d70..46e3f99 100644 --- a/src/features/game/components/mobile/mobile-status.tsx +++ b/src/features/game/components/mobile/mobile-status.tsx @@ -15,7 +15,7 @@ import { DesktopCountdown } from '@/features/game/components/desktop/desktop-cou import { useGameStatusVm } from '@/hooks/use-game-status-vm.ts' import { cn } from '@/lib/utils.ts' -const FORCE_MOBILE_STREAK_EFFECT_PREVIEW = true +const FORCE_MOBILE_STREAK_EFFECT_PREVIEW = false function isIosDevice() { if (typeof navigator === 'undefined') { diff --git a/src/features/game/components/shared/long-press-progress.tsx b/src/features/game/components/shared/long-press-progress.tsx new file mode 100644 index 0000000..44ed592 --- /dev/null +++ b/src/features/game/components/shared/long-press-progress.tsx @@ -0,0 +1,77 @@ +import { motion } from 'motion/react' +import { cn } from '@/lib/utils' + +interface LongPressProgressProps { + compact?: boolean + durationMs: number + label: string +} + +export function LongPressProgress({ + compact = false, + durationMs, + label, +}: LongPressProgressProps) { + return ( +