fix: restore sticky day headers on mobile
Non-passive touchmove listener was permanently attached to document, breaking browser scroll optimizations. Now only attached during active long-press and removed immediately after. v1.73.1 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
98a47a62de
commit
dd16e5604a
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "my-weekly-todo-list",
|
||||
"version": "1.73.0",
|
||||
"version": "1.73.1",
|
||||
"description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
||||
@ -3969,8 +3969,25 @@ export default function WeeklyView() {
|
||||
};
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// Touch long-press drag-to-create: touchmove + touchend on document
|
||||
useEffect(() => {
|
||||
// Touch long-press drag-to-create: touchmove + touchend handlers
|
||||
// Stored as refs so the onTouchStart can attach/detach them only when needed
|
||||
// (avoids a permanent non-passive touchmove listener that breaks scroll/sticky)
|
||||
const touchMoveHandlerRef = useRef<((e: TouchEvent) => void) | null>(null);
|
||||
const touchEndHandlerRef = useRef<(() => void) | null>(null);
|
||||
const cleanupTouchListeners = useCallback(() => {
|
||||
if (touchMoveHandlerRef.current) {
|
||||
document.removeEventListener('touchmove', touchMoveHandlerRef.current);
|
||||
touchMoveHandlerRef.current = null;
|
||||
}
|
||||
if (touchEndHandlerRef.current) {
|
||||
document.removeEventListener('touchend', touchEndHandlerRef.current);
|
||||
document.removeEventListener('touchcancel', touchEndHandlerRef.current);
|
||||
touchEndHandlerRef.current = null;
|
||||
}
|
||||
}, []);
|
||||
const attachTouchListeners = useCallback(() => {
|
||||
cleanupTouchListeners();
|
||||
|
||||
const handleTouchMove = (e: TouchEvent) => {
|
||||
const lp = touchLongPressRef.current;
|
||||
if (!lp) return;
|
||||
@ -3981,6 +3998,7 @@ export default function WeeklyView() {
|
||||
if (Math.abs(touch.clientX - lp.startX) > 10 || Math.abs(touch.clientY - lp.startY) > 10) {
|
||||
clearTimeout(lp.timerId);
|
||||
touchLongPressRef.current = null;
|
||||
cleanupTouchListeners();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -4010,6 +4028,7 @@ export default function WeeklyView() {
|
||||
clearTimeout(lp.timerId);
|
||||
touchLongPressRef.current = null;
|
||||
}
|
||||
cleanupTouchListeners();
|
||||
|
||||
const drag = slotDragRef.current;
|
||||
slotDragRef.current = null;
|
||||
@ -4038,16 +4057,12 @@ export default function WeeklyView() {
|
||||
});
|
||||
};
|
||||
|
||||
// Use passive: false for touchmove so we can preventDefault after long-press activates
|
||||
touchMoveHandlerRef.current = handleTouchMove;
|
||||
touchEndHandlerRef.current = handleTouchEnd;
|
||||
document.addEventListener('touchmove', handleTouchMove, { passive: false });
|
||||
document.addEventListener('touchend', handleTouchEnd);
|
||||
document.addEventListener('touchcancel', handleTouchEnd);
|
||||
return () => {
|
||||
document.removeEventListener('touchmove', handleTouchMove);
|
||||
document.removeEventListener('touchend', handleTouchEnd);
|
||||
document.removeEventListener('touchcancel', handleTouchEnd);
|
||||
};
|
||||
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
}, [cleanupTouchListeners]);
|
||||
|
||||
// Handle recurring event drag confirm (this/all)
|
||||
const handleRecurringDragConfirm = async (editMode: 'this' | 'future' | 'all') => {
|
||||
@ -7980,6 +7995,7 @@ export default function WeeklyView() {
|
||||
slot: slotName,
|
||||
activated: false,
|
||||
};
|
||||
attachTouchListeners();
|
||||
}}
|
||||
onDragOver={(e) =>
|
||||
!isProtected && !isOccupiedByTask &&
|
||||
|
||||
Loading…
Reference in New Issue
Block a user