✨ feat(vscode): 代码阅读预览单击名字高亮它在文件里的各处出现
This commit is contained in:
1 parent
5872cf7958
commit
9c0f05362c
12 files changed
+558
-9
No files matched your search
@@ -0,0 +1,55 @@
|
||||
import type { Click, Highlight } from './occurrences'
|
||||
import { createContext, useEffect, useLayoutEffect, useState } from 'react'
|
||||
import { clickAction, OccurrenceHighlight } from './occurrences'
|
||||
import { onMessage, postMessage } from './vscode'
|
||||
|
||||
/** 眼下高亮着的名字,SegmentText 按它给各处出现上底色。 */
|
||||
export const HighlightContext = createContext<Highlight | undefined>(undefined)
|
||||
|
||||
/** 自己管点击的东西:点在上面(名字以外的地方)高亮不动 */
|
||||
const CONTROLS = 'a, button, input, select, textarea, [role="listbox"], .cr-filter-bar, .cr-prop-label'
|
||||
|
||||
function clickOf(event: MouseEvent): Click {
|
||||
const target = event.target instanceof Element ? event.target : null
|
||||
const name = target?.closest<HTMLElement>('[data-offset]')
|
||||
const selection = window.getSelection()
|
||||
return {
|
||||
modified: event.metaKey || event.ctrlKey || event.altKey || event.shiftKey,
|
||||
count: event.detail,
|
||||
selecting: selection !== null && !selection.isCollapsed,
|
||||
name: name?.dataset.offset === undefined ? undefined : { offset: Number(name.dataset.offset), text: name.textContent ?? '' },
|
||||
control: target?.closest(CONTROLS) != null,
|
||||
}
|
||||
}
|
||||
|
||||
/** 单击名字高亮它在文档里的各处出现,点空白处、Esc、换文档版本或翻译清掉;返回眼下高亮着的名字。 */
|
||||
export function useOccurrences(version: number | undefined, translatorId: string | undefined): Highlight | undefined {
|
||||
const [highlight, setHighlight] = useState<Highlight | undefined>()
|
||||
const [occurrences] = useState(() => new OccurrenceHighlight(postMessage, setHighlight))
|
||||
|
||||
// 赶在绘制前清掉:新文档的下标换了意思,旧高亮不能落在新页面的别的名字上
|
||||
useLayoutEffect(() => occurrences.setDocument(version, translatorId), [occurrences, version, translatorId])
|
||||
|
||||
useEffect(() => {
|
||||
// 捕获阶段:赶在块里的按钮处理点击、折叠箭头换图标之前读出点在哪
|
||||
const onClick = (event: MouseEvent): void => occurrences.click(clickAction(clickOf(event)))
|
||||
// 输入框、下拉列表自己用掉的 Esc 不算
|
||||
const onKey = (event: KeyboardEvent): void => {
|
||||
if (event.key === 'Escape' && !event.defaultPrevented)
|
||||
occurrences.clear()
|
||||
}
|
||||
const off = onMessage((msg) => {
|
||||
if (msg.type === 'occurrencesFound')
|
||||
occurrences.answer(msg.id, msg.occurrences)
|
||||
})
|
||||
document.addEventListener('click', onClick, true)
|
||||
window.addEventListener('keydown', onKey)
|
||||
return () => {
|
||||
off()
|
||||
document.removeEventListener('click', onClick, true)
|
||||
window.removeEventListener('keydown', onKey)
|
||||
}
|
||||
}, [occurrences])
|
||||
|
||||
return highlight
|
||||
}
|
||||
Reference in new issue
Block a user