Defer initial message scroll until list renders
This commit is contained in:
@@ -27,24 +27,45 @@ interface MessageBlockListProps {
|
||||
onContentRendered?: () => void
|
||||
setBottomSentinel: (element: HTMLDivElement | null) => void
|
||||
suspendMeasurements?: () => boolean
|
||||
onInitialRenderComplete?: () => void
|
||||
}
|
||||
|
||||
export default function MessageBlockList(props: MessageBlockListProps) {
|
||||
const totalMessages = () => props.messageIds().length
|
||||
let renderedCount = 0
|
||||
let initialRenderReported = false
|
||||
const handleBlockRendered = () => {
|
||||
if (initialRenderReported) return
|
||||
renderedCount += 1
|
||||
if (renderedCount >= totalMessages() && totalMessages() > 0) {
|
||||
initialRenderReported = true
|
||||
renderedCount = 0
|
||||
props.onInitialRenderComplete?.()
|
||||
}
|
||||
}
|
||||
|
||||
createEffect(() => {
|
||||
if (props.loading) {
|
||||
renderedCount = 0
|
||||
initialRenderReported = false
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<Index each={props.messageIds()}>
|
||||
{(messageId) => {
|
||||
return (
|
||||
<VirtualItem
|
||||
id={getMessageAnchorId(messageId())}
|
||||
cacheKey={messageId()}
|
||||
scrollContainer={props.scrollContainer}
|
||||
threshold={VIRTUAL_ITEM_MARGIN_PX}
|
||||
placeholderClass="message-stream-placeholder"
|
||||
virtualizationEnabled={() => !props.loading}
|
||||
suspendMeasurements={props.suspendMeasurements}
|
||||
>
|
||||
|
||||
id={getMessageAnchorId(messageId())}
|
||||
cacheKey={messageId()}
|
||||
scrollContainer={props.scrollContainer}
|
||||
threshold={VIRTUAL_ITEM_MARGIN_PX}
|
||||
placeholderClass="message-stream-placeholder"
|
||||
virtualizationEnabled={() => !props.loading}
|
||||
suspendMeasurements={props.suspendMeasurements}
|
||||
onMeasured={handleBlockRendered}
|
||||
>
|
||||
<MessageBlock
|
||||
messageId={messageId()}
|
||||
instanceId={props.instanceId}
|
||||
|
||||
@@ -162,6 +162,9 @@ export default function MessageSection(props: MessageSectionProps) {
|
||||
let pendingActiveScroll = false
|
||||
let scrollToBottomFrame: number | null = null
|
||||
let scrollToBottomDelayedFrame: number | null = null
|
||||
let pendingInitialScroll = true
|
||||
|
||||
const [initialRenderComplete, setInitialRenderComplete] = createSignal(false)
|
||||
|
||||
function markUserScrollIntent() {
|
||||
const now = typeof performance !== "undefined" ? performance.now() : Date.now()
|
||||
@@ -368,11 +371,18 @@ export default function MessageSection(props: MessageSectionProps) {
|
||||
}
|
||||
|
||||
function handleContentRendered() {
|
||||
|
||||
if (props.loading) {
|
||||
return
|
||||
}
|
||||
scheduleAnchorScroll()
|
||||
}
|
||||
|
||||
function handleInitialRenderComplete() {
|
||||
setInitialRenderComplete(true)
|
||||
}
|
||||
|
||||
function handleScroll() {
|
||||
|
||||
if (!containerRef) return
|
||||
if (pendingScrollFrame !== null) {
|
||||
cancelAnimationFrame(pendingScrollFrame)
|
||||
@@ -412,12 +422,26 @@ export default function MessageSection(props: MessageSectionProps) {
|
||||
lastActiveState = active
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
const loading = Boolean(props.loading)
|
||||
if (loading) {
|
||||
pendingInitialScroll = true
|
||||
setInitialRenderComplete(false)
|
||||
return
|
||||
}
|
||||
if (pendingInitialScroll && initialRenderComplete()) {
|
||||
pendingInitialScroll = false
|
||||
requestScrollToBottom(false)
|
||||
}
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (!props.onQuoteSelection) {
|
||||
clearQuoteSelection()
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
createEffect(() => {
|
||||
if (typeof document === "undefined") return
|
||||
const handleSelectionChange = () => updateQuoteSelectionFromSelection()
|
||||
@@ -647,6 +671,7 @@ export default function MessageSection(props: MessageSectionProps) {
|
||||
onContentRendered={handleContentRendered}
|
||||
setBottomSentinel={setBottomSentinel}
|
||||
suspendMeasurements={() => props.isActive === false}
|
||||
onInitialRenderComplete={handleInitialRenderComplete}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user