✨ feat(vscode): 代码阅读差异加「只看改动」(连着没变的块折成一条、按工作区记住)、上一处 / 下一处改动、右边缘总览条
This commit is contained in:
1 parent
707d85c324
commit
6120c85bc0
14 files changed
+533
-42
No files matched your search
@@ -0,0 +1,50 @@
|
||||
import type { ChangeStop } from './diffView'
|
||||
import { useCallback, useLayoutEffect, useRef, useState } from 'react'
|
||||
import { nextStop } from './diffView'
|
||||
import { anchorAt } from './scrollPosition'
|
||||
import { flash } from './useReveal'
|
||||
import { measureBlocks, pinnedHeight } from './useScrollPosition'
|
||||
|
||||
/** 跳到的那处离筛选栏下沿留多少像素。 */
|
||||
const MARGIN = 8
|
||||
|
||||
/**
|
||||
* 「上一处 / 下一处」和点总览条的刻度:跳到一处改动。它在折叠着的块里时先展开那几层(expand),渲染好了再把它滚到筛选栏下面、闪几下。
|
||||
* 接着走从哪算:跳完之后页面没滚过就从刚跳到的那处接着走,用户自己滚过了就按视口顶上那块的行找(见 nextStop)。
|
||||
*/
|
||||
export function useChangeNav(stops: readonly ChangeStop[], collapsed: ReadonlySet<string>, expand: (ids: string[]) => void): {
|
||||
move: (step: 1 | -1) => void
|
||||
goTo: (stop: ChangeStop) => void
|
||||
} {
|
||||
const [target, setTarget] = useState<ChangeStop | null>(null)
|
||||
/** 最近一次跳到的那处,和跳完时页面滚到哪 */
|
||||
const jumped = useRef<{ id: string, scrollY: number } | null>(null)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!target)
|
||||
return
|
||||
const hidden = target.ancestors.filter(id => collapsed.has(id))
|
||||
if (hidden.length > 0) {
|
||||
expand(hidden)
|
||||
return
|
||||
}
|
||||
const card = document.querySelector<HTMLElement>(`.cr-block[data-id="${target.id}"]`)
|
||||
if (card) {
|
||||
window.scrollTo(0, card.getBoundingClientRect().top + window.scrollY - pinnedHeight() - MARGIN)
|
||||
flash(card)
|
||||
}
|
||||
jumped.current = { id: target.id, scrollY: window.scrollY }
|
||||
setTarget(null)
|
||||
}, [target, collapsed, expand])
|
||||
|
||||
const move = useCallback((step: 1 | -1) => {
|
||||
if (stops.length === 0)
|
||||
return
|
||||
const from = jumped.current && Math.abs(window.scrollY - jumped.current.scrollY) < 2 ? jumped.current.id : undefined
|
||||
const index = from === undefined ? -1 : stops.findIndex(stop => stop.id === from)
|
||||
const at = index >= 0 ? { index } : { line: anchorAt(measureBlocks(), window.scrollY + pinnedHeight())?.line }
|
||||
setTarget(stops[nextStop(stops, at, step)])
|
||||
}, [stops])
|
||||
|
||||
return { move, goTo: setTarget }
|
||||
}
|
||||
Reference in new issue
Block a user