鸿蒙 PC Markdown 编辑器状态一致性:脏标记、修订号与保存基线

发布时间:2026/7/21 2:24:17
鸿蒙 PC Markdown 编辑器状态一致性:脏标记、修订号与保存基线 鸿蒙 PC Markdown 编辑器状态一致性脏标记、修订号与保存基线编辑器状态不是一个isDirty布尔值。正文可能等于打开基线、恢复基线或保存请求时快照保存期间还可以继续输入多标签各有 URI、格式、revision和撤销历史ArkUI与 ArkWeb分别保存一部分状态。任何一处基线归属错误星号、恢复记录和关闭判断就会互相矛盾。本文基于 OhMarkdown分析 CodeMirror Text基线、forcedDirty、revision、DocumentSession同步和保存提交条件。代码位于 https://gitcode.com/VON-/codex_md_oh三种状态事实文件事实URI、磁盘正文、BOM、换行。编辑事实CodeMirrorEditorState.doc、选择、历史、pendingDirty、documentRevision。UI事实活动 session、标签星号、状态栏、字数和模式。UI只能投影前两类不能反过来驱动。例如状态栏写 Saved不代表磁盘一定提交关闭必须检查 dirty和 revision。保存基线使用 TextletbaselineDocument:Text;pendingDirtyforcedDirty||!update.state.doc.eq(baselineDocument);打开文档后 baseline指向初始 CodeMirror Text。输入产生新 state不等于基线则脏撤销回完全相同 Textdirty自动 false。结构化Text.eq避免每键生成完整字符串。如果只在首次输入设 true撤销回基线仍显示星号。基线比较把 dirty从事件历史改成当前事实。forcedDirty 表达未持久化恢复恢复正文创建 state后与 baseline相等但它来自沙箱草稿外部文件未包含。初始化baselineDocumenteditor.state.doc;forcedDirtyrecovered;pendingDirtyrecovered;forcedDirty让恢复文档始终脏直到显式保存。普通文本相等无法表达持久化来源因此需要独立事实。保存成功清 forcedDirty丢弃删除记录切换会话保存和恢复该字段。否则恢复标签切走回来可能错误变干净。revision 只在正文变化时增加EditorView.updateListener.of((update){if(!update.docChanged){return;}documentRevision1;// dirty、预览、通知、恢复});选择、滚动和主题不会增加 revision。它表示内容版本不是任意 UI事件计数。恢复快照携带 revision保存开始记录 snapshotRevision。ArkUI也维护活动文档 revision用 Bridge回调同步。当前两端计数路径需要谨慎onChange会递增原生 revisiononSnapshot携带 Web revision。长期更强协议应让 Web revision成为唯一内容版本并随每条消息发送减少双计数漂移。保存请求固定 Text快照if(commandsave){flushRecoverySnapshot();pendingSaveDocumenteditor.state.doc;}constcontentcommandsave?editor.state.sliceDoc():;用户按 CtrlS时固定 Text和字符串。原生异步写入这份正文。保存期间的新输入进入新的 EditorState不会改变pendingSaveDocument。写成功后baselineDocumentpendingSaveDocument??editor.state.doc;pendingSaveDocumentundefined;forcedDirtyfalse;pendingDirty!editor.state.doc.eq(baselineDocument);若没有新输入当前等于保存快照变干净若有新输入磁盘虽成功当前仍脏。使用完成时当前 doc作为基线会误把新输入标为已保存。原生层再次比较 revisionif(this.documentRevisionsnapshotRevision){this.documentDirtyfalse;this.operationStatusSaved;this.clearRecoveryDraft();}else{this.operationStatusModified;}Web基线和原生 revision形成双防线。只有保存请求版本仍是当前版本才清 dirty和恢复草稿。否则保留恢复保存并关闭也不会提交。两端判断结果必须一致测试在保存期间输入可发现分歧。长期可让 markSaved接收已保存 revisionWeb自行比较同一编号。DocumentSession 是原生快照exportinterfaceDocumentSession{id:string;uri:string;name:string;content:string;persistedContent:string|undefined;format:DocumentFormat;revision:number;dirty:boolean;wordCount:number;largeDocumentMode:boolean;}content是最近捕获缓冲区persistedContent是打开/保存后的磁盘基线。两者相同不等于格式相同format独立保存。dirty和 revision必须与 content同一次同步更新。标签栏读取每个 session.dirty页面字段只代表活动会话。后台标签不能读取全局documentDirty。切换前捕获切换后应用awaitthis.captureActiveDocumentSession();this.applyDocumentSession(targetSession);awaitthis.activateEditorSession(targetSession);顺序防止甲正文写进乙。capture从 Web读取并 JSON解码失败使用原生旧 content。apply一次恢复 URI、正文、persisted基线、格式、revision、dirty、字数和大文档模式。只切正文不切格式会导致 CRLF串线只切 dirty不切 baseline撤销判断错误只切原生不切 EditorState历史串线。Web会话保存业务状态editorSessions.set(activeSessionId,{state:editor.state,baselineDocument,forcedDirty,pendingDirty,documentRevision,lastRecoveryRevision});完整 EditorState隔离正文、选择和历史额外字段隔离保存与恢复。切换清除旧 bridgeTimer和 recoveryTimer避免延迟事件归属新活动 id。激活后 Web主动回报 wordCount和 pendingDirty让原生投影重新对齐。状态同步不是只在用户输入时发生。撤销回基线的闭环Playwright设置“基线”输入“修改”undo等待 Bridge最后回调 dirty false。它验证 EditorState transaction、Text.eq、通知防抖和原生协议语义。保存后基线测试输入“已保存”request save、markSaved再输入“后续”并撤销dirty回 false。这证明基线更新到实际保存快照而不是初始打开内容。外部文件基线保存前重新读取磁盘与 persistedContent和 documentFormat比较。外部变化时不写也不更新基线。用户 Reopen后才建立新磁盘基线。persistedContent为 undefined表示恢复记录关联 URI但磁盘读取失败不能做可靠冲突比较。保存策略应保守提示未来提供 Save As。空字符串是真实空文件基线不能与 undefined混淆。恢复记录清理条件dirty false时 onEditorChange会清恢复草稿保存成功且 revision相等清用户明确 Discard清。保存失败、选择器取消、恢复后切标签都不应清。generation防止正在写的旧快照在清理后复活。状态一致性包括异步文件生命周期不只内存变量。UI 投影标签星号来自 session.dirty底部状态来自 operationStatus格式来自 active format字数来自 Web回报。下图中活动标签、星号和底部 Modified一致。测试应制造不一致压力快速切换、保存中输入、恢复后撤销、后台标签关闭、ArkWeb重载。截图只能观察结果自动化比较每层字段。状态机不应靠字符串当前 operationStatus是字符串但业务判断不读取它。后续可定义枚举DocumentOperationState与附加 errorUI本地化显示。dirty、operation和 conflict是正交维度不应塞进一个枚举造成组合爆炸。例如文档可 dirty且 Saving也可 dirty且 SaveFailed标签星号继续显示状态栏显示操作。结构化状态能表达这种组合。多标签恢复的下一步当前恢复重点活动标签。要持久化所有脏会话应为每项保存 sessionId、URI、content、format、revision和时间启动后重建数组。总容量、淘汰、重复 URI和用户选择需设计。不能只循环写同一个current-document.json最后一项会覆盖前面。恢复集合也要原子提交或每会话独立文件加索引。当前边界原生与 Web revision仍有双计数完整多标签跨进程状态未实现选择/滚动不持久化外部冲突没有三方比较operationStatus未结构化保存期间并行会话操作由全局互斥限制。结语状态一致性依赖明确基线CodeMirror Text表示保存内容forcedDirty表示恢复来源revision保护异步保存DocumentSession保存原生会话EditorState快照隔离历史persistedContent与 format表示磁盘事实。鸿蒙 PC编辑器只有在输入、撤销、保存、切换、恢复和失败后都让这些事实保持一致标签星号和“Saved”才值得用户相信。