From ef78ed6d5099e84e7261419fd00eea014a860fcf Mon Sep 17 00:00:00 2001 From: inokawa <48897392+inokawa@users.noreply.github.com> Date: Sun, 23 Jul 2023 16:30:22 +0900 Subject: [PATCH] Remove waitForScrollDestinationItemsMeasured from store --- src/core/scroller.ts | 33 ++++++++++++++++++++++++++++++--- src/core/store.ts | 31 +------------------------------ 2 files changed, 31 insertions(+), 33 deletions(-) diff --git a/src/core/scroller.ts b/src/core/scroller.ts index 470c597f0..8c83f4072 100644 --- a/src/core/scroller.ts +++ b/src/core/scroller.ts @@ -6,8 +6,9 @@ import { VirtualStore, SCROLL_IDLE, ACTION_SCROLL_END, + UPDATE_SIZE, } from "./store"; -import { debounce, throttle, max, min } from "./utils"; +import { debounce, throttle, max, min, timeout } from "./utils"; // Infer scroll state also from wheel events // Sometimes scroll events do not fire when frame dropped even if the visual have been already scrolled @@ -51,6 +52,7 @@ export const createScroller = ( isRtl: boolean ): Scroller => { let rootElement: HTMLElement | undefined; + let scrollToQueue: [() => void, () => void] | undefined; const scrollToKey = isHorizontal ? "scrollLeft" : "scrollTop"; const getActualScrollSize = (): number => { @@ -93,12 +95,37 @@ export const createScroller = ( break; } + if (scrollToQueue) { + // Cancel waiting scrollTo + scrollToQueue[1](); + } + + // Wait for the scroll destination items to be measured. + const unsubscribe = store._subscribe(UPDATE_SIZE, () => { + scrollToQueue && scrollToQueue[0](); + }); try { - // Wait for the scroll destination items to be measured. - await store._waitForScrollDestinationItemsMeasured(); + // The measurement will be done asynchronously and the timing is not predictable so we use promise. + // For example, ResizeObserver may not fire when window is not visible. + await new Promise((resolve, reject) => { + let resolved = false; + + const resolveQueue = () => { + if (resolved) return; + resolved = true; + resolve(); + scrollToQueue = undefined; + }; + scrollToQueue = [resolveQueue, reject]; + + // In some specific situation with VGrid, the promise never resolved so we cancel it if timed out. + timeout(resolveQueue, 250); + }); } catch (e) { // canceled return; + } finally { + unsubscribe(); } } diff --git a/src/core/store.ts b/src/core/store.ts index 9f6fd3aaa..c98426dad 100644 --- a/src/core/store.ts +++ b/src/core/store.ts @@ -12,7 +12,7 @@ import { estimateDefaultItemSize, } from "./cache"; import type { Writeable } from "./types"; -import { abs, exists, max, min, timeout } from "./utils"; +import { abs, exists, max, min } from "./utils"; type ItemJump = Readonly<[sizeDiff: number, index: number]>; export type ScrollJump = Readonly; @@ -73,7 +73,6 @@ export type VirtualStore = { _getJumpCount(): number; _flushJump(): ScrollJump | undefined; _getItemIndexForScrollTo(offset: number): number; - _waitForScrollDestinationItemsMeasured(): Promise; _subscribe(target: number, cb: Subscriber): () => void; _update(...action: Actions): void; _getScrollDirection(): ScrollDirection; @@ -97,7 +96,6 @@ export const createVirtualStore = ( let _scrollDirection: ScrollDirection = SCROLL_IDLE; let _resized = false; let _prevRange: ItemsRange = [0, initialItemCount]; - let _scrollToQueue: [() => void, () => void] | undefined; const subscribers = new Set<[number, Subscriber]>(); const getScrollSize = (): number => @@ -187,28 +185,6 @@ export const createVirtualStore = ( _getItemIndexForScrollTo(offset) { return findStartIndexWithOffset(cache, offset, 0, 0); }, - _waitForScrollDestinationItemsMeasured() { - if (_scrollToQueue) { - // Cancel waiting scrollTo - _scrollToQueue[1](); - } - // The measurement will be done asynchronously and the timing is not predictable so we use promise. - // For example, ResizeObserver may not fire when window is not visible. - return new Promise((resolve, reject) => { - let resolved: boolean | undefined = false; - - const resolveQueue = () => { - if (resolved) return; - resolved = true; - resolve(); - _scrollToQueue = undefined; - }; - _scrollToQueue = [resolveQueue, reject]; - - // In some specific situation with VGrid, the promise never resolved so we cancel it if timed out. - timeout(resolveQueue, 250); - }); - }, _subscribe(target, cb) { const sub: [number, Subscriber] = [target, cb]; subscribers.add(sub); @@ -340,11 +316,6 @@ export const createVirtualStore = ( cb(shouldSync); }); } - if (_scrollToQueue) { - if (type === ACTION_ITEM_RESIZE) { - _scrollToQueue[0](); - } - } if (exists(updatedScrollState)) { onScrollStateChange(updatedScrollState); }