Skip to content

Commit

Permalink
fix: state restore works with window scrolling
Browse files Browse the repository at this point in the history
Fixes  #957
  • Loading branch information
petyosi committed Aug 9, 2023
1 parent 5b8d062 commit 586aa95
Showing 1 changed file with 52 additions and 30 deletions.
82 changes: 52 additions & 30 deletions src/stateLoadSystem.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,61 @@
import { domIOSystem } from './domIOSystem'
import { initialTopMostItemIndexSystem } from './initialTopMostItemIndexSystem'
import { StateSnapshot, StateCallback } from './interfaces'
import { StateSnapshot, StateCallback, ScrollContainerState, WindowViewportInfo } from './interfaces'
import { propsReadySystem } from './propsReadySystem'
import { sizeSystem, sizeTreeToRanges } from './sizeSystem'
import * as u from './urx'
import { windowScrollerSystem } from './windowScrollerSystem'

export const stateLoadSystem = u.system(([{ sizes, sizeRanges }, { scrollTop }, { initialTopMostItemIndex }, { didMount }]) => {
const getState = u.stream<StateCallback>()
const restoreStateFrom = u.statefulStream<StateSnapshot | undefined>(undefined)

u.subscribe(u.pipe(getState, u.withLatestFrom(sizes, scrollTop)), ([callback, sizes, scrollTop]) => {
const ranges = sizeTreeToRanges(sizes.sizeTree)
callback({ ranges, scrollTop })
})

u.connect(u.pipe(restoreStateFrom, u.filter(u.isDefined), u.map(locationFromSnapshot)), initialTopMostItemIndex)

u.connect(
u.pipe(
didMount,
u.withLatestFrom(restoreStateFrom),
u.filter(([, state]) => state !== undefined),
u.distinctUntilChanged(),
u.map(([, snapshot]) => {
return snapshot!.ranges
})
),
sizeRanges
)

return {
getState,
restoreStateFrom,
}
}, u.tup(sizeSystem, domIOSystem, initialTopMostItemIndexSystem, propsReadySystem))
export const stateLoadSystem = u.system(
([
{ sizes, sizeRanges },
{ scrollTop },
{ initialTopMostItemIndex },
{ didMount },
{ useWindowScroll, windowScrollContainerState, windowViewportRect },
]) => {
const getState = u.stream<StateCallback>()
const restoreStateFrom = u.statefulStream<StateSnapshot | undefined>(undefined)

const statefulWindowScrollContainerState = u.statefulStream<ScrollContainerState | null>(null)
const statefulWindowViewportRect = u.statefulStream<WindowViewportInfo | null>(null)

u.connect(windowScrollContainerState, statefulWindowScrollContainerState)
u.connect(windowViewportRect, statefulWindowViewportRect)

u.subscribe(
u.pipe(getState, u.withLatestFrom(sizes, scrollTop, useWindowScroll, statefulWindowScrollContainerState, statefulWindowViewportRect)),
([callback, sizes, scrollTop, useWindowScroll, windowScrollContainerState, windowViewportRect]) => {
const ranges = sizeTreeToRanges(sizes.sizeTree)
if (useWindowScroll && windowScrollContainerState !== null && windowViewportRect !== null) {
scrollTop = windowScrollContainerState.scrollTop - windowViewportRect.offsetTop
}
callback({ ranges, scrollTop })
}
)

u.connect(u.pipe(restoreStateFrom, u.filter(u.isDefined), u.map(locationFromSnapshot)), initialTopMostItemIndex)

u.connect(
u.pipe(
didMount,
u.withLatestFrom(restoreStateFrom),
u.filter(([, state]) => state !== undefined),
u.distinctUntilChanged(),
u.map(([, snapshot]) => {
return snapshot!.ranges
})
),
sizeRanges
)

return {
getState,
restoreStateFrom,
}
},
u.tup(sizeSystem, domIOSystem, initialTopMostItemIndexSystem, propsReadySystem, windowScrollerSystem)
)

function locationFromSnapshot(snapshot: StateSnapshot | undefined) {
return { offset: snapshot!.scrollTop, index: 0, align: 'start' }
Expand Down

0 comments on commit 586aa95

Please sign in to comment.