Skip to content

Commit cc3a38a

Browse files
committed
Fixed autoscroll being stuck when already scrolled to top/bottom
1 parent 21f9ae1 commit cc3a38a

1 file changed

Lines changed: 56 additions & 20 deletions

File tree

src/index.tsx

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ class DraggableFlatList<T> extends React.Component<Props<T>, State> {
226226

227227
keyToIndex = new Map<string, number>();
228228

229+
/** Whether we've sent an incomplete call to the FlatList to do a scroll */
229230
isAutoscrolling = {
230231
native: new Value<number>(0),
231232
js: false
@@ -611,23 +612,49 @@ class DraggableFlatList<T> extends React.Component<Props<T>, State> {
611612
return targetOffset;
612613
};
613614

614-
autoscroll = async ([
615-
distFromTop,
616-
distFromBottom,
617-
scrollOffset,
618-
isScrolledUp,
619-
isScrolledDown
620-
]: readonly number[]) => {
621-
const targetOffset = this.getScrollTargetOffset(
622-
distFromTop,
623-
distFromBottom,
624-
scrollOffset,
625-
!!isScrolledUp,
626-
!!isScrolledDown
627-
);
628-
if (targetOffset >= 0 && this.isPressedIn.js) {
629-
const nextScrollParams = await this.scrollToAsync(targetOffset);
630-
this.autoscroll(nextScrollParams);
615+
/** Ensure that only 1 call to autoscroll is active at a time */
616+
autoscrollLooping = false;
617+
autoscroll = async (params: readonly number[]) => {
618+
if (this.autoscrollLooping) {
619+
return;
620+
}
621+
this.autoscrollLooping = true;
622+
try {
623+
let shouldScroll = true;
624+
let curParams = params;
625+
while (shouldScroll) {
626+
const [
627+
distFromTop,
628+
distFromBottom,
629+
scrollOffset,
630+
isScrolledUp,
631+
isScrolledDown
632+
] = curParams;
633+
const targetOffset = this.getScrollTargetOffset(
634+
distFromTop,
635+
distFromBottom,
636+
scrollOffset,
637+
!!isScrolledUp,
638+
!!isScrolledDown
639+
);
640+
const scrollingUpAtTop = !!(
641+
isScrolledUp && targetOffset <= scrollOffset
642+
);
643+
const scrollingDownAtBottom = !!(
644+
isScrolledDown && targetOffset >= scrollOffset
645+
);
646+
shouldScroll =
647+
targetOffset >= 0 &&
648+
this.isPressedIn.js &&
649+
!scrollingUpAtTop &&
650+
!scrollingDownAtBottom;
651+
652+
if (shouldScroll) {
653+
curParams = await this.scrollToAsync(targetOffset);
654+
}
655+
}
656+
} finally {
657+
this.autoscrollLooping = false;
631658
}
632659
};
633660

@@ -669,17 +696,26 @@ class DraggableFlatList<T> extends React.Component<Props<T>, State> {
669696
and(
670697
this.isAutoscrolling.native,
671698
or(
699+
// We've scrolled to where we want to be
672700
lessOrEq(
673701
abs(sub(this.targetScrollOffset, this.scrollOffset)),
674702
scrollPositionTolerance
675703
),
676-
this.isScrolledUp,
677-
this.isScrolledDown
704+
// We're at the start, but still want to scroll farther up
705+
and(
706+
this.isScrolledUp,
707+
lessOrEq(this.targetScrollOffset, this.scrollOffset)
708+
),
709+
// We're at the end, but still want to scroll further down
710+
and(
711+
this.isScrolledDown,
712+
greaterOrEq(this.targetScrollOffset, this.scrollOffset)
713+
)
678714
)
679715
),
680716
[
717+
// Finish scrolling
681718
set(this.isAutoscrolling.native, 0),
682-
this.checkAutoscroll,
683719
call(this.autoscrollParams, this.onAutoscrollComplete)
684720
]
685721
)

0 commit comments

Comments
 (0)