Vibro call-back for drag & Drop (does not work in Firefox). New chart - Number of Workouts.
This commit is contained in:
@@ -68,12 +68,67 @@ const SortablePlanStep: React.FC<SortablePlanStepProps> = ({ step, index, toggle
|
||||
position: 'relative' as 'relative',
|
||||
};
|
||||
|
||||
const handlePointerDown = (e: React.PointerEvent) => {
|
||||
listeners?.onPointerDown?.(e);
|
||||
|
||||
// Only trigger vibration for touch input (long press logic)
|
||||
if (e.pointerType === 'touch') {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Use pattern [0, 300, 50] to vibrate after 300ms delay, triggered synchronously by user gesture
|
||||
// This works around Firefox Android blocking async vibrate calls
|
||||
if (typeof navigator !== 'undefined' && navigator.vibrate) {
|
||||
try {
|
||||
navigator.vibrate([0, 300, 50]);
|
||||
} catch (err) {
|
||||
// Ignore potential errors if vibrate is blocked or invalid
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup / Cancel logic
|
||||
const cancelVibration = () => {
|
||||
// Only cancel if less than 300ms has passed (meaning we aborted the long press)
|
||||
// If > 300ms, the vibration (50ms) is either playing or done, we let it finish.
|
||||
if (Date.now() - startTime < 300) {
|
||||
if (typeof navigator !== 'undefined' && navigator.vibrate) {
|
||||
navigator.vibrate(0);
|
||||
}
|
||||
}
|
||||
cleanup();
|
||||
};
|
||||
|
||||
const startX = e.clientX;
|
||||
const startY = e.clientY;
|
||||
|
||||
const onMove = (me: PointerEvent) => {
|
||||
const diff = Math.hypot(me.clientX - startX, me.clientY - startY);
|
||||
if (diff > 10) { // 10px tolerance
|
||||
cancelVibration();
|
||||
}
|
||||
};
|
||||
|
||||
const cleanup = () => {
|
||||
window.removeEventListener('pointermove', onMove);
|
||||
window.removeEventListener('pointerup', cancelVibration);
|
||||
window.removeEventListener('pointercancel', cancelVibration);
|
||||
};
|
||||
|
||||
window.addEventListener('pointermove', onMove);
|
||||
window.addEventListener('pointerup', cancelVibration);
|
||||
window.addEventListener('pointercancel', cancelVibration);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={setNodeRef} style={style} {...attributes}>
|
||||
<Card
|
||||
className={`flex items-center gap-3 transition-all hover:bg-surface-container-high ${isDragging ? 'bg-surface-container-high shadow-elevation-3' : ''}`}
|
||||
>
|
||||
<div className="text-on-surface-variant p-1 cursor-grab touch-none" {...listeners}>
|
||||
<div
|
||||
className="text-on-surface-variant p-1 cursor-grab touch-none"
|
||||
{...listeners}
|
||||
onPointerDown={handlePointerDown}
|
||||
>
|
||||
<GripVertical size={20} />
|
||||
</div>
|
||||
|
||||
@@ -136,17 +191,19 @@ const Plans: React.FC<PlansProps> = ({ lang }) => {
|
||||
|
||||
// Dnd Sensors
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor), // Handle mouse and basic pointer events
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
useSensor(MouseSensor, {
|
||||
activationConstraint: {
|
||||
distance: 10,
|
||||
},
|
||||
}),
|
||||
useSensor(TouchSensor, {
|
||||
// Small delay or tolerance can help distinguish scrolling from dragging,
|
||||
// but usually for a handle drag, instant is fine or defaults work.
|
||||
// Let's add a small activation constraint to prevent accidental drags while scrolling if picking by handle
|
||||
activationConstraint: {
|
||||
distance: 5,
|
||||
delay: 300,
|
||||
tolerance: 5,
|
||||
},
|
||||
}),
|
||||
useSensor(KeyboardSensor, {
|
||||
coordinateGetter: sortableKeyboardCoordinates,
|
||||
})
|
||||
);
|
||||
|
||||
@@ -288,6 +345,16 @@ const Plans: React.FC<PlansProps> = ({ lang }) => {
|
||||
setSteps(steps.filter(s => s.id !== stepId));
|
||||
};
|
||||
|
||||
/* Vibration handled in SortablePlanStep locally for better touch support */
|
||||
/*
|
||||
const handleDragStart = () => {
|
||||
console.log('handleDragStart called');
|
||||
if (typeof navigator !== 'undefined' && navigator.vibrate) {
|
||||
navigator.vibrate(50);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
const handleDragEnd = (event: DragEndEvent) => {
|
||||
const { active, over } = event;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user