From ee39cf865107d991c4ac7f2e15e4819544dd3e21 Mon Sep 17 00:00:00 2001 From: thislight Date: Wed, 9 Oct 2024 14:51:32 +0800 Subject: [PATCH] PullDownToRefresh: fix trigger many refreshings This commit fixes that the wheel event path may trigger too many refreshings. --- src/timelines/PullDownToRefresh.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/timelines/PullDownToRefresh.tsx b/src/timelines/PullDownToRefresh.tsx index ccf8294..3343027 100644 --- a/src/timelines/PullDownToRefresh.tsx +++ b/src/timelines/PullDownToRefresh.tsx @@ -28,11 +28,13 @@ const PullDownToRefresh: Component<{ let rootElement: HTMLDivElement; const [pullDown, setPullDown] = createSignal(0); - const pullDownDistance = () => { + const stopPos = () => 160 + + const indicatorOfsY = () => { if (props.loading) { - return 140; + return stopPos() * 0.875; } - return Math.max(Math.min(160, pullDown()), 0); + return pullDown(); }; const obvx = createVisibilityObserver({ @@ -55,7 +57,7 @@ const PullDownToRefresh: Component<{ const vspring = holding ? 0 : K * x * dt; v = ds / dt - vspring; - setPullDown(x + v * dt); + setPullDown(Math.max(Math.min(x + v * dt, stopPos()), 0)); if (Math.abs(x) > 1 || Math.abs(v) > 1) { requestAnimationFrame(updatePullDown); @@ -66,12 +68,11 @@ const PullDownToRefresh: Component<{ if ( !holding && - untrack(pullDownDistance) >= 160 && + untrack(pullDown) >= stopPos() && !props.loading && props.onRefresh ) { setTimeout(props.onRefresh, 0); - // FIXME: this may trigger at multiple frames } } finally { ds = 0; @@ -91,11 +92,12 @@ const PullDownToRefresh: Component<{ if (scrollTop >= 0 && scrollTop < 1) { event.preventDefault() ds = -(event.deltaY / window.devicePixelRatio / 2); - holding = true; + holding = untrack(pullDown) < stopPos(); if (wheelTimeout) { clearTimeout(wheelTimeout); } wheelTimeout = setTimeout(onWheelNotUpdated, 200); + if (released) { released = false; requestAnimationFrame(updatePullDown); @@ -130,7 +132,7 @@ const PullDownToRefresh: Component<{ } holding = true; if (lastTouchScreenY !== 0) { - ds = (item.screenY - lastTouchScreenY) / window.devicePixelRatio; + ds = (item.screenY - lastTouchScreenY) ; } lastTouchScreenY = item.screenY; if (released) { @@ -143,7 +145,7 @@ const PullDownToRefresh: Component<{ lastTouchId = undefined; lastTouchScreenY = 0; holding = false; - if (untrack(pullDownDistance) >= 160 && !props.loading && props.onRefresh) { + if (untrack(indicatorOfsY) >= 160 && !props.loading && props.onRefresh) { setTimeout(props.onRefresh, 0); } else { if (released) { @@ -185,14 +187,14 @@ const PullDownToRefresh: Component<{ aspect-ratio: 1/1; width: 2rem; color: var(--tutu-color-primary); - transform: translateY(${`${pullDownDistance() - 2}px`}); + transform: translateY(${`${indicatorOfsY() - 2}px`}); will-change: transform; z-index: var(--tutu-zidx-nav); background-color: var(--tutu-color-surface); > :global(.refresh-icon) { transform: rotate( - ${`${((pullDownDistance() / 160) * 180).toString()}deg`} + ${`${((indicatorOfsY() / 160) * 180).toString()}deg`} ); will-change: transform; }