Skip to content

Commit

Permalink
Improve scroll stop detection after imperative scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
inokawa committed Dec 15, 2023
1 parent ac39f25 commit 5ffe8c6
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 34 deletions.
20 changes: 9 additions & 11 deletions src/core/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ export const UPDATE_SCROLL_STATE = 0b0001;
/** @internal */
export const UPDATE_SIZE_STATE = 0b0010;
/** @internal */
export const UPDATE_SCROLL_WITH_EVENT = 0b0100;
export const UPDATE_SCROLL_EVENT = 0b0100;
/** @internal */
export const UPDATE_SCROLL_STOP_EVENT = 0b1000;

/**
* @internal
Expand Down Expand Up @@ -179,12 +181,6 @@ export const createVirtualStore = (
jumpCount++;
}
};
const updateScrollDirection = (dir: ScrollDirection): boolean => {
const prev = _scrollDirection;
_scrollDirection = dir;
// Return true if scrolling is just started or stopped
return _scrollDirection !== prev;
};

return {
_getCache() {
Expand Down Expand Up @@ -390,7 +386,7 @@ export const createVirtualStore = (
// Ignore until manual scrolling
!_isManualScrolling
) {
updateScrollDirection(delta < 0 ? SCROLL_UP : SCROLL_DOWN);
_scrollDirection = delta < 0 ? SCROLL_UP : SCROLL_DOWN;
}

// TODO This will cause glitch in reverse infinite scrolling. Disable this until better solution is found.
Expand All @@ -409,14 +405,16 @@ export const createVirtualStore = (
shouldSync = distance > viewportSize;

scrollOffset = nextScrollOffset;
mutated = UPDATE_SCROLL_STATE + UPDATE_SCROLL_WITH_EVENT;
mutated = UPDATE_SCROLL_STATE + UPDATE_SCROLL_EVENT;
break;
}
case ACTION_SCROLL_END: {
if (updateScrollDirection(SCROLL_IDLE)) {
mutated = UPDATE_SCROLL_STOP_EVENT;
if (_scrollDirection !== SCROLL_IDLE) {
shouldFlushPendingJump = true;
mutated = UPDATE_SCROLL_STATE;
mutated += UPDATE_SCROLL_STATE;
}
_scrollDirection = SCROLL_IDLE;
_isManualScrolling = false;
_smoothScrollRange = null;
break;
Expand Down
6 changes: 3 additions & 3 deletions src/react/VGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,6 @@ export const VGrid = forwardRef<VGridHandle, VGridProps>(
const height = vStore._getScrollSize();
const width = hStore._getScrollSize();
const rootRef = useRef<HTMLDivElement>(null);
const vScrolling = vScrollDirection !== SCROLL_IDLE;
const hScrolling = hScrollDirection !== SCROLL_IDLE;

useIsomorphicLayoutEffect(() => {
const root = rootRef[refKey]!;
Expand Down Expand Up @@ -415,7 +413,9 @@ export const VGrid = forwardRef<VGridHandle, VGridProps>(
ref={rootRef}
width={width}
height={height}
scrolling={vScrolling || hScrolling}
scrolling={
vScrollDirection !== SCROLL_IDLE || hScrollDirection !== SCROLL_IDLE
}
attrs={useMemo(
() => ({
...viewportAttrs,
Expand Down
22 changes: 10 additions & 12 deletions src/react/VList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import {
useEffect,
} from "react";
import {
UPDATE_SCROLL_WITH_EVENT,
UPDATE_SCROLL_EVENT,
ACTION_ITEMS_LENGTH_CHANGE,
clampEndIndex,
clampStartIndex,
createVirtualStore,
UPDATE_SIZE_STATE,
UPDATE_SCROLL_STATE,
SCROLL_IDLE,
UPDATE_SCROLL_STOP_EVENT,
} from "../core/store";
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
import { exists, max, values } from "../core/utils";
Expand Down Expand Up @@ -228,7 +229,6 @@ export const VList = forwardRef<VListHandle, VListProps>(
const scrollSize = store._getScrollSize();

const rootRef = useRef<HTMLDivElement>(null);
const scrolling = scrollDirection !== SCROLL_IDLE;

useIsomorphicLayoutEffect(() => {
const root = rootRef[refKey]!;
Expand All @@ -243,17 +243,21 @@ export const VList = forwardRef<VListHandle, VListProps>(
}
}
);
const unsubscribeOnScroll = store._subscribe(
UPDATE_SCROLL_WITH_EVENT,
const unsubscribeOnScroll = store._subscribe(UPDATE_SCROLL_EVENT, () => {
onScroll[refKey] && onScroll[refKey](store._getScrollOffset());
});
const unsubscribeOnScrollStop = store._subscribe(
UPDATE_SCROLL_STOP_EVENT,
() => {
onScroll[refKey] && onScroll[refKey](store._getScrollOffset());
onScrollStop[refKey] && onScrollStop[refKey]();
}
);
const cleanupResizer = resizer._observeRoot(root);
const cleanupScroller = scroller._observe(root);
return () => {
unsubscribeStore();
unsubscribeOnScroll();
unsubscribeOnScrollStop();
cleanupResizer();
cleanupScroller();
};
Expand All @@ -266,12 +270,6 @@ export const VList = forwardRef<VListHandle, VListProps>(
scroller._fixScrollJump(jump);
}, [jumpCount]);

useEffect(() => {
if (!scrolling) {
onScrollStop[refKey] && onScrollStop[refKey]();
}
}, [scrolling]);

useEffect(() => {
if (!onRangeChangeProp) return;

Expand Down Expand Up @@ -341,7 +339,7 @@ export const VList = forwardRef<VListHandle, VListProps>(
ref={rootRef}
width={isHorizontal ? scrollSize : undefined}
height={isHorizontal ? undefined : scrollSize}
scrolling={scrolling}
scrolling={scrollDirection !== SCROLL_IDLE}
attrs={useMemo(
() => ({
...viewportAttrs,
Expand Down
17 changes: 9 additions & 8 deletions src/react/WVList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
clampStartIndex,
createVirtualStore,
SCROLL_IDLE,
UPDATE_SCROLL_STOP_EVENT,
} from "../core/store";
import { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
import { exists, values } from "../core/utils";
Expand Down Expand Up @@ -188,7 +189,6 @@ export const WVList = forwardRef<WVListHandle, WVListProps>(
const scrollSize = store._getTotalSize();

const rootRef = useRef<HTMLDivElement>(null);
const scrolling = scrollDirection !== SCROLL_IDLE;

useIsomorphicLayoutEffect(() => {
const root = rootRef[refKey]!;
Expand All @@ -203,10 +203,17 @@ export const WVList = forwardRef<WVListHandle, WVListProps>(
}
}
);
const unsubscribeOnScrollStop = store._subscribe(
UPDATE_SCROLL_STOP_EVENT,
() => {
onScrollStop[refKey] && onScrollStop[refKey]();
}
);
const cleanupResizer = resizer._observeRoot(root);
const cleanupScroller = scroller._observe(root);
return () => {
unsubscribeStore();
unsubscribeOnScrollStop();
cleanupResizer();
cleanupScroller();
};
Expand All @@ -219,12 +226,6 @@ export const WVList = forwardRef<WVListHandle, WVListProps>(
scroller._fixScrollJump(jump);
}, [jumpCount]);

useEffect(() => {
if (!scrolling) {
onScrollStop[refKey] && onScrollStop[refKey]();
}
}, [scrolling]);

useEffect(() => {
if (!onRangeChangeProp) return;

Expand Down Expand Up @@ -278,7 +279,7 @@ export const WVList = forwardRef<WVListHandle, WVListProps>(
ref={rootRef}
width={isHorizontal ? scrollSize : undefined}
height={isHorizontal ? undefined : scrollSize}
scrolling={scrolling}
scrolling={scrollDirection !== SCROLL_IDLE}
attrs={useMemo(
() => ({
...viewportAttrs,
Expand Down

0 comments on commit 5ffe8c6

Please sign in to comment.