⚡ perf(vscode): 代码阅读预览的卡片位置量过就记着,内容或大小变了才重量:粘性标题、记滚动位置、上报可见行、跳转按顶层块二分找,滚动时不再每帧量全部卡片,滚动回调里也不读会逼排版的位置

This commit is contained in:
cruldra committed 2026-10-13 14:58:03 +11:00
1 parent b2e998665e
commit ffb0f147e1
13 files changed
+380 -102

No files matched your search

+11 -3
View File
@@ -5,7 +5,7 @@ import type { TextMarks } from './SegmentText'
import type { BlockView, DocumentMessage } from './types'
import type { OccurrencePage } from './useOccurrences'
import { TriangleAlert } from 'lucide-react'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import { AskThread, FEATURE_THREAD } from './AskThread'
import { BlockTree } from './BlockTree'
import { CallTreeDialog } from './CallTreeDialog'
@@ -17,6 +17,7 @@ import { startEditing } from './editing'
import { keptWhileEditing } from './filter'
import { FilterBar } from './FilterBar'
import { OverviewRuler } from './OverviewRuler'
import { pageLayout } from './pageLayout'
import { createPageStore } from './pageState'
import { chatOf, PATH_ASK_ANCHOR, sameChat } from './qa'
import { TextMarksContext } from './SegmentText'
@@ -75,6 +76,13 @@ export function App(): ReactElement | null {
const restoreCall = useRef(viewState.get().callTree)
/** 块树所在的页面内容:钉住卡片时在这里面量 */
const content = useRef<HTMLDivElement>(null)
/** 页面内容挂上时,卡片的位置从它量(pageLayout):筛选栏和它在同一次提交里画出来 */
const attachContent = useCallback((el: HTMLDivElement | null) => {
content.current = el
return el ? pageLayout.attach(el, document.querySelector<HTMLElement>('.cr-filter-bar')) : undefined
}, [])
// 这一层重画了:同一段脚本里接着要量位置的(滚到某一行、跳到改动、滚到当前那一处)不能用重画前量的,先作废;放在它们前面
useLayoutEffect(() => pageLayout.invalidate())
const { doc, editing, folds, reveal, excluded, diff, onlyChanges, openCall, changes, collapsed, filter, covered, unshown, stops } = useStore(page, current => current)
const pathChat = useStore(qa.store, state => chatOf(state, PATH_ASK_ANCHOR), sameChat)
const qaAvailable = useStore(qa.store, state => state.available)
@@ -236,7 +244,7 @@ export function App(): ReactElement | null {
)}
/>
{changes && diff && <OverviewRuler stops={stops} lineCount={diff.lineCount} onPick={nav.goTo} />}
<div ref={content} className="mx-auto box-content max-w-[880px] px-6 py-5">
<div ref={attachContent} className="mx-auto box-content max-w-[880px] px-6 py-5">
{qaAvailable && (
<div className="mb-4">
<AskThread
@@ -273,7 +281,7 @@ export function App(): ReactElement | null {
{doc.blocks.length === 0
? doc.error === undefined && qaSubject === 'file' && <div className="text-[var(--vscode-descriptionForeground)]">这个文件里没有代码。</div>
: doc.blocks.some(block => !filter.hidden.has(block.id))
? <BlockTree blocks={doc.blocks} tree={tree} />
? <BlockTree blocks={doc.blocks} tree={tree} items />
: <div className="text-[var(--vscode-descriptionForeground)]">所有块都被筛选隐藏了。</div>}
</div>
{sticky?.enabled && <StickyLines content={content} blocks={doc.blocks} settings={sticky} />}