From 857541fb948b1596d25b43769017c795d0f235e2 Mon Sep 17 00:00:00 2001 From: Egor Date: Thu, 22 Jan 2026 23:32:17 +0300 Subject: [PATCH] Update usePullToRefresh.ts --- src/hooks/usePullToRefresh.ts | 59 +++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/hooks/usePullToRefresh.ts b/src/hooks/usePullToRefresh.ts index b97b83e..bd98115 100644 --- a/src/hooks/usePullToRefresh.ts +++ b/src/hooks/usePullToRefresh.ts @@ -35,16 +35,66 @@ export function usePullToRefresh({ useEffect(() => { if (disabled) return + // Check if a modal/overlay is currently open + const isModalOpen = (): boolean => { + // Check if body scroll is locked (common pattern for modals) + if (document.body.style.overflow === 'hidden') return true + // Check for high z-index fixed elements (modals typically use z-index > 50) + const fixedElements = document.querySelectorAll('[style*="position: fixed"], [style*="position:fixed"]') + for (const el of fixedElements) { + const style = window.getComputedStyle(el) + const zIndex = parseInt(style.zIndex, 10) + if (zIndex >= 50 && el.clientHeight > window.innerHeight * 0.5) { + return true + } + } + return false + } + + // Check if element or any parent is scrollable and not at top + const isInsideScrollableContainer = (element: HTMLElement | null): boolean => { + while (element && element !== document.body) { + const style = window.getComputedStyle(element) + const overflowY = style.overflowY + const isScrollable = overflowY === 'auto' || overflowY === 'scroll' + + if (isScrollable && element.scrollHeight > element.clientHeight) { + // Element is scrollable - check if it's at the top + if (element.scrollTop > 0) { + return true // Not at top, don't trigger pull-to-refresh + } + } + element = element.parentElement + } + return false + } + const handleTouchStart = (e: TouchEvent) => { + // Don't trigger if a modal is open + if (isModalOpen()) return + // Only trigger if at top of page if (window.scrollY > 5) return + // Don't trigger if touch started inside a scrollable container that's not at top + const target = e.target as HTMLElement + if (isInsideScrollableContainer(target)) return + startY.current = e.touches[0].clientY currentY.current = e.touches[0].clientY } const handleTouchMove = (e: TouchEvent) => { if (startY.current === 0) return + + // Cancel if modal opened during gesture + if (isModalOpen()) { + startY.current = 0 + setPullDistance(0) + setIsPulling(false) + return + } + if (window.scrollY > 5) { // User scrolled down, reset startY.current = 0 @@ -53,6 +103,15 @@ export function usePullToRefresh({ return } + // Also check during move - user might start at top then scroll inside container + const target = e.target as HTMLElement + if (isInsideScrollableContainer(target)) { + startY.current = 0 + setPullDistance(0) + setIsPulling(false) + return + } + currentY.current = e.touches[0].clientY const diff = currentY.current - startY.current