🐛 fix(vscode): 代码阅读预览跳到定义后页面还在长高(注释里的 mermaid 画成图、中文名到了)不再把视口带跑:页面滚动统一交给滚动所有者,跟住跳到的目标、用户自己滚了改钉视口顶部那块,关掉浏览器自带的滚动锚定

This commit is contained in:
cruldra committed 2026-10-14 06:11:25 +11:00
1 parent 2fa6319dd4
commit 3c5f5f5f35
24 files changed
+1016 -149

No files matched your search

+14 -5
View File
@@ -10,6 +10,7 @@ import { SelectMenu } from '@/components/ui/select-menu'
import { renderMarkdown, renderMarkdownOnce } from './markdown'
import { answerPreview, relativeTime, unfinished } from './qa'
import { MAX_IMAGES, pickImages, readImage, transferFiles } from './qaImages'
import { showInViewport } from './useReveal'
/** 一种对话在界面上怎么称呼:区域的名字、图标、「问过 N 次」、删一条、输入框的提示和名字、回答长出来时的状态 */
export interface ThreadWording {
@@ -83,10 +84,10 @@ function ImagePreview({ url, onClose }: { url: string, onClose: () => void }): R
const close = useRef<HTMLButtonElement>(null)
useEffect(() => {
const opener = document.activeElement
close.current?.focus()
close.current?.focus({ preventScroll: true })
return () => {
if (opener instanceof HTMLElement)
opener.focus()
opener.focus({ preventScroll: true })
}
}, [])
const onKeyDown = (event: KeyboardEvent<HTMLDivElement>): void => {
@@ -194,6 +195,14 @@ function CurrentItem({ ask, wording, onOpenImage }: { ask: Ask, wording: ThreadW
}
/** 底下的输入框:Enter 发送、Shift+Enter 换行、Esc 收起;正在答时发送换成停止,排着队时换成取消排队。能贴图、拖图,贴的图在输入框上面一排,随下一个问题发 */
/** 把光标放进输入框;它不在视口里时交给[滚动所有者](vscode/webview-ui/src/codeReader/scrollOwner.ts#ScrollOwner)滚过去(见 [showInViewport]),不让浏览器自己滚。 */
function focusField(field: HTMLTextAreaElement | null): void {
if (!field)
return
field.focus({ preventScroll: true })
showInViewport(() => field.isConnected ? field : null)
}
function AskInput({ active, placeholder, label, profiles, onSelectProfile, onAsk, onStop, onClose, closable, onOpenImage, autoFocus, focusToken }: {
/** 正在答或排着队的那一轮 */
active: Ask | undefined
@@ -222,11 +231,11 @@ function AskInput({ active, placeholder, label, profiles, onSelectProfile, onAsk
const textarea = useRef<HTMLTextAreaElement>(null)
useEffect(() => {
if (autoFocus)
textarea.current?.focus()
focusField(textarea.current)
}, [autoFocus])
useEffect(() => {
if (focusToken > 0)
textarea.current?.focus()
focusField(textarea.current)
}, [focusToken])
const attach = (files: File[]): void => {
if (files.length === 0)
@@ -275,7 +284,7 @@ function AskInput({ active, placeholder, label, profiles, onSelectProfile, onAsk
}
const remove = (index: number): void => {
setImages(current => current.filter((_, i) => i !== index))
textarea.current?.focus()
focusField(textarea.current)
}
return (
<>