fix(card-sorting): prevent replaying own movements from server

Fix issue where dragging a card would replay the entire movement
sequence when position updates bounced back from the server:

- Add lastPositionUpdateRef to track when we send position updates
- Set timestamp when sending updates (both real-time and on drop)
- Ignore server position updates for 500ms after sending our own
- Prevents local client from re-applying its own movements

When you drag and drop a card, the position is sent to the server
and broadcast back. This was causing the card to animate through
the entire drag path again. Now we ignore server updates for 500ms
after sending, eliminating the replay while still allowing sync
from other windows.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2025-10-23 15:08:33 -05:00
parent c1bd4cf2e1
commit 308168a7fb
1 changed files with 10 additions and 0 deletions

View File

@ -383,6 +383,9 @@ export function PlayingPhaseDrag() {
initialRotation: number
} | null>(null)
// Track timestamp of last position update we sent to avoid re-applying our own updates
const lastPositionUpdateRef = useRef<number>(0)
// Track card positions and visual states (UI only - not game state)
const [cardStates, setCardStates] = useState<Map<string, CardState>>(new Map())
const [draggingCardId, setDraggingCardId] = useState<string | null>(null)
@ -545,6 +548,11 @@ export function PlayingPhaseDrag() {
if (!state.cardPositions || state.cardPositions.length === 0) return
if (cardStates.size === 0) return
// Ignore server updates for 500ms after we send our own update
// This prevents replaying our own movements when they bounce back from server
const timeSinceOurUpdate = Date.now() - lastPositionUpdateRef.current
if (timeSinceOurUpdate < 500) return
// Check if server positions differ from current positions
let needsUpdate = false
const newStates = new Map(cardStates)
@ -667,6 +675,7 @@ export function PlayingPhaseDrag() {
const now = Date.now()
if (now - lastSyncTimeRef.current > 100) {
lastSyncTimeRef.current = now
lastPositionUpdateRef.current = now
const positions = Array.from(newStates.entries()).map(([id, state]) => ({
cardId: id,
x: state.x,
@ -708,6 +717,7 @@ export function PlayingPhaseDrag() {
rotation: state.rotation,
zIndex: state.zIndex,
}))
lastPositionUpdateRef.current = Date.now()
updateCardPositions(positions)
}
}