✨ feat(vscode): 代码阅读滚进卡片的子块时把外层卡片钉在顶上,同 VS Code 的 Sticky Scroll

This commit is contained in:
cruldra committed 2026-10-08 07:17:26 +08:00
1 parent 5ce2e904f4
commit eb3d1b90cd
17 files changed
+548 -31

No files matched your search

@@ -1,18 +1,21 @@
import type { ChangeStop } from './diffView'
import type { StickyScrollSettings } from './types'
import { useCallback, useLayoutEffect, useRef, useState } from 'react'
import { nextStop } from './diffView'
import { anchorAt } from './scrollPosition'
import { flash } from './useReveal'
import { measureBlocks, pinnedHeight } from './useScrollPosition'
import { stickyInset } from './useStickyScroll'
/** 跳到的那处离筛选栏下沿留多少像素。 */
const MARGIN = 8
/**
* 「上一处 / 下一处」和点总览条的刻度:跳到一处改动。它在折叠着的块里时先展开那几层(expand),渲染好了再把它滚到筛选栏下面、闪几下。
* 「上一处 / 下一处」和点总览条的刻度:跳到一处改动。它在折叠着的块里时先展开那几层(expand),渲染好了再把它滚到筛选栏下面
* (钉着外层卡片时在钉着的几行下面,sticky 是 VS Code 的 Sticky Scroll 设置)、闪几下。
* 接着走从哪算:跳完之后页面没滚过就从刚跳到的那处接着走,用户自己滚过了就按视口顶上那块的行找(见 nextStop)。
*/
export function useChangeNav(stops: readonly ChangeStop[], collapsed: ReadonlySet<string>, expand: (ids: string[]) => void): {
export function useChangeNav(stops: readonly ChangeStop[], collapsed: ReadonlySet<string>, expand: (ids: string[]) => void, sticky: StickyScrollSettings | undefined): {
move: (step: 1 | -1) => void
goTo: (stop: ChangeStop) => void
} {
@@ -30,12 +33,12 @@ export function useChangeNav(stops: readonly ChangeStop[], collapsed: ReadonlySe
}
const card = document.querySelector<HTMLElement>(`.cr-block[data-id="${target.id}"]`)
if (card) {
window.scrollTo(0, card.getBoundingClientRect().top + window.scrollY - pinnedHeight() - MARGIN)
window.scrollTo(0, card.getBoundingClientRect().top + window.scrollY - pinnedHeight() - stickyInset(card, sticky) - MARGIN)
flash(card)
}
jumped.current = { id: target.id, scrollY: window.scrollY }
setTarget(null)
}, [target, collapsed, expand])
}, [target, collapsed, expand, sticky])
const move = useCallback((step: 1 | -1) => {
if (stops.length === 0)