fix(sidebar): compute sticky folder offsets from uniform item height to avoid NaN scroll height

This commit is contained in:
xintaofei
2026-04-22 11:08:17 +08:00
parent 78caf4d827
commit 3f3a325848

View File

@@ -404,10 +404,20 @@ export function SidebarConversationList({
folder: Extract<FlatItem, { type: "folder_header" }> | null folder: Extract<FlatItem, { type: "folder_header" }> | null
pushOffset: number pushOffset: number
}>(() => { }>(() => {
const vr = virtualizerRef.current // All items are uniform height (cardHeightPx). Compute offsets from the
const startIdx = vr ? vr.findItemIndex(scrollOffset) : 0 // index directly instead of querying virtua — querying it during render
// (when flatItems has grown but Virtualizer hasn't re-rendered yet) can
// poison its internal size cache and produce NaN for total scroll height.
if (flatItems.length === 0 || cardHeightPx <= 0) {
return { folder: null, pushOffset: 0 }
}
const rawStart = Math.floor(scrollOffset / cardHeightPx)
const startIdx = Math.max(
0,
Math.min(flatItems.length - 1, Number.isFinite(rawStart) ? rawStart : 0)
)
let folderIdx = -1 let folderIdx = -1
for (let i = Math.min(startIdx, flatItems.length - 1); i >= 0; i--) { for (let i = startIdx; i >= 0; i--) {
if (flatItems[i]?.type === "folder_header") { if (flatItems[i]?.type === "folder_header") {
folderIdx = i folderIdx = i
break break
@@ -421,16 +431,13 @@ export function SidebarConversationList({
{ type: "folder_header" } { type: "folder_header" }
> >
let pushOffset = 0 let pushOffset = 0
if (vr) { for (let i = folderIdx + 1; i < flatItems.length; i++) {
const stickyHeight = vr.getItemSize(folderIdx) || cardHeightPx if (flatItems[i].type === "folder_header") {
for (let i = folderIdx + 1; i < flatItems.length; i++) { const nextRelativeY = i * cardHeightPx - scrollOffset
if (flatItems[i].type === "folder_header") { if (nextRelativeY < cardHeightPx) {
const nextRelativeY = vr.getItemOffset(i) - scrollOffset pushOffset = Math.min(0, nextRelativeY - cardHeightPx)
if (nextRelativeY < stickyHeight) {
pushOffset = Math.min(0, nextRelativeY - stickyHeight)
}
break
} }
break
} }
} }
return { folder, pushOffset } return { folder, pushOffset }