From e7724b0bf5365120fe6124804c86b113b6309f5c Mon Sep 17 00:00:00 2001 From: pory-gone <83127821+pory-gone@users.noreply.github.com> Date: Wed, 26 Nov 2025 19:16:11 +0100 Subject: [PATCH 1/2] fix_refresh_android_pwa --- components/pull-to-refresh.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/components/pull-to-refresh.js b/components/pull-to-refresh.js index 1e5150f104..ba3a85a012 100644 --- a/components/pull-to-refresh.js +++ b/components/pull-to-refresh.js @@ -1,6 +1,7 @@ import { useRouter } from 'next/router' import { useState, useRef, useEffect, useCallback, useMemo } from 'react' import styles from './pull-to-refresh.module.css' +import NProgress from 'nprogress' const REFRESH_THRESHOLD = 150 @@ -41,7 +42,7 @@ export default function PullToRefresh ({ children, className }) { clearPullDistance() return } - + e.preventDefault() touchEndY.current = e.touches[0].clientY const distance = touchEndY.current - touchStartY.current setPullDistance(distance) @@ -51,7 +52,8 @@ export default function PullToRefresh ({ children, className }) { const handleTouchEnd = useCallback(() => { if (touchStartY.current === 0 || touchEndY.current === 0) return if (touchEndY.current - touchStartY.current > REFRESH_THRESHOLD) { - router.push(router.asPath) + NProgress.done() + router.replace(router.asPath) } clearPullDistance() }, [router]) @@ -59,8 +61,8 @@ export default function PullToRefresh ({ children, className }) { useEffect(() => { if (!isPWA) return document.body.style.overscrollBehaviorY = 'contain' - document.addEventListener('touchstart', handleTouchStart) - document.addEventListener('touchmove', handleTouchMove) + document.addEventListener('touchstart', handleTouchStart, { passive: false }) + document.addEventListener('touchmove', handleTouchMove, { passive: false }) document.addEventListener('touchend', handleTouchEnd) return () => { document.body.style.overscrollBehaviorY = '' From 39145a734072506f1f9036cf411d5d21f3972173 Mon Sep 17 00:00:00 2001 From: pory-gone <83127821+pory-gone@users.noreply.github.com> Date: Wed, 26 Nov 2025 20:32:36 +0100 Subject: [PATCH 2/2] fix: prevent native Chrome PTR on slow pull gestures with timeout --- components/pull-to-refresh.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/components/pull-to-refresh.js b/components/pull-to-refresh.js index ba3a85a012..3e2d551e30 100644 --- a/components/pull-to-refresh.js +++ b/components/pull-to-refresh.js @@ -4,6 +4,7 @@ import styles from './pull-to-refresh.module.css' import NProgress from 'nprogress' const REFRESH_THRESHOLD = 150 +const PULL_TIMEOUT = 1500 export default function PullToRefresh ({ children, className }) { const router = useRouter() @@ -11,6 +12,7 @@ export default function PullToRefresh ({ children, className }) { const [isPWA, setIsPWA] = useState(false) const touchStartY = useRef(0) const touchEndY = useRef(0) + const pullTimeoutRef = useRef(null) const checkPWA = () => { const androidPWA = window.matchMedia('(display-mode: standalone)').matches @@ -23,6 +25,10 @@ export default function PullToRefresh ({ children, className }) { document.body.style.marginTop = '0px' touchStartY.current = 0 touchEndY.current = 0 + if (pullTimeoutRef.current) { + clearTimeout(pullTimeoutRef.current) + pullTimeoutRef.current = null + } } useEffect(checkPWA, []) @@ -31,6 +37,9 @@ export default function PullToRefresh ({ children, className }) { // don't handle if the user is not scrolling from the top of the page, is not on a PWA or if we want Android's native PTR if (!isPWA || window.scrollY > 0) return touchStartY.current = e.touches[0].clientY + pullTimeoutRef.current = setTimeout(() => { + clearPullDistance() + }, PULL_TIMEOUT) }, [isPWA]) const handleTouchMove = useCallback((e) => { @@ -42,11 +51,15 @@ export default function PullToRefresh ({ children, className }) { clearPullDistance() return } - e.preventDefault() touchEndY.current = e.touches[0].clientY const distance = touchEndY.current - touchStartY.current - setPullDistance(distance) - document.body.style.marginTop = `${Math.max(0, Math.min(distance / 2, 25))}px` + if (distance > 0) { + e.preventDefault() + setPullDistance(distance) + document.body.style.marginTop = `${Math.max(0, Math.min(distance / 2, 25))}px` + } else { + clearPullDistance() + } }, [isPWA]) const handleTouchEnd = useCallback(() => { @@ -81,9 +94,6 @@ export default function PullToRefresh ({ children, className }) { return (