⚡ perf(vscode): 代码阅读预览发给页面的块只记相对位置:块在源码里占的地方记成离前一块多远、自己多长,块里名字的下标从块的开头算,页面从文件开头累加回文件里的位置、和扩展端打交道的地方都在一处换算;靠前改了代码,后面内容没变的块发过去一模一样,扩展端自己的块和发给页面的块分成两种类型

This commit is contained in:
cruldra committed 2026-10-13 16:32:18 +11:00
1 parent 3a2815c19c
commit ad5f559e92
43 files changed
+980 -424

No files matched your search

@@ -1,6 +1,6 @@
import type { ChangeEvent, KeyboardEvent, ReactElement } from 'react'
import type { SourceText } from './blockSource'
import type { BlockView } from './types'
import type { Place } from './placement'
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import { blockSource } from './blockSource'
import { recolor } from './segments'
@@ -10,9 +10,10 @@ import { postMessage } from './vscode'
const EDIT_DEBOUNCE_MS = 200
interface CodeEditorProps {
block: BlockView
/** 这一版文档的源码和着色:这块的源码按它的编辑范围从里面取 */
sourceText: SourceText
/** 这块在这一版文档里的位置:编辑范围是它的首尾行 */
place: Place
/** 文档版本:每来一份新文档都要对一次输入框内容,哪怕这一块的代码没变 */
version: number
autoFocus: boolean
@@ -21,12 +22,12 @@ interface CodeEditorProps {
}
/** 一块源码的编辑状态:着色层显示,透明输入框接收输入,改动防抖后整行替换回文件。 */
export function CodeEditor({ block, sourceText, version, autoFocus, onAutoFocused, onExit }: CodeEditorProps): ReactElement {
const { code, tokens } = useMemo(() => blockSource(sourceText, block.startLine, block.endLine), [sourceText, block.startLine, block.endLine])
export function CodeEditor({ sourceText, place, version, autoFocus, onAutoFocused, onExit }: CodeEditorProps): ReactElement {
const { code, tokens } = useMemo(() => blockSource(sourceText, place.line, place.endLine), [sourceText, place.line, place.endLine])
const [text, setText] = useState(code)
const textareaRef = useRef<HTMLTextAreaElement>(null)
const blockRef = useRef(block)
blockRef.current = block
const placeRef = useRef(place)
placeRef.current = place
const textRef = useRef(text)
textRef.current = text
/** 本地改过、还没在新文档里看到的文字;有它时新文档不能覆盖有焦点的输入框 */
@@ -42,12 +43,12 @@ export function CodeEditor({ block, sourceText, version, autoFocus, onAutoFocuse
if (!unsent.current)
return
unsent.current = false
const { startLine, endLine } = blockRef.current
const { line, endLine } = placeRef.current
const value = textRef.current
postMessage({
type: 'edit',
startLine,
endLine: sentLineCount.current === null ? endLine : startLine + sentLineCount.current - 1,
startLine: line,
endLine: sentLineCount.current === null ? endLine : line + sentLineCount.current - 1,
text: value,
})
sentLineCount.current = value.split('\n').length