Skip to content

🐛 预览/编辑切换丢失阅读位置:切回预览回顶、切入编辑停在文件顶部 #466

Description

@elysia395

🙏 感谢反馈 / Thanks for reporting!

提交前确认 / Pre-submit checklist

  • 我已搜索现有 issue,确认没有完全相同的条目 / I searched existing issues and confirmed there is no exact duplicate
  • 修复已在本地验证 / The fix is verified locally (see PR)

运行环境 / Environment

  • 运行方式 / Runtime: DSH Web(浏览器访问)/ DSH Web (browser access)

插件版本 / Plugin version

  • dsh-better-sidebar@0.17.1(npm 安装于 profile web)

类别 / Category

  • 🐛 Bug(功能异常 / Something is broken)

描述 / Description

现象 / What happened:

长 markdown 文件在「预览 / 编辑」之间切换时阅读位置丢失,两个方向都有:

  1. 编辑 → 预览(preview 回顶):预览滚动到中部/底部 → 切编辑模式修改并保存 → 切回预览:预览回到文件顶部(实测是「先恢复一下、瞬间又跳回顶部」)。
  2. 预览 → 编辑(editor 不跟随):预览滚动到中部 → 切编辑模式:编辑器打开在文件顶部,而不是预览对应的位置。

期望行为 / Expected behavior:

  • 预览 ↔ 编辑切换后,预览应停在原阅读位置;
  • 从预览切入编辑时,编辑器应定位到预览当前阅读位置对应的小节。

复现步骤 / Steps to reproduce (Bug 必填):

  1. 打开一个足够长的 markdown 文件(≥ 几十屏),用预览模式滚到中部或底部;
  2. Bug 1:点击「编辑」,随便修改一处,Ctrl/Cmd+S 保存,再点「预览」→ 预览回到顶部;
  3. Bug 2:在预览模式滚到中部,直接点「编辑」→ 编辑器停在文件第一行,而不是当前位置对应的小节。

根因定位 / Root cause(已定位,随 PR 修复):

  1. 预览回顶:预览容器 .editorMd 是条件渲染(markdown && mode === 'preview'),每次模式切换都会卸载重建,scrollTop 存在该元素上直接丢失;更关键的是「保存后切回预览」走 fix(editor): 预览刷新三件套——手动刷新按钮 + 切预览自动重载 + 预览保存后重载(fixes #167) #215 的切预览自动重载路径——EditorHost 通过 reloadSeq 重跑 load、进入 loading 占位,整个 TextEditor 组件被卸载重建(实测 CodeMirror 节点标记在重载后消失),组件内任何 ref 记忆随之蒸发,因此组件内修复无效,必须把滚动记忆放到模块级(按 session + path 键控,即 feat(editor): 查找栏 / 滚动记忆 / 自动聚焦 / 资源管理器显示 #236 曾提出的 scroll-memory 思路)。
  2. 编辑器不跟随:预览→编辑切换时没有任何「预览阅读位置 → 编辑器位置」的映射,编辑器打开在自身默认(顶部)位置。

实测数据(headless 浏览器驱动真机 GUI,填充文档 preview scrollHeight ≈ 24730、底端 scrollTop 23838):

路径 修复前 修复后
滚到底→编辑→返回预览(不保存) 0 23838 ✓
滚到底→编辑→保存→预览(#215 重载路径) 0(用户场景) 23838,20×150ms 采样全程 23838,零闪回 ✓
预览滚到中部(12000)→切编辑 编辑器顶部显示 ## Section 001 编辑器顶部显示 ## Section 070(对应小节)✓

建议修法 / Suggested fix:

  • 预览滚动位置:模块级 previewScrollMemory(按会话+路径),滚动时写、预览容器挂载/内容变化时在 useLayoutEffect 中于绘制前恢复;恢复期间用 restoringRef 防止浏览器塌缩/scroll 事件污染记忆(PR 已实现)。
  • 预览→编辑:滚动预览时(节流)捕获视口顶部第一个块元素的文本作为锚点,切编辑后用 linesOfSelection(唯一命中)反查源行,再 dispatch + EditorView.scrollIntoView 定位;文本无从匹配时按滚动比例兜底(PR 已实现)。

补充信息 / Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions