首页编辑、预览、差异视图自查方案与记录
1. 范围与基线
- 检查日期:2026-10-04。
- 代码基线:
896126e371262509774dc41e0d65302cc524d2bf。
- 近期修改范围:最近 16 次提交,包含
2ba9141 至 896126e。
- 本轮交付:自查方案、代码阅读结论、现有验证结果与后续修复建议。
- 本轮不修改业务代码、公开接口、会话格式或现有测试。
- 检查对象:首页编辑、预览、当前文件只读差异,以及直接关联的工具栏、标签状态、保存、历史基准、缩放和源码定位。
- 文件树差异仅检查共用组件与返回首页的跳转路径。
- 不扩展到仓库管理、登录、同步协议和其他页面的全面审查。
1.1 规范来源
1.2 状态与证据说明
- 确认问题:代码调用链已经能确定缺少必要保护;明确注明是否有运行时复现。
- 待验证风险:存在不一致或覆盖缺口,但还不能确定用户可见问题。
- 已覆盖且未发现问题:阅读实现并核对已有测试,本次验证通过;不代表所有设备和操作组合均已验证。
- 范围外事项:仅记录边界,不在本轮安排实现。
- P1 优先处理错误状态回写;P2 处理交互、规范与测试遗漏;P3 处理需测量后才能决定的性能问题。
2. 近期修改与关联检查
| 提交 |
修改主题 |
关联检查 |
896126e |
溢出菜单半透明背景 |
渐变不扩大遮挡,菜单可点击,末尾操作可完整露出 |
aa7880b |
预览代码块不自动换行 |
长行横向滚动,缩放和复制保留源码 |
5e5a4df |
透出渐变下方按钮 |
滚动区域和固定菜单重叠时的操作可达性 |
2f12f8e |
隐藏工具提示渐变 |
滚动、尺寸和按钮数量变化后的溢出状态 |
61d31aa |
预览、差异标题配色 |
六级标题、明暗主题、围栏、Setext 与增删背景叠加 |
3b10f61 |
相邻差异块连续导航 |
共享首尾滚动位置、手动滚动、换行及缩放后的导航 |
f086594 |
双图标开关普通背景 |
图标表达当前状态,两种状态均不添加高亮背景 |
ea22e1e |
统一状态图标 |
单图标开关启用高亮,长按提示状态,同类控件一致 |
c6f15ef |
编辑、预览双指缩放 |
选区、焦点、撤销历史、链接误触、控件尺寸及仓库隔离 |
cceda25 |
历史索引缓存 |
基准加载失效、缓存不可用与恢复路径;不审查同步协议 |
3d2c6c4 |
优先恢复缓存差异 |
首页可响应,差异恢复不等待无关启动任务 |
ee80d37 |
差异恢复期间可操作 |
不闪现预览,退出加载模式后旧请求不回写 |
d58a443 |
Markdown 语法高亮 |
原始文字、输入法组合区、差异背景、未知语言和大文档回退 |
349a44a |
差异会话和缩放持久化 |
标签与仓库隔离、恢复滚动、基准重读、正文缩放不持久化 |
4bfc552 |
绘制前缩放补偿 |
同帧滚动修正,松手后不跳回,边界与重排允许必要偏差 |
2ba9141 |
触点锚定差异缩放 |
横纵向补偿,行号与正文缩放,共用组件对首页的影响 |
2.1 检查方法
- 按“近期修改 → 共用逻辑 → 三种视图调用路径 → 现有测试”追踪,不仅检查提交改动行。
- 编辑、预览由
NoteContent 使用标签持有的正文、历史和滚动控制器。
- 只读差异由
CurrentDifferenceView 使用标签的差异会话和当前正文。
home_view.dart 连接模式选择、提示、保存和源码跳转。
difference_actions.dart 管理历史基准及视图切换,区分基准请求与差异计算任务。
- 正文缩放与差异缩放都复用
DifferenceZoom,但使用独立的仓库级比例;当前差异与文件树差异共用差异比例。
- 核对共用调用方,包括模式按钮、恢复标签、差异时间变化、收藏与文件树返回首页。
3. 按优先级排列的问题清单
A01 · P1 · 手动差异请求可覆盖后来选择的模式
- 状态:确认问题,静态调用链确认;本轮未增加延迟加载复现测试。
- 位置:
lib/difference_actions.dart:70,关联 lib/home_view.dart:125。
- 证据:
_showCurrentDifference 等待基准后检查挂载、活动标签、仓库和筛选快照。
- 只有
restoring == true 时检查标签是否仍处于差异模式。
- 手动进入差异使用默认
restoring == false;等待期间切回编辑或预览,不会使上述检查失效。
- 基准返回后仍设置
tab.difference = true,并安排会话持久化。
- 触发时序:同一标签手动点击差异 → 基准读取尚未完成 → 点击编辑或预览 → 旧基准成功返回。
- 影响:用户最新选择被覆盖;错误模式可能随后写入会话。此项未发现正文被修改或丢失的证据。
- 最小修复建议:为标签的模式与差异基准请求记录有效请求代次;切换模式、切换标签/仓库、改变差异时间或发起新请求时使旧请求失效,返回结果仅允许当前请求提交。
- 验收:延迟旧请求返回不改变新模式、不写入旧基准;普通手动进入、恢复模式及历史补齐后重试仍正常。
- 关联说明:差异计算内部已有
_generation 保护,但它不保护页面层的历史基准请求,不能据此判定本项已覆盖。
A02 · P1 · 开启编辑差异的旧请求可重新启用已关闭的高亮
- 状态:确认问题,静态调用链确认;本轮未增加运行时复现测试。
- 位置:
lib/difference_actions.dart:105,关联 lib/home_page.dart 的 _applyFileFilter。
- 证据:
_showEditDifference 等待基准后只校验基准非空、页面挂载及活动标签相同。
_applyFileFilter 关闭差异时间时清除标签的差异模式、编辑差异开关和基准。
- 旧开启请求没有筛选快照或请求有效性检查,返回后仍设置
editDifference = true 和旧基准。
- 相邻的
_refreshEditDifference 已校验仓库、筛选与开关状态;首次开启路径缺少对应保护。
- 触发时序:点击开启编辑差异 → 等待历史 → 在文件筛选中关闭差异时间或改用另一时间 → 旧历史成功返回。
- 影响:重新出现已关闭的高亮,或使用旧时间基准;若此时已进入只读差异,旧请求还会设置
difference = false。
- 最小修复建议:与 A01 共用请求失效机制,记录开启意图及差异时间;关闭开关、修改时间和选择新模式时失效旧请求。首次开启时开关尚未为真,不能仅增加
!tab.editDifference 判断。
- 验收:关闭时间、改时间、切换视图及重复开启后的乱序返回均不恢复旧状态;编辑与预览中开启高亮仍保持原模式。
- 关联说明:这一开启路径在近期修改前已存在;属于与近期恢复和状态规范相关的遗漏,不认定为最近提交新引入的回归。
A03 · P2 · 忙碌、同步期间的模式入口策略需核实
- 状态:待验证风险;不能仅因禁用条件不同就认定为缺陷。
- 位置:
lib/note_toolbar.dart:87、:112,lib/note_content.dart,lib/home_view.dart:405。
- 证据:
- 内嵌编辑入口以
!busy 控制,外层模式选择始终接收 onModeChanged。
- 编辑输入、撤销重做、保存和操作菜单使用忙碌与同步保护。
- 预览双击返回编辑检查忙碌与同步;当前差异的跳转回调未传入相同条件。
- 验证方法:分别在保存等待、同步期间和差异恢复期间操作三个模式入口及双击跳转,观察模式、焦点、正文和保存目标。
- 影响:可能存在入口表现不一致;是否影响数据安全尚未验证。
- 最小修复建议:根据复现结果,仅对需要阻止的操作统一入口与回调保护,保留差异恢复期间退出加载和切换标签的能力;不默认将所有浏览操作禁用。
- 验收:不能通过另一入口绕过已规定的禁用行为;保存目标、未保存正文和历史不受模式切换影响。
A04 · P2 · 模式按钮内边距与文档不一致
- 状态:参数与文档差异已确认;实际布局影响待验证。
- 位置:
lib/note_toolbar.dart:79;FEATURES.md 3.3。
- 证据:模式按钮声明横向 6、纵向 25 的内边距;功能说明要求模式与保存按钮内边距为 8 像素。保存按钮使用 8 像素。
- 验证方法:测量横竖屏下模式组、内嵌编辑开关和保存按钮的实际边界,覆盖默认及放大系统文字;检查是否存在布局约束、裁切或命中区域变化。
- 影响:可能增加竖屏工具栏高度,压缩正文空间;本轮不以参数直接推导最终渲染高度。
- 最小修复建议:测量后按文档调整紧凑内边距;保留模式组内部编辑差异开关的可用空间,并同时验证点击和无障碍语义。
- 验收:文档与实现一致;横屏工具栏不增高,竖屏不浪费正文高度,按钮可操作且无溢出。
A05 · P2 · 工具栏动态操作与无障碍组合覆盖不足
- 状态:待验证风险,已确认现有专门溢出测试覆盖范围有限。
- 位置:
test/note_toolbar_test.dart、lib/edit_mode_menu.dart、lib/home_view.dart。
- 证据:
- 溢出测试使用横屏配置,验证滚动、半透明菜单、末尾操作及 260/700 宽度变化。
- 尚未在该测试中组合验证编辑/预览/差异切换、拍照按钮显隐及不同主题和系统文字缩放。
- 横屏布局测试覆盖横竖屏和窄窗口;安全区域测试覆盖键盘 inset,但不等同于三种视图的完整布局验证。
- 编辑入口使用
GestureDetector,还需实测语义树与键盘可达性,不能仅凭有 Tooltip 判定无障碍通过。
- 验证方法:改变模式、拍照能力、窗口尺寸及系统文字缩放,检查渐变更新、保存和菜单可达性;检查模式与开关的语义名称、状态和操作。
- 最小修复建议:出现失败时扩展现有工具栏或布局测试,并复用 Flutter 控件或补必要语义;不新增一套工具栏抽象。
- 验收:操作数量与尺寸变化后渐变及时更新;末尾按钮可完整露出;状态提示正确;无布局异常和不可达操作。
A06 · P3 · 大文档标题配色的重复解析需测量
- 状态:待验证风险,无性能缺陷结论。
- 位置:
lib/current_difference_view.dart 的 build 与 lib/difference_rows.dart:10。
- 证据:差异结果已缓存,但构建视图时仍调用
differenceHeadingLevels,从完整新旧行重建文本并提取标题;导航、换行和缩放重建也经过该路径。
- 验证方法:在较大笔记中记录缩放、换行及连续导航时的解析次数和帧耗时,区分首次差异计算与后续标题解析。
- 最小修复建议:仅在测量证明开销明显时,随完整差异结果缓存标题级别;保持源码变化时失效、明暗主题实时取色,不引入新的缓存框架。
- 验收:交互不反复解析相同完整源码,标题级别、增删背景和主题颜色仍正确。
4. 已覆盖且未发现问题
以下结论限于代码阅读和现有自动测试,未作 Android/iOS 真机完整验收。
| 核心行为 |
实现与已有测试证据 |
| 输入法、撤销重做与选区 |
editor_history_test.dart 覆盖组合输入、连续输入合并、剪切粘贴、选区恢复及标签历史隔离 |
| 语法高亮与编辑差异叠加 |
syntax_highlight_test.dart、note_tabs_test.dart 覆盖源码保留、组合区下划线、明暗样式和差异背景;实现有大文档及代码块阈值回退 |
| 编辑差异开关保持原模式 |
note_tabs_test.dart 验证组件中切换开关不激活编辑段,并验证启用背景对比度;不覆盖 A02 的异步开启时序 |
| 草稿与保存隔离 |
标签持有独立正文与 savedText;保存捕获目标标签、仓库和正文;landscape_header_test.dart 覆盖保存及未保存状态,标签与会话测试覆盖草稿恢复和仓库快照隔离 |
| 编辑、预览滚动恢复 |
note_tab_scroll_test.dart 分别验证标签的编辑与预览位置;控制器使用最新标签偏移重新挂载 |
| 预览源码定位及差异高亮 |
preview_difference_test.dart 覆盖混合 Markdown、嵌套列表、Setext、引用、表格及纯删除不高亮;源码范围不匹配时不猜测定位 |
| 长代码行与缩放 |
note_content_zoom_test.dart 验证不同缩放下围栏代码不自动换行且可横向滚动;code_block_test.dart 覆盖语言、高亮和代码内容 |
| 正文缩放状态 |
note_content_zoom_test.dart 覆盖触点锚定、选区保留、链接误触与非线性文字缩放;tab_session_controller_test.dart 验证仓库隔离、运行期保留及不持久化 |
| 标题配色与差异背景 |
heading_highlight_test.dart 验证六级标题、明暗主题、围栏和新旧版本级别,以及差异行内背景 |
| 差异恢复与过期计算 |
difference_loading_test.dart 验证启动不挂载预览、无基准仍可操作,以及大型差异丢弃旧计算;历史基准层的 A01/A02 需单独补验证 |
| 差异会话与浏览位置 |
difference_session_test.dart 覆盖重启、仓库隔离、精简/换行、浏览位置及无效值回退;比例与正文缩放独立 |
| 相邻差异块连续导航 |
difference_navigation_test.dart 覆盖精简/完整、两种视口高度、共享首尾滚动位置及到头提示 |
| 差异缩放与跳转 |
difference_zoom_test.dart、difference_views_test.dart 和文件树导航测试覆盖共用组件及返回首页;不据此宣称忙碌状态和多指双击组合全部通过 |
| 状态图标与紧凑布局 |
state_icon_test.dart 验证双图标状态普通背景;标签、预览标题和横屏布局测试覆盖各自入口;A05 的组合覆盖仍待补充 |
| 确认、提示和快捷键 |
使用 Flutter 对话框、toast/ScaffoldMessenger;历史快捷键按当前平台显示,保留模式选择组件和展开箭头的既有表达 |
5. 后续实施与验收方案
5.1 顺序与边界
- 优先复现 A01/A02,使用可控制完成顺序的历史加载测试,覆盖旧请求最后返回和切换后又返回原状态的时序。
- 对相关基准请求实施统一失效保护,沿用标签状态归属,不修改公开接口和会话磁盘格式。
- 核实 A03–A05,只有确认失败后才修改入口或布局,并同步更新对应
FEATURES.md 内容。
- 对 A06 先测量;未发现明显开销时保留实现。
- 每项修复复用已有测试文件,补最小复现用例,运行相关测试、
flutter analyze 和 flutter test。
5.2 验收矩阵
- 状态:编辑、预览、只读差异;编辑差异开/关;精简/完整;换行开/关;干净/未保存正文。
- 异步:历史可用、缺失、延迟、失败及补齐;等待时切模式、改时间、关闭差异、切标签/仓库和关闭标签;重复请求乱序返回。
- 内容:空文档、长代码行、六级标题、Setext、未闭合围栏、嵌套列表、表格、图片与链接、相邻差异块、纯新增/删除及大文档。
- 交互:保存当前标签、撤销重做、输入法组合、双击源码定位、双指缩放/移动/取消和恢复单指操作。
- 布局:横竖屏、窄宽窗口、明暗主题、系统文字放大、键盘与底部安全区域;模式、保存和菜单均可达。
- 会话:切换标签与仓库、重启恢复模式和差异浏览位置;正文比例运行期保留、重启归 100%,差异比例按原规范持久化。
- 数据:所有浏览和定位操作不改正文;保存只写预定目标;旧历史基准不进入新状态或会话。
5.3 维护约束
- 保留现有注释、日志和调试产物,复杂失效时序需解释设计决策。
- 本轮检查的主要视图与共用组件未发现需要仅因 600 行规则而立即拆分的情况;Markdown 文档不受该规则限制。
- 若后续修改需要提取模块,按内聚职责集中安排,保留原行为,不为单次增量零散拆分。
- 不增加重复的状态、缓存框架、工具栏控件或无关依赖。
- 发现兼容性需求时先询问是否支持,再安排兼容实现。
- 后续代码修改若需要重启应用生效,交付时明确说明;本轮仅文档,无需重启。
6. 验证记录与范围外事项
6.1 已执行验证
- 方案阶段在同一代码基线上执行:
flutter analyze:无问题。
flutter test:211 项通过。
- Git 工作区:干净。
- 文档完成后在 2026-10-04 重新执行:
flutter analyze:无问题。
flutter test:211 项通过。
- 文档编码检查:有效 UTF-8,无 BOM,无 CR,使用 LF 换行。
- 文档规范来源的相对链接:均存在。
- 提交前检查:仅新增本文件;暂存内容执行
git diff --cached --check。
- 本轮不新增业务代码或测试;因此尚未通过新增测试复现 A01/A02,也未运行 A03–A06 的完整组合矩阵。
6.2 范围外与环境限制
- 仓库管理、账号与登录、同步协议和其他页面的全面规范检查不在本轮范围。
- Android/iOS 真机布局、输入法和系统无障碍完整验收未执行。
- 按项目约定跳过
flutter build apk 等 Gradle 打包命令:当前 Windows 环境已有 Java Selector.open() loopback 连接失败记录,环境未变化且用户未要求重试。
- 打包未验证;不将此环境限制作为代码缺陷。
- 本轮只提交此新增文档;后续修复另行按问题清单实施。