diff options
| author | copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> | 2025-11-06 22:52:02 +0000 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2025-11-07 10:47:20 +0100 |
| commit | ee77f38cdb324cbcf12518490df77fc9e6b89282 (patch) | |
| tree | 407f64a434291e1e375e6a1ccb55f59fa886a1ef /src/frontend/app/components/PullToRefresh.tsx | |
| parent | e51cdd89afc08274ca622e18b8127feca29e90a3 (diff) | |
Improve gallery scroll indicators and format code
Co-authored-by: arielcostas <94913521+arielcostas@users.noreply.github.com>
Diffstat (limited to 'src/frontend/app/components/PullToRefresh.tsx')
| -rw-r--r-- | src/frontend/app/components/PullToRefresh.tsx | 161 |
1 files changed, 91 insertions, 70 deletions
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<PullToRefreshProps> = ({ 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); + 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; - } + if (maxScroll > 0 || isRefreshing) { + setIsPulling(false); + setIsActive(false); + return; + } - startY.current = e.touches[0].clientY; - setIsPulling(true); - }, [isRefreshing]); + startY.current = e.touches[0].clientY; + setIsPulling(true); + }, + [isRefreshing], + ); - const handleTouchMove = useCallback((e: TouchEvent) => { - if (!isPulling) return; + 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); + // 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; - } + if (maxScroll > 10) { + // Cancel pull-to-refresh if we've scrolled away from top + setIsPulling(false); + setIsActive(false); + y.set(0); + return; + } - const currentY = e.touches[0].clientY; - const pullDistance = currentY - startY.current; + const currentY = e.touches[0].clientY; + const pullDistance = currentY - startY.current; - if (pullDistance > 0) { - // Only prevent default when the event is cancelable - if (e.cancelable) { - e.preventDefault(); - } + if (pullDistance > 0) { + // Only prevent default when the event is cancelable + if (e.cancelable) { + e.preventDefault(); + } - const dampedDistance = Math.min(pullDistance * 0.5, threshold * 1.2); - y.set(dampedDistance); + 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); + 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 if (dampedDistance < threshold && isActive) { + } 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<PullToRefreshProps> = ({ try { await onRefresh(); } catch (error) { - console.error('Refresh failed:', error); + console.error("Refresh failed:", error); } } @@ -121,14 +143,18 @@ export const PullToRefresh: React.FC<PullToRefreshProps> = ({ 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<PullToRefreshProps> = ({ <div className="pull-to-refresh-container" ref={containerRef}> {/* Simple indicator */} {isPulling && ( - <motion.div - className="pull-to-refresh-indicator" - style={{ opacity }} - > + <motion.div className="pull-to-refresh-indicator" style={{ opacity }}> <motion.div - className={`refresh-icon-container ${isActive ? 'active' : ''}`} + className={`refresh-icon-container ${isActive ? "active" : ""}`} style={{ scale, rotate: isRefreshing ? 0 : rotate }} > <RefreshCw - className={`refresh-icon ${isRefreshing ? 'spinning' : ''}`} + className={`refresh-icon ${isRefreshing ? "spinning" : ""}`} /> </motion.div> </motion.div> )} {/* Normal content - no transform interference */} - <div className="pull-to-refresh-content"> - {children} - </div> + <div className="pull-to-refresh-content">{children}</div> </div> ); }; |
