From ee77f38cdb324cbcf12518490df77fc9e6b89282 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 6 Nov 2025 22:52:02 +0000 Subject: Improve gallery scroll indicators and format code Co-authored-by: arielcostas <94913521+arielcostas@users.noreply.github.com> --- src/frontend/app/components/PullToRefresh.tsx | 169 +++++++++++++++----------- 1 file changed, 95 insertions(+), 74 deletions(-) (limited to 'src/frontend/app/components/PullToRefresh.tsx') diff --git a/src/frontend/app/components/PullToRefresh.tsx b/src/frontend/app/components/PullToRefresh.tsx index 9def8f5..d5ea51b 100644 --- a/src/frontend/app/components/PullToRefresh.tsx +++ b/src/frontend/app/components/PullToRefresh.tsx @@ -27,75 +27,97 @@ export const PullToRefresh: React.FC = ({ const rotate = useTransform(y, [0, threshold], [0, 180]); const isAtPageTop = useCallback(() => { - const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; + const scrollTop = + window.pageYOffset || + document.documentElement.scrollTop || + document.body.scrollTop || + 0; return scrollTop <= 10; // Increased tolerance to 10px }, []); - const handleTouchStart = useCallback((e: TouchEvent) => { - // Very strict check - must be at absolute top - const windowScroll = window.pageYOffset || window.scrollY || 0; - const htmlScroll = document.documentElement.scrollTop; - const bodyScroll = document.body.scrollTop; - const containerScroll = containerRef.current?.scrollTop || 0; - const parentScroll = containerRef.current?.parentElement?.scrollTop || 0; - const maxScroll = Math.max(windowScroll, htmlScroll, bodyScroll, containerScroll, parentScroll); - - if (maxScroll > 0 || isRefreshing) { - setIsPulling(false); - setIsActive(false); - return; - } - - startY.current = e.touches[0].clientY; - setIsPulling(true); - }, [isRefreshing]); - - const handleTouchMove = useCallback((e: TouchEvent) => { - if (!isPulling) return; - - // Continuously check if we're still at the top during the gesture - const windowScroll = window.pageYOffset || window.scrollY || 0; - const htmlScroll = document.documentElement.scrollTop; - const bodyScroll = document.body.scrollTop; - const containerScroll = containerRef.current?.scrollTop || 0; - const parentScroll = containerRef.current?.parentElement?.scrollTop || 0; - const maxScroll = Math.max(windowScroll, htmlScroll, bodyScroll, containerScroll, parentScroll); - - if (maxScroll > 10) { - // Cancel pull-to-refresh if we've scrolled away from top - setIsPulling(false); - setIsActive(false); - y.set(0); - return; - } + const handleTouchStart = useCallback( + (e: TouchEvent) => { + // Very strict check - must be at absolute top + const windowScroll = window.pageYOffset || window.scrollY || 0; + const htmlScroll = document.documentElement.scrollTop; + const bodyScroll = document.body.scrollTop; + const containerScroll = containerRef.current?.scrollTop || 0; + const parentScroll = containerRef.current?.parentElement?.scrollTop || 0; + const maxScroll = Math.max( + windowScroll, + htmlScroll, + bodyScroll, + containerScroll, + parentScroll, + ); + + if (maxScroll > 0 || isRefreshing) { + setIsPulling(false); + setIsActive(false); + return; + } - const currentY = e.touches[0].clientY; - const pullDistance = currentY - startY.current; + startY.current = e.touches[0].clientY; + setIsPulling(true); + }, + [isRefreshing], + ); - if (pullDistance > 0) { - // Only prevent default when the event is cancelable - if (e.cancelable) { - e.preventDefault(); + const handleTouchMove = useCallback( + (e: TouchEvent) => { + if (!isPulling) return; + + // Continuously check if we're still at the top during the gesture + const windowScroll = window.pageYOffset || window.scrollY || 0; + const htmlScroll = document.documentElement.scrollTop; + const bodyScroll = document.body.scrollTop; + const containerScroll = containerRef.current?.scrollTop || 0; + const parentScroll = containerRef.current?.parentElement?.scrollTop || 0; + const maxScroll = Math.max( + windowScroll, + htmlScroll, + bodyScroll, + containerScroll, + parentScroll, + ); + + if (maxScroll > 10) { + // Cancel pull-to-refresh if we've scrolled away from top + setIsPulling(false); + setIsActive(false); + y.set(0); + return; } - const dampedDistance = Math.min(pullDistance * 0.5, threshold * 1.2); - y.set(dampedDistance); + const currentY = e.touches[0].clientY; + const pullDistance = currentY - startY.current; - if (dampedDistance >= threshold && !isActive) { - setIsActive(true); - // Only vibrate if user activation is available and vibrate is supported - if (navigator.vibrate && navigator.userActivation?.hasBeenActive) { - navigator.vibrate(50); + if (pullDistance > 0) { + // Only prevent default when the event is cancelable + if (e.cancelable) { + e.preventDefault(); } - } else if (dampedDistance < threshold && isActive) { + + const dampedDistance = Math.min(pullDistance * 0.5, threshold * 1.2); + y.set(dampedDistance); + + if (dampedDistance >= threshold && !isActive) { + setIsActive(true); + // Only vibrate if user activation is available and vibrate is supported + if (navigator.vibrate && navigator.userActivation?.hasBeenActive) { + navigator.vibrate(50); + } + } else if (dampedDistance < threshold && isActive) { + setIsActive(false); + } + } else { + // Reset if pulling up + y.set(0); setIsActive(false); } - } else { - // Reset if pulling up - y.set(0); - setIsActive(false); - } - }, [isPulling, threshold, isActive, y]); + }, + [isPulling, threshold, isActive, y], + ); const handleTouchEnd = useCallback(async () => { if (!isPulling) return; @@ -106,7 +128,7 @@ export const PullToRefresh: React.FC = ({ try { await onRefresh(); } catch (error) { - console.error('Refresh failed:', error); + console.error("Refresh failed:", error); } } @@ -121,14 +143,18 @@ export const PullToRefresh: React.FC = ({ if (!container) return; // Use passive: false for touchmove to allow preventDefault - container.addEventListener('touchstart', handleTouchStart, { passive: true }); - container.addEventListener('touchmove', handleTouchMove, { passive: false }); - container.addEventListener('touchend', handleTouchEnd, { passive: true }); + container.addEventListener("touchstart", handleTouchStart, { + passive: true, + }); + container.addEventListener("touchmove", handleTouchMove, { + passive: false, + }); + container.addEventListener("touchend", handleTouchEnd, { passive: true }); return () => { - container.removeEventListener('touchstart', handleTouchStart); - container.removeEventListener('touchmove', handleTouchMove); - container.removeEventListener('touchend', handleTouchEnd); + container.removeEventListener("touchstart", handleTouchStart); + container.removeEventListener("touchmove", handleTouchMove); + container.removeEventListener("touchend", handleTouchEnd); }; }, [handleTouchStart, handleTouchMove, handleTouchEnd]); @@ -136,25 +162,20 @@ export const PullToRefresh: React.FC = ({
{/* Simple indicator */} {isPulling && ( - + )} {/* Normal content - no transform interference */} -
- {children} -
+
{children}
); }; -- cgit v1.3