fix(simulator): prevent crosshair from activating during wire segment editing on mobile
- Add data-segment-handle attribute to segment handle circles in WireLayer - Skip long-press aiming timer when touch targets segment handle - Add safety checks to cancel pending timer when segment drag starts - Ensure segment drag always takes priority over crosshair activation This fixes the bug where accidentally holding still while dragging a wire segment would activate the crosshair overlay and interrupt the editing workflow.master
parent
52321dffe8
commit
1973b0adbc
|
|
@ -402,6 +402,9 @@ export const SimulatorCanvas = () => {
|
|||
// Any phase that uses aiming: cancel previous timer first
|
||||
if (wireAimingTimerRef.current) { clearTimeout(wireAimingTimerRef.current); wireAimingTimerRef.current = null; }
|
||||
|
||||
// Check if touch is on a segment handle - if so, skip aiming timer (handle drag takes priority)
|
||||
const isOnSegmentHandle = target?.closest('[data-segment-handle]');
|
||||
|
||||
const aimPhase = wireAimingPhaseRef.current;
|
||||
|
||||
// Already in an aiming phase (aiming_start or aiming_end) → touch updates crosshair immediately
|
||||
|
|
@ -415,16 +418,21 @@ export const SimulatorCanvas = () => {
|
|||
|
||||
// wire_started → long press to aim for endpoint, short drag = pan
|
||||
if (aimPhase === 'wire_started') {
|
||||
wireAimingTimerRef.current = setTimeout(() => {
|
||||
wireAimingPhaseRef.current = 'aiming_end';
|
||||
setWireAiming(true);
|
||||
if (navigator.vibrate) navigator.vibrate(30);
|
||||
const world = toWorld(currentTouchRef.current.x, currentTouchRef.current.y);
|
||||
const aimX = world.x;
|
||||
const aimY = world.y + AIMING_OFFSET_Y;
|
||||
setAimPosition({ x: aimX, y: aimY });
|
||||
useSimulatorStore.getState().updateWireInProgress(aimX, aimY);
|
||||
}, AIMING_LONG_PRESS_MS);
|
||||
// Only start aiming timer if NOT on a segment handle
|
||||
if (!isOnSegmentHandle) {
|
||||
wireAimingTimerRef.current = setTimeout(() => {
|
||||
// Double-check: only activate if segment drag hasn't started
|
||||
if (segmentDragRef.current) return;
|
||||
wireAimingPhaseRef.current = 'aiming_end';
|
||||
setWireAiming(true);
|
||||
if (navigator.vibrate) navigator.vibrate(30);
|
||||
const world = toWorld(currentTouchRef.current.x, currentTouchRef.current.y);
|
||||
const aimX = world.x;
|
||||
const aimY = world.y + AIMING_OFFSET_Y;
|
||||
setAimPosition({ x: aimX, y: aimY });
|
||||
useSimulatorStore.getState().updateWireInProgress(aimX, aimY);
|
||||
}, AIMING_LONG_PRESS_MS);
|
||||
}
|
||||
|
||||
isPanningRef.current = true;
|
||||
panStartRef.current = {
|
||||
|
|
@ -479,8 +487,10 @@ export const SimulatorCanvas = () => {
|
|||
}
|
||||
} else {
|
||||
// ── 6. Empty canvas → start pan + long press starts aiming (idle phase only) ──
|
||||
if (aimPhase === 'idle') {
|
||||
if (aimPhase === 'idle' && !isOnSegmentHandle) {
|
||||
wireAimingTimerRef.current = setTimeout(() => {
|
||||
// Double-check: only activate if segment drag hasn't started
|
||||
if (segmentDragRef.current) return;
|
||||
wireAimingPhaseRef.current = 'aiming_start';
|
||||
setWireAiming(true);
|
||||
if (navigator.vibrate) navigator.vibrate(30);
|
||||
|
|
@ -538,6 +548,11 @@ export const SimulatorCanvas = () => {
|
|||
|
||||
// ── Segment drag (wire editing) via touch ──
|
||||
if (segmentDragRef.current) {
|
||||
// Cancel any pending aiming timer - segment drag takes priority
|
||||
if (wireAimingTimerRef.current) {
|
||||
clearTimeout(wireAimingTimerRef.current);
|
||||
wireAimingTimerRef.current = null;
|
||||
}
|
||||
const world = toWorld(touch.clientX, touch.clientY);
|
||||
const sd = segmentDragRef.current;
|
||||
sd.isDragging = true;
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ export const WireLayer: React.FC<WireLayerProps> = ({
|
|||
stroke="#007acc"
|
||||
strokeWidth={sw}
|
||||
style={{ pointerEvents: 'all', cursor: handle.axis === 'horizontal' ? 'ns-resize' : 'ew-resize', touchAction: 'none' }}
|
||||
data-segment-handle={handle.segIndex}
|
||||
onMouseDown={(e) => onHandleMouseDown(e, handle.segIndex)}
|
||||
onTouchStart={(e) => onHandleTouchStart?.(e, handle.segIndex)}
|
||||
/>
|
||||
|
|
|
|||
Loading…
Reference in New Issue