资讯详情

资讯详情

MooTool Compose 端自动 Git Pull 后的 Vault 树刷新:DIFF-408 的 tick 通知机制深度解析

桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载导读本篇文章聚焦 MooToolnext-compose桌面实现中一个关键的状态同步问题VaultJSON 文档库与随手记文档库在定时自动 Git pull 成功后如何让 Vault 树与干净编辑器立刻感知磁盘变化并完成重载。DIFF-408 通过引入「Vault 树刷新 tick」通知机制把自动 pull 与手动 Git 面板、刷新按钮统一到同一条刷新信号链路上补齐了 Compose 端此前依赖VaultRevisionMonitor但缺少显式对齐刷新信号的空档。读完本文你将掌握该机制的调用链、源码实现、判定规则与测试验证方式可直接在 Compose Desktop 工程中复现或扩展同类模式。背景自动 pull 与 UI 刷新之间的信号缺口MooTool 的 Electron 实现中pullJsonVault/pullQuickNoteVault在 pull成功或进入 merge/冲突态后会通过broadcast(*-vault:changed)事件驱动 Vault 树加载与干净编辑器重载Composenext-compose端则依赖VaultRevisionMonitor轮询来发现外部写入。然而Compose 的自动 pull完成后并没有显式的刷新信号 —— 树中看不到远程新增/删除的文件编辑器也得不到重载提示。这与手动 Git 面板onVaultRefresh/persistFilter的行为不一致构成了一个明确的交互缺口。DIFF-408 的目标正是补上这个缺口让自动 pull 成功或进入 merge/冲突态时主动触发与手动刷新完全一致的「重抓 snapshot persistFilter」链路。核心行为设计DIFF-408 定义了三层协作关系判定层VaultGitAutoPull.shouldNotifyVaultAfterPull负责回答「本次 pull 结果是否需要通知 UI」判定条件为 pull 成功pullResult.success或 pull 后进入merging/conflicts 0状态。通知层AppContainer.notifyJsonVaultTreeChanged()/notifyQuickNoteVaultTreeChanged()分别递增 JSON 与随手记的 tick 计数模拟 Electron 的broadcast(json-vault:changed)/broadcast(quick-note-vault:changed)。该 tick 与手动 Git 刷新DIFF-415共用。消费层JSON / 随手记屏的LaunchedEffect观察到 tick 变化后在 IO 线程重抓文档库snapshot随后调用persistFilter()含干净时重载当前文件、递增 Git 角标 rev 等副作用。这三层形成了「判定 → 通知 → 重载」的完整闭环保证无论刷新信号来自自动 pull、手动 Git 面板还是刷新按钮UI 都走同一条刷新路径避免多套逻辑分叉。源码级实现拆解1. 判定函数shouldNotifyVaultAfterPull判定逻辑实现在 VaultGitAutoPull.kt/** Electron pull*Vaultbroadcast(*-vault:changed) after success or merge/conflict state. */ fun shouldNotifyVaultAfterPull(pullResult: GitActionResult, afterStatus: GitStatus): Boolean pullResult.success || afterStatus.merging || afterStatus.conflicts 0该函数接受两个参数pullResultGitActionResult定义于 GitEngine.kt仅含success与message两个字段afterStatuspull之后重新执行GitEngine.status(root)得到的GitStatus定义于 GitEngine.kt携带merging、conflicts、changes、remote等字段。注意其语义对齐了 Electron即使 pull 命令本身失败只要事后工作区进入了 merge 或冲突态例如远端带来冲突也要通知 UI—— 因为冲突态下需要重载 snapshot 以展示冲突文件反之若 pull 失败且工作区仍干净则不通知避免无谓重载。2. 通知层tick 递增AppContainer.kt 中两个通知函数分别递增各自的 tick 状态/** Electron broadcast(json-vault:changed) → Vault 面板 load() 干净编辑器 reloadSelectedFromDisk。 */ fun notifyJsonVaultTreeChanged() { _jsonVaultAutoPullTick.value 1 } /** Electron broadcast(quick-note-vault:changed) 同上。 */ fun notifyQuickNoteVaultTreeChanged() { _quickNoteVaultAutoPullTick.value 1 }tick 是单调递增的 Long 状态量UI 通过collectAsState()观察。除了自动 pull以下场景也复用同一 tick详见 DIFF-415 与 DIFF-416JSON/随手记 Git 面板的onVaultRefresh回调Vault 面板的「刷新」按钮与 JSON 更多菜单中的「刷新」入口见 JsonScreen.ktVaultRevisionMonitor磁盘监视回调DIFF-416reloadToolSessionsFromStore()备份恢复/跨产品导入后同时调用两个通知函数AppContainer.kt。3. 自动 pull 的完整调用链自动 pull 由VaultGitPullScheduler定时驱动其实现位于 VaultGitCheckpointScheduler.kt。该调度器支持enabled、hasUnsavedEditorChanges、intervalMilliseconds、pull等 lambda 注入并提供resetIntervalClock()在设置变更时从下一周期重新计时。在 AppContainer.kt 中JSON 与随手记各注册了一个调度器实例private val notePullScheduler VaultGitPullScheduler( enabled { _settings.value.vault.autoPullMinutes 0 }, // ... intervalMilliseconds { _settings.value.vault.autoPullMinutes.coerceIn(0, 1440) * 60_000L }, pull { runScheduledVaultPull(noteVault().root(), forJson false) } ) private val jsonPullScheduler VaultGitPullScheduler( enabled { _settings.value.vault.autoPullMinutes 0 }, // ... intervalMilliseconds { _settings.value.vault.autoPullMinutes.coerceIn(0, 1440) * 60_000L }, pull { runScheduledVaultPull(jsonVault.root(), forJson true) } )关键参数autoPullMinutes自动 pull 间隔分钟0表示关闭上限被coerceIn(0, 1440)限制为 24 小时编辑器脏存在未保存改动时由调度器的hasUnsavedEditorChanges单独拦截不执行 pull当autoPullMinutes设置变化时两个调度器调用resetIntervalClock()重设计时起点AppContainer.kt。实际的拉取与通知逻辑集中在 runScheduledVaultPullprivate fun runScheduledVaultPull(root: Path, forJson: Boolean): GitActionResult { val status GitEngine.status(root) if (!VaultGitAutoPull.mayPullCleanWorkingTree(status)) { return GitActionResult(true, skipped) } val result GitEngine.pull(root, token _settings.value.vault.gitToken) val after GitEngine.status(root) if (VaultGitAutoPull.shouldNotifyVaultAfterPull(result, after)) { if (forJson) notifyJsonVaultTreeChanged() else notifyQuickNoteVaultTreeChanged() } return result }这里完整呈现了 DIFF-408 与前置 DIFF-407 的衔接pull 之前先用mayPullCleanWorkingTree校验工作区前置条件仓库可用、已配置 remote、无 merge、无冲突、changes为空满足才真正执行GitEngine.pullpull 之后再依据shouldNotifyVaultAfterPull决定是否发通知。从源码结构看这两步「事前校验 事后通知判定」构成一个可独立单测的纯函数对。4. 消费层LaunchedEffect重抓 snapshotJSON 屏的消费逻辑位于 JsonScreen.ktval jsonVaultAutoPullTick by container.jsonVaultAutoPullTick.collectAsState() LaunchedEffect(jsonVaultAutoPullTick, settings.vault.hideGitignoredFiles) { if (jsonVaultAutoPullTick 0L) returnLaunchedEffect snapshot withContext(Dispatchers.IO) { container.jsonVault.snapshot(settings.vault.hideGitignoredFiles) } persistFilter() }随手记屏的对应逻辑几乎相同QuickNoteScreen.kt。设计要点tick 初始为0L作为「从未发生过刷新」的哨兵值LaunchedEffect首帧不会触发重载避免启动时重复抓取snapshot 抓取在Dispatchers.IO上执行避免阻塞 UI 线程persistFilter()定义见 JsonScreen.kt在干净条件下重载当前文件jsonVaultReloadOpenFileIfClean并递增filterRev与gitCountRev驱动 Git 角标rememberVaultGitChangeCount重算hideGitignoredFiles同时作为LaunchedEffect的 key切换该设置时也会重抓 snapshot复用同一刷新链路。与 Electron 实现的逐点对齐DIFF-408 的所有判定规则都能在 Electron 主进程代码 next/electron/main/index.ts 中找到对应实现async function pullJsonVault(): Promisevoid { if (jsonVaultEditorDirty) return const service createVaultGitService() const status await service.status() if (!status.repository || !status.remote || status.merging || status.conflicts 0 || status.changes.length 0) return const result await service.action({ action: pull }) const updatedStatus await service.status() if (result.success || updatedStatus.merging || updatedStatus.conflicts 0) broadcast(json-vault:changed, ) }pullQuickNoteVault结构相同index.ts仅广播事件名不同。对应关系如下表Electron 行为Compose 对应实现编辑器脏直接返回VaultGitPullScheduler.hasUnsavedEditorChanges拦截status.repository/remote/merging/conflicts/changes前置校验VaultGitAutoPull.mayPullCleanWorkingTreeDIFF-407pull 后重查 status 并判result.success \|\| merging \|\| conflicts 0VaultGitAutoPull.shouldNotifyVaultAfterPullbroadcast(json-vault:changed)/broadcast(quick-note-vault:changed)notifyJsonVaultTreeChanged()/notifyQuickNoteVaultTreeChanged()递增 tick定时器configureJsonVaultAutoPull/configureQuickNoteVaultAutoPullautoPullMinutes * 60_000VaultGitPullSchedulerintervalMilliseconds定时配置方面Electron 在 index.ts 中通过setInterval(..., settings.vault.autoPullMinutes * 60_000)实现autoPullMinutes 0时不建定时器Compose 的enabledlambda 与之语义一致。测试与验收DIFF-408 的验收覆盖 A03 / F01/F04 的 Vault Git 场景主要落在两个测试类VaultGitAutoPullTestVaultGitAutoPullTest.kt验证纯函数判定逻辑allowsPullWhenRepositoryClean干净仓库允许 pullskipsWhenLocalChangesOrConflictOrMerge本地有变更、存在冲突、正在 merge、未配置 remote 时均拒绝 pullnotifiesVaultAfterPullOnSuccessOrMergeStatepull 成功后通知、pull 失败但进入 merge 态时通知、pull 失败且工作区干净时不通知 —— 恰好覆盖shouldNotifyVaultAfterPull的真值表。VaultTreeRefreshNotifyTestVaultTreeRefreshNotifyTest.kt验证 tick 通知行为notifyIncrementsVaultTreeRefreshTicks初始 tick 为0L调用notifyJsonVaultTreeChanged()/notifyQuickNoteVaultTreeChanged()后各自递增为1LreloadToolSessionsFromStoreNotifiesVaultTrees备份恢复等场景会同时递增两个 tick。运行方式沿用 Compose 工程的标准离线测试命令./gradlew :composeApp:desktopTest --offline该工程还配套了 Vault Git 检查点调度器测试VaultGitPullSchedulerTest用于覆盖定时器的使能与重计时行为。小结与扩展阅读DIFF-408 本质上是把「自动 pull 结束事件」翻译成一个可观察的 tick 状态再复用手动刷新已有的 snapshot 重抓链路从而以最小改动闭合了「pull 成功 → 树与编辑器同步」这一产品路径。它与其兄弟 DIFF 共同构成了 Compose Vault Git 刷新机制的完整拼图DIFF-407Vault 自动 pull 对齐 Electron 工作区前置条件mayPullCleanWorkingTree事前校验DIFF-415手动 Git / 刷新 Vault 重载文档库 snapshot手动路径并入同一 tickDIFF-416Vault 磁盘监视触发文档库树 snapshot 刷新磁盘监视并入同一 tick。对后续维护者而言若要新增一种「Vault 可能已变化」的触发源只需在对应时机调用notifyJsonVaultTreeChanged()/notifyQuickNoteVaultTreeChanged()UI 侧的LaunchedEffect会自动完成 snapshot 重抓与过滤持久化无需改动编辑器逻辑 —— 这正是该 tick 机制的核心价值。赞分享桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载相关推荐MooToolCompose 版Vault Git 丢弃确认与工作区刷新机制深度解析MooToolCompose 版Vault Git 丢弃确认与工作区刷新机制深度解析 本篇技术指南围绕 MooTool 下一代 Compose 桌面端 DI桌面应用开发工具MooTool Next Compose Vault Git 中止合并确认机制解析DIFF-108MooTool Next Compose Vault Git 中止合并确认机制解析DIFF 108 本文以 MooTool 仓库中 next compose桌面应用开发工具MooTool Next-Compose 备份恢复后的 Vault 树刷新机制从 sessionGeneration 到 *-vault:changed 信号对齐MooTool Next Compose 备份恢复后的 Vault 树刷新机制从 sessionGeneration 到 vault:changed 信号对齐桌面应用开发工具上一篇AI-For-Beginners 人体分割实验室用神经网络模型从视频画面中抠出人体轮廓下一篇ModOrganizer2游戏报错怎么办快速解决MO2运行失败的实用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →