⚡ perf(vscode): 代码阅读预览按卡片订阅状态:中文名、调用树棵数、单击高亮、问答一条消息只重画受影响的卡片和文字,新文档里内容没变的块沿用原来的对象不重画,没展开又没说过的块不画问答区

This commit is contained in:
cruldra committed 2026-10-13 14:40:53 +11:00
1 parent 6e2c541558
commit 0ad4748cc6
27 files changed
+1359 -620

No files matched your search

@@ -98,6 +98,39 @@ export function collapsedIds(blocks: readonly BlockView[], folds: Readonly<Recor
return collapsed
}
/**
* 折叠着的 id 按卡片分好,卡片只订阅自己那份:属性行、子行的 id(`<块 id>/…`)归它那张卡片;块 id 归它自己,
* 也归它的父卡片(挂在父卡片子行上的子块由父卡片的属性表画、点子行开关)。
* 和 previous 里同一张卡片的那份一样时沿用那一份:别的卡片折叠、展开时,这张卡片订阅的还是原来那个对象,不重画。
*/
export function foldsByCard(collapsed: ReadonlySet<string>, previous?: ReadonlyMap<string, ReadonlySet<string>>): ReadonlyMap<string, ReadonlySet<string>> {
const groups = new Map<string, Set<string>>()
const add = (card: string, id: string): void => {
const group = groups.get(card)
if (group)
group.add(id)
else
groups.set(card, new Set([id]))
}
for (const id of collapsed) {
const slash = id.indexOf('/')
if (slash >= 0) {
add(id.slice(0, slash), id)
continue
}
add(id, id)
const dot = id.lastIndexOf('.')
if (dot >= 0)
add(id.slice(0, dot), id)
}
if (!previous)
return groups
return new Map([...groups].map(([card, ids]) => {
const before = previous.get(card)
return [card, before && before.size === ids.size && [...ids].every(id => before.has(id)) ? before : ids]
}))
}
/**
* 属性表里带子行的那一行(输入参数、导入项、字典 / 对象的值)的折叠 id,和块 id 放在同一份 folds 里:
* `<块 id>/p<行序号>`,例如 '6.1.0/p3'。块 id 只由数字和点组成,带 '/' 的不会和任何块 id 撞上。