import { Index, createEffect, createSignal, type Accessor } from "solid-js" import VirtualItem from "./virtual-item" import MessageBlock from "./message-block" import type { InstanceMessageStore } from "../stores/message-v2/instance-store" const VIRTUAL_ITEM_MARGIN_PX = 800 const ESTIMATED_MESSAGE_HEIGHT = 320 const INITIAL_FORCE_MIN_ITEMS = 12 const INITIAL_FORCE_OVERSCAN = 6 interface MessageBlockListProps { instanceId: string sessionId: string store: () => InstanceMessageStore messageIds: () => string[] messageIndexMap: () => Map lastAssistantIndex: () => number showThinking: () => boolean thinkingDefaultExpanded: () => boolean showUsageMetrics: () => boolean scrollContainer: Accessor loading?: boolean onRevert?: (messageId: string) => void onFork?: (messageId?: string) => void onContentRendered?: () => void setBottomSentinel: (element: HTMLDivElement | null) => void } export default function MessageBlockList(props: MessageBlockListProps) { const [initialForceActive, setInitialForceActive] = createSignal(true) const [initialForceInitialized, setInitialForceInitialized] = createSignal(false) const [initialForceStartIndex, setInitialForceStartIndex] = createSignal(0) const [, setInitialForceRemaining] = createSignal(0) createEffect(() => { props.instanceId props.sessionId setInitialForceActive(true) setInitialForceInitialized(false) setInitialForceStartIndex(0) setInitialForceRemaining(0) }) createEffect(() => { if (!initialForceActive() || initialForceInitialized()) return const ids = props.messageIds() if (ids.length === 0) return const viewportHeight = props.scrollContainer()?.clientHeight ?? (typeof window !== "undefined" ? window.innerHeight : 800) const estimatedCount = Math.min( ids.length, Math.max(INITIAL_FORCE_MIN_ITEMS, Math.ceil(viewportHeight / ESTIMATED_MESSAGE_HEIGHT) + INITIAL_FORCE_OVERSCAN), ) setInitialForceStartIndex(Math.max(0, ids.length - estimatedCount)) setInitialForceRemaining(estimatedCount) setInitialForceInitialized(true) }) return ( <> {(messageId) => { const messageIndex = () => props.messageIndexMap().get(messageId()) ?? 0 const forceVisible = () => initialForceActive() && messageIndex() >= initialForceStartIndex() const handleMeasured = () => { if (!forceVisible()) return setInitialForceRemaining((value) => { const next = value > 0 ? value - 1 : 0 if (next === 0) { setInitialForceActive(false) } return next }) } return ( !props.loading} forceVisible={forceVisible} onMeasured={handleMeasured} > ) }}