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<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);
-
-    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<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>
   );
 };
-- 
cgit v1.3

