From e64d20792b589cf9aa5e3b5d9b66c5679649c4de Mon Sep 17 00:00:00 2001 From: Petyo Ivanov Date: Fri, 6 Aug 2021 09:27:47 +0300 Subject: [PATCH] fix(): handle very tall last item in reverse mode --- src/scrollToIndexSystem.ts | 21 ++++++++++++++++++++- test/listSystem.test.ts | 13 ++++++++----- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/scrollToIndexSystem.ts b/src/scrollToIndexSystem.ts index bb59b7d71..77e7e7aa7 100644 --- a/src/scrollToIndexSystem.ts +++ b/src/scrollToIndexSystem.ts @@ -88,6 +88,7 @@ export const scrollToIndexSystem = u.system( cleanup() if (listChanged) { u.publish(scrollToIndex, location) + } else { } } @@ -103,7 +104,7 @@ export const scrollToIndexSystem = u.system( retry(listChanged) }) } else { - unsubscribeNextListRefresh = u.handleNext(listRefresh, retry) + unsubscribeNextListRefresh = u.handleNext(u.pipe(listRefresh, accumulateChange(0)), retry) } // if the scroll jump is too small, the list won't get rerendered. @@ -127,3 +128,21 @@ export const scrollToIndexSystem = u.system( u.tup(sizeSystem, domIOSystem), { singleton: true } ) + +function accumulateChange(interval: number): u.Operator { + let currentValue: T | undefined + let timeout: any + + return (done) => (value) => { + currentValue = currentValue || value + + if (timeout) { + return + } + + timeout = setTimeout(() => { + timeout = undefined + done(currentValue!) + }, interval) + } +} diff --git a/test/listSystem.test.ts b/test/listSystem.test.ts index 1854f9f72..ec641e8a3 100644 --- a/test/listSystem.test.ts +++ b/test/listSystem.test.ts @@ -174,7 +174,7 @@ describe('list engine', () => { }) }) - it('readjusts once when new sizes are reported', () => { + it('readjusts once when new sizes are reported', (done) => { const DEVIATION = 20 publish(sti, { index: INDEX, align: 'end' }) @@ -185,10 +185,13 @@ describe('list engine', () => { publish(sr, [{ startIndex: INDEX - 1, endIndex: INDEX - 1, size: SIZE + DEVIATION }]) - expect(sub).toHaveBeenCalledWith({ - top: INDEX * SIZE - VIEWPORT + SIZE + DEVIATION, - behavior: 'auto', - }) + setTimeout(() => { + expect(sub).toHaveBeenCalledWith({ + top: INDEX * SIZE - VIEWPORT + SIZE + DEVIATION, + behavior: 'auto', + }) + done() + }, 20) }) })