perf(app): virtualize session timeline rows (#26949)

Co-authored-by: Brendan Allan <git@brendonovich.dev>
This commit is contained in:
Luke Parker
2026-05-18 03:40:52 +00:00
committed by GitHub
co-authored by Brendan Allan
parent e85119aa64
commit 5452ab6db7
9 changed files with 1618 additions and 883 deletions
+61 -16
View File
@@ -1,4 +1,4 @@
import { createEffect, For, Match, on, onCleanup, Show, Switch, type JSX } from "solid-js"
import { createEffect, For, Match, on, onCleanup, onMount, Show, Switch, type JSX } from "solid-js"
import { animate, type AnimationPlaybackControls } from "motion"
import { useI18n } from "../context/i18n"
import { createStore } from "solid-js/store"
@@ -40,26 +40,76 @@ export interface BasicToolProps {
}
const SPRING = { type: "spring" as const, visualDuration: 0.35, bounce: 0 }
const deferredMounts: Array<{ active: boolean; fn: () => void }> = []
let deferredFrame: number | undefined
function flushDeferredMounts() {
while (deferredMounts.length > 0) {
// Timeline tools are mounted top-to-bottom, but the viewport starts at the latest turn.
// Pop from the end so heavy default-open bodies near the bottom become interactive first.
const item = deferredMounts.pop()!
if (item.active) {
deferredFrame = deferredMounts.length > 0 ? requestAnimationFrame(flushDeferredMounts) : undefined
item.fn()
return
}
}
deferredFrame = undefined
}
function scheduleDeferredFlush() {
if (deferredFrame !== undefined) return
deferredFrame = requestAnimationFrame(() => {
deferredFrame = requestAnimationFrame(flushDeferredMounts)
})
}
function scheduleDeferredMount(fn: () => void) {
const item = { active: true, fn }
deferredMounts.push(item)
scheduleDeferredFlush()
return () => {
item.active = false
}
}
function scheduleFrameMount(fn: () => void) {
const frame = requestAnimationFrame(fn)
return () => cancelAnimationFrame(frame)
}
export function BasicTool(props: BasicToolProps) {
const [state, setState] = createStore({
open: props.defaultOpen ?? false,
ready: props.defaultOpen ?? false,
ready: !props.defer && (props.defaultOpen ?? false),
})
const open = () => state.open
const ready = () => state.ready
const pending = () => props.status === "pending" || props.status === "running"
const hasChildren = () => (props.defer ? "children" in props : props.children)
let frame: number | undefined
let cancelReady: (() => void) | undefined
const cancel = () => {
if (frame === undefined) return
cancelAnimationFrame(frame)
frame = undefined
cancelReady?.()
cancelReady = undefined
}
const scheduleReady = (initial = false) => {
cancel()
cancelReady = (initial ? scheduleDeferredMount : scheduleFrameMount)(() => {
cancelReady = undefined
if (!open()) return
setState("ready", true)
})
}
onCleanup(cancel)
onMount(() => {
if (props.defer && open()) scheduleReady(true)
})
createEffect(() => {
if (props.forceOpen) setState("open", true)
})
@@ -75,12 +125,7 @@ export function BasicTool(props: BasicToolProps) {
return
}
cancel()
frame = requestAnimationFrame(() => {
frame = undefined
if (!open()) return
setState("ready", true)
})
scheduleReady()
},
{ defer: true },
),
@@ -189,7 +234,7 @@ export function BasicTool(props: BasicToolProps) {
</Switch>
</div>
</div>
<Show when={props.children && !props.hideDetails && !props.locked && !pending()}>
<Show when={hasChildren() && !props.hideDetails && !props.locked && !pending()}>
<Collapsible.Arrow />
</Show>
</div>
@@ -219,7 +264,7 @@ export function BasicTool(props: BasicToolProps) {
</Collapsible.Trigger>
)}
</Show>
<Show when={props.animated && props.children && !props.hideDetails}>
<Show when={props.animated && hasChildren() && !props.hideDetails}>
<div
ref={contentRef}
data-slot="collapsible-content"
@@ -229,10 +274,10 @@ export function BasicTool(props: BasicToolProps) {
overflow: initialOpen ? "visible" : "hidden",
}}
>
{props.children}
<Show when={!props.defer || ready()}>{props.children}</Show>
</div>
</Show>
<Show when={!props.animated && props.children && !props.hideDetails}>
<Show when={!props.animated && hasChildren() && !props.hideDetails}>
<Collapsible.Content>
<Show when={!props.defer || ready()}>{props.children}</Show>
</Collapsible.Content>