fix(ui): keep stream virtualized and bottom-anchored while loading
This commit is contained in:
@@ -558,7 +558,6 @@ export default function MessageSection(props: MessageSectionProps) {
|
|||||||
getKeyFromAnchorId={getMessageIdFromAnchorId}
|
getKeyFromAnchorId={getMessageIdFromAnchorId}
|
||||||
overscanPx={800}
|
overscanPx={800}
|
||||||
scrollSentinelMarginPx={SCROLL_SENTINEL_MARGIN_PX}
|
scrollSentinelMarginPx={SCROLL_SENTINEL_MARGIN_PX}
|
||||||
virtualizationEnabled={() => !props.loading}
|
|
||||||
suspendMeasurements={() => !isActive()}
|
suspendMeasurements={() => !isActive()}
|
||||||
loading={() => Boolean(props.loading)}
|
loading={() => Boolean(props.loading)}
|
||||||
isActive={isActive}
|
isActive={isActive}
|
||||||
|
|||||||
@@ -340,7 +340,6 @@ export default function VirtualFollowList<T>(props: VirtualFollowListProps<T>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function handleContentRendered() {
|
function handleContentRendered() {
|
||||||
if (isLoading()) return
|
|
||||||
scheduleAnchorScroll()
|
scheduleAnchorScroll()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,25 +522,32 @@ export default function VirtualFollowList<T>(props: VirtualFollowListProps<T>) {
|
|||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const loading = isLoading()
|
const loading = isLoading()
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
// Keep the initial scroll pending while loading so we can
|
||||||
|
// anchor to the bottom as soon as items appear.
|
||||||
pendingInitialScroll = true
|
pendingInitialScroll = true
|
||||||
return
|
|
||||||
}
|
|
||||||
if (!pendingInitialScroll) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pendingInitialScroll) return
|
||||||
|
|
||||||
const container = scrollElement()
|
const container = scrollElement()
|
||||||
const sentinel = bottomSentinel()
|
const sentinel = bottomSentinel()
|
||||||
if (!container || !sentinel || props.items().length === 0) {
|
if (!container || !sentinel || props.items().length === 0) return
|
||||||
return
|
|
||||||
|
// Ensure we're in follow-to-bottom mode for the initial position.
|
||||||
|
if (anchorLock()) {
|
||||||
|
clearAnchorLock()
|
||||||
}
|
}
|
||||||
|
setAutoScroll(true)
|
||||||
|
|
||||||
pendingInitialScroll = false
|
pendingInitialScroll = false
|
||||||
requestScrollToBottom(true)
|
// Scroll synchronously so the first paint prefers bottom content.
|
||||||
|
scrollToBottom(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
let previousFollowToken: string | number | undefined
|
let previousFollowToken: string | number | undefined
|
||||||
createEffect(() => {
|
createEffect(() => {
|
||||||
const token = props.followToken?.()
|
const token = props.followToken?.()
|
||||||
if (isLoading() || token === undefined) {
|
if (token === undefined) {
|
||||||
previousFollowToken = token
|
previousFollowToken = token
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -735,7 +741,7 @@ export default function VirtualFollowList<T>(props: VirtualFollowListProps<T>) {
|
|||||||
scrollContainer={scrollElement}
|
scrollContainer={scrollElement}
|
||||||
threshold={overscanPx}
|
threshold={overscanPx}
|
||||||
placeholderClass="message-stream-placeholder"
|
placeholderClass="message-stream-placeholder"
|
||||||
virtualizationEnabled={() => virtualizationEnabled() && !isLoading()}
|
virtualizationEnabled={virtualizationEnabled}
|
||||||
suspendMeasurements={suspendMeasurements}
|
suspendMeasurements={suspendMeasurements}
|
||||||
onHeightChange={(nextHeight, previousHeight) => {
|
onHeightChange={(nextHeight, previousHeight) => {
|
||||||
const delta = nextHeight - previousHeight
|
const delta = nextHeight - previousHeight
|
||||||
|
|||||||
Reference in New Issue
Block a user