fix(mobile): Symbol-Tap auf dem Handy zuverlässig – TouchBackend schluckte onClick (v1.5.2)
Ursache: react-dnd TouchBackend (delayTouchStart:150) unterdrückt auf Touch- Geräten den onClick der Drag-Quelle → Tap-to-place löste auf dem Handy nie aus, und echtes Touch-Drag über die MapLibre-Karte ist ohnehin unzuverlässig. - DraggableSymbol erkennt Taps jetzt über echte Touch-Events (onTouchStart/End): kurzer, ortsfester Tipp (<12px, <600ms) = Auswahl → Karte antippen platziert - preventDefault verhindert Doppel-Auslösung durch den synthetischen Klick - onClick bleibt für Desktop/Maus erhalten Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "lageplan",
|
"name": "lageplan",
|
||||||
"version": "1.5.1",
|
"version": "1.5.2",
|
||||||
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
"description": "Feuerwehr Lageplan - Krokier-App für Einsatzdokumentation",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState, useEffect } from 'react'
|
import { useState, useEffect, useRef } from 'react'
|
||||||
import { useDrag } from 'react-dnd'
|
import { useDrag } from 'react-dnd'
|
||||||
import { getEmptyImage } from 'react-dnd-html5-backend'
|
import { getEmptyImage } from 'react-dnd-html5-backend'
|
||||||
import { Input } from '@/components/ui/input'
|
import { Input } from '@/components/ui/input'
|
||||||
@@ -76,10 +76,34 @@ function DraggableSymbol({ symbol, canEdit, onSelect }: {
|
|||||||
preview(getEmptyImage(), { captureDraggingState: true })
|
preview(getEmptyImage(), { captureDraggingState: true })
|
||||||
}, [preview])
|
}, [preview])
|
||||||
|
|
||||||
|
// Touch-Tap eigenständig erkennen: der TouchBackend (react-dnd) schluckt auf
|
||||||
|
// dem Handy den onClick der Drag-Quelle. Ohne diesen Handler würde Tap-to-place
|
||||||
|
// auf Mobil gar nicht auslösen. Ein kurzer Tipp ohne Bewegung = Auswahl.
|
||||||
|
const touchStartRef = useRef<{ x: number; y: number; t: number } | null>(null)
|
||||||
|
|
||||||
|
const handleTouchStart = (e: React.TouchEvent) => {
|
||||||
|
const t = e.touches[0]
|
||||||
|
touchStartRef.current = { x: t.clientX, y: t.clientY, t: Date.now() }
|
||||||
|
}
|
||||||
|
const handleTouchEnd = (e: React.TouchEvent) => {
|
||||||
|
const start = touchStartRef.current
|
||||||
|
touchStartRef.current = null
|
||||||
|
if (!start || !canEdit || !onSelect) return
|
||||||
|
const t = e.changedTouches[0]
|
||||||
|
const moved = Math.hypot(t.clientX - start.x, t.clientY - start.y)
|
||||||
|
// Kurzer, ortsfester Tipp → als Auswahl werten (kein Drag)
|
||||||
|
if (moved < 12 && Date.now() - start.t < 600) {
|
||||||
|
e.preventDefault() // verhindert den synthetischen Klick (kein Doppel-Auslösen)
|
||||||
|
onSelect(symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={drag as unknown as React.LegacyRef<HTMLDivElement>}
|
ref={drag as unknown as React.LegacyRef<HTMLDivElement>}
|
||||||
onClick={() => { if (canEdit && onSelect) onSelect(symbol) }}
|
onClick={() => { if (canEdit && onSelect) onSelect(symbol) }}
|
||||||
|
onTouchStart={handleTouchStart}
|
||||||
|
onTouchEnd={handleTouchEnd}
|
||||||
className={`
|
className={`
|
||||||
flex flex-col items-center gap-1 p-1.5 md:p-2 lg:p-2.5 rounded-lg border-2 transition-all
|
flex flex-col items-center gap-1 p-1.5 md:p-2 lg:p-2.5 rounded-lg border-2 transition-all
|
||||||
border-transparent hover:border-border hover:bg-accent
|
border-transparent hover:border-border hover:bg-accent
|
||||||
|
|||||||
Reference in New Issue
Block a user