fix(galaxy): un deuxième doigt annule le glisser d'une personne

Au passage à deux doigts (ou en cas d'interruption tactile), le glisser en
cours est annulé et la personne revient à sa place : plus d'enregistrement
pendant un pincement. Un doigt qui reste après un pincement ne saisit plus
de personne, il ne fait que déplacer l'arbre.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
IliesAllaliandClaude Opus 5.5 committed 2026-10-16 18:13:52 +02:00
1 parent b27b5e9737
commit 8fa2808b5d
2 files changed
+30 -7

No files matched your search

+6 -4
View File
@@ -119,7 +119,7 @@ const Galaxy = ({ onPersonSelect, onMediaSelect, onPersonPositionChange, editMod
const {
isDragging, isZooming, zoomTimeoutRef, hasDragged,
handleMouseDown, handleMouseMove, handleMouseUp,
handleMouseDown, handleMouseMove, handleMouseUp, cancelPersonDrag,
handleMouseLeave, handleWheel, handleClick,
} = useGalaxyInteractions({
canvasRef, transformRef, targetTransformRef,
@@ -706,7 +706,8 @@ const Galaxy = ({ onPersonSelect, onMediaSelect, onPersonPositionChange, editMod
handleMouseDown({ clientX: t.clientX, clientY: t.clientY, preventDefault: () => e.preventDefault() })
} else if (e.touches.length === 2) {
e.preventDefault()
// Stop any ongoing single-finger pan before starting pinch
// Un second doigt annule le glisser d'une personne (rien n'est enregistré) puis arrête le pan
cancelPersonDrag()
handleMouseUp()
const [a, b] = e.touches
const dx = a.clientX - b.clientX
@@ -744,15 +745,16 @@ const Galaxy = ({ onPersonSelect, onMediaSelect, onPersonPositionChange, editMod
// and mark hasDragged=true so the lift doesn't fire an accidental click
const t = e.touches[0]
handleMouseUp()
handleMouseDown({ clientX: t.clientX, clientY: t.clientY, preventDefault: () => e.preventDefault() })
handleMouseDown({ clientX: t.clientX, clientY: t.clientY, preventDefault: () => e.preventDefault() }, { panOnly: true })
hasDragged.current = true
} else {
handleMouseUp()
}
}}
onTouchCancel={() => {
// System interruption (notification, keyboard, etc.) — reset all touch state
// System interruption (notification, keyboard, etc.) — reset all touch state, sans enregistrer de position
pinchRef.current = null
cancelPersonDrag()
handleMouseUp()
}}
onClick={handleClick}
@@ -50,7 +50,8 @@ export function useGalaxyInteractions({
}
}, [canvasRef, transformRef])
const handleMouseDown = useCallback((e) => {
// panOnly : un doigt qui reste après un pincement ne saisit pas de personne, il ne fait que déplacer l'arbre
const handleMouseDown = useCallback((e, { panOnly = false } = {}) => {
const ah = annotationHandlers
const worldPos = getWorldPos(e)
@@ -72,7 +73,7 @@ export function useGalaxyInteractions({
}
}
if (editModeActive && (!ah || ah.activeTool === 'pointer') && worldPos && layoutDataRef.current) {
if (editModeActive && !panOnly && (!ah || ah.activeTool === 'pointer') && worldPos && layoutDataRef.current) {
const now = performance.now()
for (let index = layoutDataRef.current.children.length - 1; index >= 0; index -= 1) {
const node = layoutDataRef.current.children[index]
@@ -86,6 +87,10 @@ export function useGalaxyInteractions({
offsetY: worldPos.y - pos.cy,
startClientX: e.clientX,
startClientY: e.clientY,
// Place d'origine, pour un glisser annulé (second doigt, interruption)
originX: node.x,
originY: node.y,
originManual: node._manualPosition,
}
hoveredNodeIdRef.current = node.id
hasDragged.current = false
@@ -257,6 +262,22 @@ export function useGalaxyInteractions({
}
}, [handleGlobalMouseUp])
// Annule le glisser d'une personne sans rien enregistrer : la personne revient à sa place d'avant
const cancelPersonDrag = useCallback(() => {
const drag = draggedPersonRef.current
if (!drag) return
draggedPersonRef.current = null
const { node, originX, originY, originManual } = drag
node.x = originX
node.y = originY
node._manualPosition = originManual
if (typeof window !== 'undefined') {
window.removeEventListener('mouseup', handleGlobalMouseUp)
}
hoveredNodeIdRef.current = node.id
setCanvasCursor(canvasRef, editModeActive ? CURSOR_NODE_GRAB : CURSOR_POINTER)
}, [canvasRef, hoveredNodeIdRef, editModeActive, handleGlobalMouseUp])
const handleMouseLeave = useCallback(() => {
isDragging.current = false
annotationDragging.current = false
@@ -366,6 +387,6 @@ export function useGalaxyInteractions({
return {
isDragging, isZooming, zoomTimeoutRef, hasDragged,
handleMouseDown, handleMouseMove, handleMouseUp,
handleMouseLeave, handleWheel, handleClick,
handleMouseLeave, handleWheel, handleClick, cancelPersonDrag,
}
}