From 7edad1a4d064c97086b1fe41107e08ad664cd709 Mon Sep 17 00:00:00 2001 From: Petyo Ivanov Date: Tue, 22 Dec 2020 19:20:35 +0200 Subject: [PATCH] fix(): broken startReached is broken no more Fix #242 --- package.json | 4 +- src/List.tsx | 2 +- src/listStateSystem.ts | 12 +++--- src/sizeSystem.ts | 35 +++++++++-------- src/upwardScrollFixSystem.ts | 74 ++++++++++++++++++------------------ yarn.lock | 54 ++++++-------------------- 6 files changed, 79 insertions(+), 102 deletions(-) diff --git a/package.json b/package.json index e015d6293..c087cdb8c 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "semantic-release": "semantic-release" }, "dependencies": { - "@virtuoso.dev/react-urx": "^0.2.0", - "@virtuoso.dev/urx": "^0.2.0", + "@virtuoso.dev/react-urx": "^0.2.3", + "@virtuoso.dev/urx": "^0.2.3", "react-app-polyfill": "^1.0.6", "resize-observer-polyfill": "^1.5.1" }, diff --git a/src/List.tsx b/src/List.tsx index a8fcb352c..97aa99af9 100644 --- a/src/List.tsx +++ b/src/List.tsx @@ -324,6 +324,7 @@ export const { Component: List, usePublisher, useEmitterValue, useEmitter } = sy { required: {}, optional: { + firstItemIndex: 'firstItemIndex', itemContent: 'itemContent', groupContent: 'groupContent', overscan: 'overscan', @@ -339,7 +340,6 @@ export const { Component: List, usePublisher, useEmitterValue, useEmitter } = sy followOutput: 'followOutput', headerFooterTag: 'headerFooterTag', data: 'data', - firstItemIndex: 'firstItemIndex', initialItemCount: 'initialItemCount', initialScrollTop: 'initialScrollTop', diff --git a/src/listStateSystem.ts b/src/listStateSystem.ts index e5a0788c7..efa6642dc 100644 --- a/src/listStateSystem.ts +++ b/src/listStateSystem.ts @@ -1,15 +1,14 @@ import * as u from '@virtuoso.dev/urx' import { empty, find, findMaxKeyValue, Range, rangesWithin } from './AATree' +import { domIOSystem } from './domIOSystem' import { groupedListSystem } from './groupedListSystem' import { initialTopMostItemIndexSystem } from './initialTopMostItemIndexSystem' -import { ListRange } from './interfaces' +import { Item, ListItem, ListRange } from './interfaces' import { propsReadySystem } from './propsReadySystem' import { scrollToIndexSystem } from './scrollToIndexSystem' import { sizeRangeSystem } from './sizeRangeSystem' import { Data, originalIndexFromItemIndex, SizeState, sizeSystem } from './sizeSystem' import { stateFlagsSystem } from './stateFlagsSystem' -import { domIOSystem } from './domIOSystem' -import { Item, ListItem } from './interfaces' export interface TopListState { items: ListItem[] @@ -153,7 +152,7 @@ export const listStateSystem = u.system( u.duc(firstItemIndex), data ), - u.filter(([didMount]) => didMount), + u.filter(([mount]) => mount), u.map( ([ , @@ -294,7 +293,10 @@ export const listStateSystem = u.system( const startReached = u.streamFromEmitter( u.pipe( listState, - u.filter(({ items, topItems }) => items.length > 0 && items[0].originalIndex === topItems.length), + u.throttleTime(100), + u.filter(({ items, topItems }) => { + return items.length > 0 && items[0].originalIndex === topItems.length + }), u.map(({ items }) => items[0].index), u.distinctUntilChanged() ) diff --git a/src/sizeSystem.ts b/src/sizeSystem.ts index 6ac6c9eaf..b48bc52c0 100644 --- a/src/sizeSystem.ts +++ b/src/sizeSystem.ts @@ -252,6 +252,25 @@ export const sizeSystem = u.system( ) ) + u.connect( + u.pipe( + firstItemIndex, + u.scan( + (prev, next) => { + return { diff: prev.prev - next, prev: next } + }, + { diff: 0, prev: 0 } + ), + u.map(val => val.diff), + u.filter(value => value > 0) + ), + unshiftWith + ) + + // hack to capture the current list top item before the sizes get refreshed + // :( + const prioUnshiftWith = u.streamFromEmitter(unshiftWith) + u.connect( u.pipe( unshiftWith, @@ -280,21 +299,6 @@ export const sizeSystem = u.system( sizeRanges ) - u.connect( - u.pipe( - firstItemIndex, - u.scan( - (prev, next) => { - return { diff: prev.prev - next, prev: next } - }, - { diff: 0, prev: 0 } - ), - u.map(val => val.diff), - u.filter(value => value > 0) - ), - unshiftWith - ) - return { // input data, @@ -304,6 +308,7 @@ export const sizeSystem = u.system( defaultItemSize, fixedItemSize, unshiftWith, + prioUnshiftWith, firstItemIndex, // output diff --git a/src/upwardScrollFixSystem.ts b/src/upwardScrollFixSystem.ts index c8cd7695b..9bb2b236f 100644 --- a/src/upwardScrollFixSystem.ts +++ b/src/upwardScrollFixSystem.ts @@ -1,4 +1,4 @@ -import { connect, filter, getValue, handleNext, map, pipe, publish, scan, subscribe, system, tup, withLatestFrom } from '@virtuoso.dev/urx' +import * as u from '@virtuoso.dev/urx' import { UP, domIOSystem } from './domIOSystem' import { listStateSystem } from './listStateSystem' import { offsetOf, sizeSystem } from './sizeSystem' @@ -10,16 +10,16 @@ const GLITCHY_SCROLL_BY = UA && (!!UA.match(/iPad/i) || !!UA.match(/iPhone/i)) /** * Fixes upward scrolling by calculating and compensation from changed item heights, using scrollBy. */ -export const upwardScrollFixSystem = system( - ([{ scrollBy, scrollTop, scrollDirection, deviation }, { isScrolling }, { listState }, { unshiftWith, sizes, listRefresh }]) => { - const deviationOffset = pipe( +export const upwardScrollFixSystem = u.system( + ([{ scrollBy, scrollTop, scrollDirection, deviation }, { isScrolling }, { listState }, { prioUnshiftWith, sizes }]) => { + const deviationOffset = u.pipe( listState, - withLatestFrom(scrollTop, scrollDirection), - filter(([, scrollTop, scrollDirection]) => { + u.withLatestFrom(scrollTop, scrollDirection), + u.filter(([, scrollTop, scrollDirection]) => { return scrollTop !== 0 && scrollDirection === UP }), - map(([state]) => state), - scan( + u.map(([state]) => state), + u.scan( ([, prevItems], { items }) => { let newDev = 0 if (prevItems.length > 0 && items.length > 0) { @@ -47,65 +47,67 @@ export const upwardScrollFixSystem = system( }, [0, []] as [number, ListItem[]] ), - filter(([amount]) => amount !== 0), - map(([amount]) => amount) + u.filter(([amount]) => amount !== 0), + u.map(([amount]) => amount) ) if (GLITCHY_SCROLL_BY) { - connect( - pipe( + u.connect( + u.pipe( deviationOffset, - withLatestFrom(deviation), - map(([amount, deviation]) => deviation - amount) + u.withLatestFrom(deviation), + u.map(([amount, deviation]) => deviation - amount) ), deviation ) // when the browser stops scrolling, // restore the position and reset the glitching - subscribe( - pipe( + u.subscribe( + u.pipe( isScrolling, - filter(is => !is), - withLatestFrom(deviation), - filter(([_, deviation]) => deviation !== 0), - map(([_, deviation]) => deviation) + u.filter(is => !is), + u.withLatestFrom(deviation), + u.filter(([_, deviation]) => deviation !== 0), + u.map(([_, deviation]) => deviation) ), offset => { - publish(scrollBy, { top: -offset, behavior: 'auto' }) - publish(deviation, 0) + u.publish(scrollBy, { top: -offset, behavior: 'auto' }) + u.publish(deviation, 0) } ) } else { - connect( - pipe( + u.connect( + u.pipe( deviationOffset, - map(offset => ({ top: offset, behavior: 'auto' })) + u.map(offset => ({ top: offset, behavior: 'auto' })) ), scrollBy ) } - subscribe( - pipe( - unshiftWith, - withLatestFrom(sizes, listState), - map(([unshiftWith, sizeState, listState]) => { + u.subscribe( + u.pipe( + prioUnshiftWith, + u.map(unshiftWith => { + const currentTopIndex = u.getValue(listState).items[0].originalIndex! + + console.log({ currentTopIndex }) return { - index: listState.items[0].originalIndex! + unshiftWith, - offset: offsetOf(listState.items[0].originalIndex!, sizeState), + index: currentTopIndex + unshiftWith, + offset: offsetOf(currentTopIndex, u.getValue(sizes)), } }) ), ({ index, offset }) => { - handleNext(listRefresh, () => { - const newOffset = offsetOf(index, getValue(sizes)) - publish(scrollBy, { top: newOffset - offset }) + setTimeout(() => { + const newOffset = offsetOf(index, u.getValue(sizes)) + u.publish(scrollBy, { top: newOffset - offset }) }) } ) return { deviation } }, - tup(domIOSystem, stateFlagsSystem, listStateSystem, sizeSystem) + u.tup(domIOSystem, stateFlagsSystem, listStateSystem, sizeSystem) ) diff --git a/yarn.lock b/yarn.lock index 19d7672fd..8aa264286 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2230,17 +2230,17 @@ semver "^7.3.2" tsutils "^3.17.1" -"@virtuoso.dev/react-urx@^0.2.0": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@virtuoso.dev/react-urx/-/react-urx-0.2.1.tgz#770c82a4f7944a4fad1a0ef689f7f7dafbda1af7" - integrity sha512-RiRG8+lMB2mf+lxgI3p1c7I1G2uRX5A25inxlGO3EFgjPzD1oX3g6yaH7ioOjAieBb2OKmaoR+imKXNzTIuzNQ== +"@virtuoso.dev/react-urx@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@virtuoso.dev/react-urx/-/react-urx-0.2.3.tgz#b336adcfaadf7526f568f0bb2482f28e5fe81e40" + integrity sha512-8U8Vjebv/Itkc2tXvLVystMXimsTAHaDSauqzy1xrSDvWybdWxkRmTOjykK8gYUfLVIDNuC2NHXOBSocNcAx8w== dependencies: - "@virtuoso.dev/urx" "^0.2.1" + "@virtuoso.dev/urx" "^0.2.3" -"@virtuoso.dev/urx@^0.2.0", "@virtuoso.dev/urx@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@virtuoso.dev/urx/-/urx-0.2.1.tgz#d81d9ac2ae5e8cd24d0b4595b8131f9280b48945" - integrity sha512-OpaQmK4EGH+DVwIvS0zuhLQPvLb8yWzTy07iDEVGTE1GFMznRhnF+aSZeMOshllEZkRzjjzOWxLxrkPR3vOkrQ== +"@virtuoso.dev/urx@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@virtuoso.dev/urx/-/urx-0.2.3.tgz#31b8a09cceb76567115ecbdad5355d0c9e44c23c" + integrity sha512-GrsPotsF4I9ZSmdGsy1Uv5qdsiOdbYYWbE0WGeTfWnB1BGS2ANSeprAROZFv9FEW+ZKTYbqGWCzrY8CdfJxn4Q== JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@^1.3.5: version "1.3.5" @@ -4272,7 +4272,7 @@ debug@^4.0.0: dependencies: ms "2.1.2" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= @@ -6371,7 +6371,7 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= @@ -8341,11 +8341,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw= - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -8354,33 +8349,11 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= - -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI= - -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM= - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= -lodash._getnative@*, lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - lodash._root@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" @@ -8431,11 +8404,6 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.restparam@*: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"