diff --git a/package.json b/package.json index a350147..07f8e65 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.76.2", + "version": "1.77.0", "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": { diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index acd1bb1..273eb5c 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -4110,38 +4110,34 @@ export default function WeeklyView() { // 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 touchMoveDragHandlerRef = 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 (touchMoveDragHandlerRef.current) { + document.removeEventListener('touchmove', touchMoveDragHandlerRef.current); + touchMoveDragHandlerRef.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; - - const touch = e.touches[0]; - if (!lp.activated) { - // Before long-press fires: cancel if finger moves too much (scrolling) - if (Math.abs(touch.clientX - lp.startX) > 10 || Math.abs(touch.clientY - lp.startY) > 10) { - clearTimeout(lp.timerId); - touchLongPressRef.current = null; - cleanupTouchListeners(); - } - return; - } + // Called when long-press activates: swap passive cancel-listener for non-passive drag-listener + const upgradeToDragListeners = useCallback(() => { + if (touchMoveHandlerRef.current) { + document.removeEventListener('touchmove', touchMoveHandlerRef.current); + touchMoveHandlerRef.current = null; + } + const handleDragMove = (e: TouchEvent) => { // Long-press active: prevent scrolling and track slot under finger e.preventDefault(); + const touch = e.touches[0]; const el = document.elementFromPoint(touch.clientX, touch.clientY); const slotEl = el?.closest('[data-slot]') as HTMLElement | null; if (slotEl) { @@ -4158,6 +4154,24 @@ export default function WeeklyView() { } } }; + touchMoveDragHandlerRef.current = handleDragMove; + document.addEventListener('touchmove', handleDragMove, { passive: false }); + }, []); + + const attachTouchListeners = useCallback(() => { + cleanupTouchListeners(); + + // Phase 1: passive listener — only cancels long-press if finger moves (no scroll blocking) + const handlePassiveTouchMove = (e: TouchEvent) => { + const lp = touchLongPressRef.current; + if (!lp || lp.activated) return; + const touch = e.touches[0]; + if (Math.abs(touch.clientX - lp.startX) > 10 || Math.abs(touch.clientY - lp.startY) > 10) { + clearTimeout(lp.timerId); + touchLongPressRef.current = null; + cleanupTouchListeners(); + } + }; const handleTouchEnd = () => { const lp = touchLongPressRef.current; @@ -4194,9 +4208,9 @@ export default function WeeklyView() { }); }; - touchMoveHandlerRef.current = handleTouchMove; + touchMoveHandlerRef.current = handlePassiveTouchMove; touchEndHandlerRef.current = handleTouchEnd; - document.addEventListener('touchmove', handleTouchMove, { passive: false }); + document.addEventListener('touchmove', handlePassiveTouchMove, { passive: true }); document.addEventListener('touchend', handleTouchEnd); document.addEventListener('touchcancel', handleTouchEnd); }, [cleanupTouchListeners]); @@ -6827,7 +6841,7 @@ export default function WeeklyView() { {/* CENTER SECTION: Week/Year, Goal, Focus Mode - Reveal on Hover */} -
+
{/* Week & Year */}
{/* Clickable Week & Year */} @@ -8092,6 +8106,8 @@ export default function WeeklyView() { if (touchLongPressRef.current) { touchLongPressRef.current.activated = true; } + // Upgrade from passive to non-passive touchmove now that drag is active + upgradeToDragListeners(); const ds = `${slotDate.getFullYear()}-${String(slotDate.getMonth() + 1).padStart(2, '0')}-${String(slotDate.getDate()).padStart(2, '0')}`; setSlotDragSelection({ dateStr: ds, startSlot: slotName, endSlot: slotName }); }, 500);