首页 / 资讯中心 / 文章详情

MooTool(Compose 桌面版)F 工具引擎接线:WiringPresentation 守卫模式、随手记 Vault 底栏与命令盘深链导航实现解析

MooTool(Compose 桌面版)F 工具引擎接线:WiringPresentation 守卫模式、随手记 Vault 底栏与命令盘深链导航实现解析 ★ FEATURED ARTICLE
桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载导读本文以 DIFF-556 设计文档为主体剖析 MooTool Compose 桌面版在单一 diff 切片中完成的四类工作九个 F 工具的引擎接线与工具栏操作启用守卫*WiringPresentation纯函数层、随手记QuickNoteVault 底栏的路径/脏标记/复制守卫、五个 CSS 风格组件的落地以及命令盘Command Palette中工具与设置类别的深链导航关键词。读完本文你将理解 MooTool 如何用可单测的 Presentation 层 引擎层 Screen 接线层的分层方式推进功能落地以及如何用一条 Gradle 命令闭环验证全部改动。一、背景DIFF 切片推进与 parity-gap 上下文DIFF-556 是 MooTool Compose 版next-compose模块一系列增量切片中的一环。按其自身说明前一条 DIFF-555 已经完成了 F10/F13/F14/F19 四个工具的引擎接线、JSON 列编辑 wrap notice、JsonVaultFooterPresentation、更新/托盘链路以及 crypto/vault 相关 CSS因此本条明确不重复以下内容Crypto / Encode / Host / MessageBoard 四工具的接线JSON 列编辑EditorHost 语义与 Json 底栏Update / Tray 链路。同时文档在背景处保留了对外部差异清单parity-gap的承诺状态仍有六套 CSS 逐选择器皮肤、产品主窗 Tab/IME/TCC 手工 PNG、P7 三平台安装、以及部分 F 工具 substantial实质性缺口未达成。这一点说明 DIFF-556 的定位是稳步补齐非 metadata 层面的工具引擎链路而非一次性完成全部 parity 目标。从仓库实际结构看wiring 一词对应的是desktopMain与commonMain中的一批*WiringPresentation对象以及各features/*目录下的 Screen。这个命名约定在本条之前DIFF-555已经确立DIFF-556 只是把同一套模式扩展到其余九个工具。二、核心模式Presentation 守卫 引擎 Screen 接线三层分工要读懂 DIFF-556先要理解它反复强调非 metadata的含义。MooTool Compose 版的工具逻辑被拆成三个层次引擎层Engine如ColorEngine、CalculatorEngine、CronEngine、RegexEngine、UaEngine、TimeEngine、DiffEngine、ConfigEngine、ImageEngine——只负责纯计算/转换不感知 UI。Presentation 层Wiring Presentation以object形式暴露一批纯函数提供工具栏操作启用守卫如canXxx/xxxActionEnabled与run*包装方法把引擎调用包进runCatching并折叠为Success/Failure密封结果。这一层不依赖 Compose因此可以直接跑桌面单测。Screen 接线层对应features/*目录下的*Screen.kt将 Presentation 守卫接到真实按钮的enabled属性将run*结果接到状态提示notice/toast。文档正文列出了本条涉及的九条链路与源码一一对应工具编号工具Presentation 对象核心守卫F22调色板ColorWiringPresentation取色/应用代码/收藏F21计算器CalculatorWiringPresentation运算/复制/进制转换F06配置转换ConfigWiringPresentationYAML↔Properties 转换/校验/导出F12UA 解析UaWiringPresentation解析/复制结果F15正则RegexWiringPresentation运行测试/取消F18时间转换TimeWiringPresentation时间戳↔本地时间/复制字段F23图片ImageWiringPresentation导入/批量处理/水印/base64 导出F02文本对比TextDiffPresentation差异导航/手动比较F16CronCronWiringPresentation解析/复制运行结果下面对每一类逐一展开源码级细节。2.1 F22 调色板ColorWiringPresentationColorWiringPresentation.kt 提供四个守卫与一个引擎路径canScreenPick(picking)取色过程中picking true禁止再次启动屏幕取色canApplyCode(code)颜色代码 trim 后非空才允许应用canFavorite(favoriteFolderId)收藏目录 id 非空才允许收藏runFormatColor(primary, format)委托ColorEngine.formatColor完成 RGB→指定格式的格式化输出。此外shouldToastOperationFailure/shouldToastErrorMessage恒为true表示该工具在操作失败或出现错误信息时总是弹出 toast。对应的 ColorWiringPresentationTest.kt 用assertFalse(ColorWiringPresentation.canScreenPick(picking true))、assertFalse(canApplyCode( ))等用例锁定了这些边界行为。2.2 F21 计算器CalculatorWiringPresentationCalculatorWiringPresentation.kt 覆盖的守卫更细canEvaluate(expression)表达式非空才允许求值canCopyResult(result)结果非空才允许复制canConvertField(value)进制转换输入非空convertBaseActionEnabled(value, fromRadix, toRadix)不仅要求输入非空还会预先调用CalculatorEngine.convertBase探测是否可转换异常时返回false按钮禁用canBinaryOp(first, second)GCD/LCM 等二元运算要求两个操作数都非空。run*系列覆盖evaluateExpression、convertBase、gcd、lcm、permutation、combination全部折叠为TextOutcome.Success/Failure。这也是 DIFF-556 中守卫数量最密集的工具之一反映计算器工具栏按钮大多处于有输入才可点的状态。2.3 F06 配置转换ConfigWiringPresentationConfigWiringPresentation.kt 面向 YAML ↔.properties互转canToYaml(properties)/canToProperties(yaml)/canValidateSource(source)三种源文本非空守卫propertiesToYamlActionEnabled/yamlToPropertiesActionEnabled/validateYamlActionEnabled/formatYamlActionEnabled对应四个工具栏动作exportTextActionEnabled(content)侧栏导出在对应 pane 无文本时禁用注释明确对齐ConfigConvertScreen侧栏导出。引擎路径包括ConfigEngine.propertiesToYaml、ConfigEngine.yamlToProperties、ConfigEngine.validateYaml返回YamlValidation、ConfigEngine.formatYaml文件读写则封装为runReadImportFileUTF-8 读取与runWriteExportFileUTF-8 写出并各自有shouldToastIoFailure。这些 IO 路径被设计成可单测的纯函数与 Electron 版 Java 侧行为对齐。2.4 F12 UA 解析UaWiringPresentationUaWiringPresentation.kt 很简单canParse(source)UA 字符串非空才允许解析canCopyResult(result)解析结果非空才允许复制runParse(source)委托UaEngine.parse折叠为ParseOutcome.Success(Failure)。对应的 UaRegexTimeWiringPresentationTest.kt 使用UaEngine.presets.first().second作为样例 UA 输入验证成功路径。2.5 F15 正则RegexWiringPresentationRegexWiringPresentation.kt 的守卫关注运行态canRunTest(pattern, running)pattern 非空且当前不在运行中showCancel(running)/cancelTestActionEnabled(running)运行中才显示取消按钮。引擎路径runMatch(pattern, source, options, maxMatches)委托RegexEngine.match默认匹配上限RegexEngine.DEFAULT_MAX_MATCHES折叠为MatchOutcome.Success/Failure。注释强调UI 仍经RegexWorkerClient进程隔离即正则的实际执行仍走 worker 进程Presentation 层只负责守卫与结果折叠。测试用例还验证了runMatch结果与直接调用RegexEngine.match完全一致assertEquals(direct, ...)以及非法模式(会折叠为Failure并携带RegexException。2.6 F18 时间转换TimeWiringPresentationTimeWiringPresentation.kt 提供双向转换守卫canConvertTimestamp(timestamp)/canConvertLocal(localTime)两种输入方向的非空守卫canCopyField(value)字段复制守卫runTimestampToLocal(timestamp, unit, zone)/runLocalToTimestamp(localTime, unit, zone)委托TimeEngine支持TimestampUnit如 Second与zone时区参数。TimeWiringPresentationTest.kt 给出了很好的可验证样例runTimestampToLocal(0, TimestampUnit.Second, Asia/Shanghai)得到1970-01-01 08:00:00反向runLocalToTimestamp(1970-01-01 08:00:00, ..., Asia/Shanghai)得到0而非法输入nope折叠为Failure。2.7 F23 图片ImageWiringPresentationImageWiringPresentation.kt 的守卫以busy 状态与选中数量为核心canImport(busy)忙碌时禁止导入canProcessSelection(selectedCount, busy)有选中项且不忙碌canActOnCurrent(hasCurrent, busy)存在当前图片且不忙碌canCopyCurrent(hasCurrent)仅要求存在当前项canExportBase64(text)/canStartWatermark(text)文本非空守卫renamePromptActionEnabled(name)重命名输入非空。引擎路径runDecodeDataUrl(text)委托ImageEngine.decodeDataUrl得到BufferedImagerunExportAssets(block)把资源导出闭包包装成ExportAssetsOutcome。值得注意shouldToastProcessFailure的取消豁免逻辑当错误是CancellationException或ImageException.code cancelled时不弹 toast其余才弹——这与 F15 正则的shouldToastWorkerError(code)code ! cancelled才提示是同一套用户主动取消不算失败的交互约定。注释还提示 SVG 数值 clamp 归ImageSvgWiringPresentation负责不在本条范围。2.8 F02 文本对比TextDiffPresentation 扩展TextDiffPresentation.kt 在本条新增了两个能力文档原话扩展canNavigateDiffs(visibleSegmentCount)可见差异段数 0 才允许上下导航canManualCompare(left, right)两侧文本至少一侧非空才允许手动比较。围绕它们还有三个动作使能别名manualCompareActionEnabled、navigateDiffActionEnabled、copyPatchActionEnabled(unified)无 unified 文本时禁用复制补丁。文件头部保留了既有常量AUTO_COMPARE_DEBOUNCE_MS 160L自动对比防抖 160ms对齐 Electron输入后短延迟重算以及nextNavIndex(current, step, size)的循环导航索引计算(current step size) % sizesize ≤ 0 返回 -1。runCompare委托DiffEngine.compare(left, right, ignoreWhitespace)导入则封装runReadImportFile。测试 TextDiffPresentationTest.kt 验证了防抖常量、循环索引、导航/比较/复制三类守卫以及缺失文件导入折叠为Failure。2.9 F16 CronCronWiringPresentation 扩展CronWiringPresentation.kt 在本条同样以扩展方式加入canParse(expression)/parseActionEnabled(expression)表达式非空才允许解析canCopyRuns(runs)/copyRunsActionEnabled(runs)运行结果列表非空才允许复制runPreview(expression, zone, language)委托CronEngine.nextRuns与CronEngine.describe折叠为ScheduleOutcome.Success(runs, description) / FailureshouldToastPreviewFailure恒为true。文件中还保留了本条之前已有的timezoneMenu系统时区去重合并与coerceSessionZone空白时区回退到 fallback用于时区菜单与 session 区规范化。测试 CronWiringPresentationTest.kt 用0 0 * * *与0 0 12 * * ?Quartz 风格验证了守卫与引擎路径其中runPreview(0 0 12 * * ?, UTC, en-US)必须返回非空 runs。2.10 Screen 接线从守卫到按钮文档强调上述每条链路都伴随对应 Screen 接线。以最典型的一处为例QuickNoteScreen.kt 中随手记 Vault 底栏的路径计算与脏标记展示直接调用QuickNoteVaultFooterPresentation.effectivePath(...)、showFooter(...)、footerDirty(...)再配合VaultSelectionFooter组件与mooQuickNoteVaultFooter样式渲染。其余工具的 ScreenColorBoardScreen、CalculatorScreen、ConfigConvertScreen、UaParseScreen、RegexScreen、TimeConvertScreen、ImageScreen、TextDiffScreen、CronScreen同样以xxxActionEnabled(...)绑定按钮enabled。三、F01 随手记 Vault 底栏QuickNoteVaultFooterPresentationDIFF-556 的 Vault 部分是一个新引入的公共对象 QuickNoteVaultFooterPresentation.kt位于commonMain说明可在多平台共享其定位是对齐JsonVaultFooterPresentationeffectivePath(vaultSelectedPath, currentFile)直接复用 Json 版本的优先取树选中路径规则showFooter(path)决定是否展示底栏footerDirty(path, currentFile, documentDirty)仅当路径等于当前打开文件且正文脏时标记脏path currentFile documentDirtycanDuplicate(isDirectory)目录不可重复复用 Json 规则gitFlushSkipsWhenClean(currentFile, documentDirty)无打开笔记或正文已经保存时Vault Git 操作前的 flush 可以跳过写盘gitUntitledBlockKey(currentFile, editorText, sampleText)无 Vault 笔记但编辑器有非示例内容时阻止 Git 操作并返回 i18n 键git.flush.untitled若编辑器内容恰好等于示例文本或已有打开文件则不阻止。这个脏标记只看当前文件的设计在测试 QuickNoteVaultFooterPresentationTest.kt 中非常直白footerDirty(a.md, b.md, documentDirty true)必须为falsegitFlushSkipsWhenClean(, true)与gitFlushSkipsWhenClean(a.md, false)为truegitUntitledBlockKey(, draft, sample)返回git.flush.untitled而把draft换成示例文本sample或传入已打开文件a.md时返回null。在 Screen 侧QuickNoteScreen的底栏动作行重命名/复制/移动/删除全部以mooQuickNoteVaultFooter()mooQuickNoteVaultFooterActions()样式承载canDuplicate(footerEntry?.directory)控制复制按钮显隐形成了与 JSON Vault 一致的底栏交互体验。四、CSS 组件批次五个 moo 风格修饰符DIFF-556 的样式切片包含五个组件全部集中在 Controls.kt每一个都在注释中标明了对应的 Electron 选择器样式修饰符实现对齐的 Electron 选择器 / 语义mooQuickNoteVaultFooter()mooJsonVaultFooter()heightIn(min 36.dp) 顶部分隔线drawBehind.quick-note-vault-footer与 JSON 底栏共用分隔样式mooColorFormatRow()heightIn(min 46.dp)调色板格式/取色工具条mooUaParseBar()heightIn(min 46.dp)UA 解析顶栏操作行mooConfigTabsRow()heightIn(min 40.dp)配置转换 Tab 行mooDiffNavCluster()heightIn(min 34.dp)文本对比工具栏差异导航区这些修饰符本质是最小行高约束 少量绘制用极低的成本复刻 Electron 版各工具的工具栏/底栏密度。它们在仓库中同时被界面代码与样式捕获测试引用例如 TextDiffNavCaptureTest.kt 使用mooDiffNavCluster()QuickNoteVaultFooterCaptureTest.kt 使用mooQuickNoteVaultFooter()ColorScreenPickCaptureTest.kt 使用mooColorFormatRow()ConfigConvertTabCaptureTest.kt 使用mooConfigTabsRow()。这些 capture 测试的存在说明样式并非随手加的 magic modifier而是有截图/捕获证据支撑的逐一落地。五、A02 导航深链命令盘关键词与工具注册表DIFF-556 的导航部分对两个目录做了深链关键词扩展目标是让命令盘Command Palette输入关键词能命中工具或设置分类5.1 CommandSearchCatalog设置分类深链CommandSearchCatalog.kt 定义了CommandSettingsTarget(categoryId, labelKey, navIcon, keywords)覆盖general / ai / vault / editor / network / runtime / tools / data / appearance / layout / shortcuts / about共 12 个设置分类。其关键词表中英日三语混排以本条的tools分类为例除了tools本身还包含qrcode / qr / random / translation / unicode / hex / urlencode / base64 / aes / rsa / sm2 / calculator / color / palette / protobuf / yaml / regex / gcd / lcm / unixtime / timezone / ua / user-agent以及中文计算器/调色/编码/二维码/随机/翻译等vault分类则覆盖git / merge / rebase / push / pull / fetch / conflict / savecopy / quicknote / quick-note / memo / 随手记 / jsonvault / vaultsearch / includecontent等。搜索实现上search(query, translate)会同时用Locale.ROOT与Locale.getDefault()两份小写化结果做匹配命中条件包括categoryId 前缀包含、翻译后的分类标签包含、以及任意 keyword 包含。matchesSearch是internal函数因此可被单测直接引用。5.2 ToolRegistry工具深链关键词ToolRegistry.kt 的ToolDefinition(id, groupId, titleKey, keywords, glyph, status, supportsHistory, supportsFavorites)定义了全部工具的导航元数据。DIFF-556 涉及的工具关键词在表中清晰可见QuickNotenote / memo / markdown / vault / duplicate / 随手记 / 笔记TextDiffdiff / compare / whitespace / myers / patch / history / 对比Calculatorcalculator / calc / gcd / lcm / permutation / 计算 / 进制ColorBoardcolor / palette / hex / rgb / picker / screen / 调色 / 取色UaParseua / user-agent / browser / chrome / preset / parse / 浏览器Regexregex / regular / pattern / test / global / 正则 / 捕获TimeConverttime / timestamp / unix / timezone / 时间Imageimage / 图片 / svg / watermark / compress / base64 / clipboard / 截图Croncron / schedule / quartz / parse / timezone / favorite / history / 定时。ToolRegistry.search在空查询时返回全部工具非空时用Locale.ROOT小写化匹配 id / 翻译标题 / keywords。两部分结果由 CommandSearchResults.kt 的commandSearchEntries合并为CommandSearchEntry.Tool与CommandSearchEntry.Settings两类条目供命令盘统一展示。5.3 测试锁定的行为CommandSearchCatalogTest.kt 是本文档验证节的直接证据它锁定了大量深链映射例如mcp→aigit/rebase/mergeflow/savecopy→vaultquicknote/vaultsearch→vault随手记深链命中 Vault 设置myers→layoutMyers diff 属于布局/对比设置yaml/aes/calculator/qr/translate→toolshardware/detect/coderun→runtime检查更新中文→aboutcatalogCoversEverySettingsNavCategory用例还会遍历SettingsNavCategory.entries强制保证每个设置分类都被命令盘覆盖。六、MCP 边界本条无新增 handlerDIFF-556 特意声明Electron MCP 仍为 11 项核心工具 Vault 扩展本条无新增 MCP handler并指向对照文档 electron-next-mcp-server-vitest.md。也就是说本条的 F 工具接线、Vault 底栏、CSS 与命令盘关键词都发生在桌面 UI 与导航层没有向 MCP 服务端暴露新的工具。这既是范围控制避免在一条 diff 里混合太多改动面也是沟通工具与 UI 工具的演进节奏差异——MCP 工具的扩展走的是另一套 catalog 登记流程参见 DIFF-555 的McpToolCatalogTest登记mootool_protobuf_wire的例子。七、验证方式单测、证据脚本与 Gradle 离线任务文档验证节给出了三类闭环验证手段Presentation 单测*WiringPresentation*、QuickNoteVaultFooterPresentation*、TextDiffPresentation*、CronWiringPresentation*的测试用例。除本文已列出的几个测试文件外仓库中还有CalculatorWiringPresentationTest、ConfigWiringPresentationTest、ImageWiringPresentationTest、UaWiringPresentationTest、TimeWiringPresentationTest等一一对应位于desktopTest的domain包。从测试命名可以确认DIFF-556 采取的是每个 Presentation 一个测试类的约定。命令盘测试CommandSearchCatalogTest覆盖 yaml / quicknote / myers 等深链场景上节已详述。证据恢复脚本 桌面测试./scripts/prepare-tray-screencapture-evidence.sh恢复证据 PNG托盘截屏证据链仓库中的next-compose/scripts/prepare-tray-screencapture-evidence.sh./gradlew :composeApp:desktopTest --offlineJDK 21离线跑 Compose 桌面端全部测试这是本模块每次 diff 的最终回归门槛。这些命令适用于next-compose模块的开发环境需要 JDK 21 与 Gradle 工具链可用属于项目内既定流程读者可按需在本地复现。八、未做事项与切边界文档最后明确列出了未做清单作为下一条 diff 的输入六套 CSS 逐选择器皮肤即 parity-gap 中六套 CSS 逐选择器皮肤的承诺项产品主窗全工具 Tab / 系统 IME 手工 PNGnext-compose/docs/diff/系列中多次提及的产品主窗 Tab/IME/TCC PNGP7 三平台安装 / 公证参见 P7 相关文档 的语境其余 F 工具的 substantial 引擎 / UI整体 parity 目标仍未达成。这些未做项说明 DIFF-556 是增量合规交付它只承诺了 F 工具守卫接线、Vault 底栏、CSS 组件批次与导航关键词四件事并把遗留事项显式登记供后续切片如 557/558/559 等相邻编号的 diff 文档继续消化。结语一条 diff 的可测性设计回看 DIFF-556 的完整交付物最值得借鉴的是它的可测试性纪律所有 UI 使能逻辑都被抽成无 Compose 依赖的object纯函数引擎调用一律折叠为密封Success/Failure取消语义cancelled在 toast 层面被显式豁免样式用最小行高修饰符落地并被 capture 测试引用命令盘关键词中英日三语覆盖且有 40 条断言用例。这种守卫先行、接线后置、测试兜底的切片式推进方式正是 MooTool 在多平台Electron/Compose/Flutter/Tauri间维持 parity 且每步都可回归的工程基础。若你在自己的多窗口工具类产品中需要类似的分批落地节奏可以直接复用这套WiringPresentation Screen 接线 捕获测试的骨架。赞分享桌面应用开发工具【免费下载链接】MooToolHandy tool set for developers项目地址https://gitcode.com/gh_mirrors/mo/MooTool点击查看免费下载相关推荐MooTool Compose 桌面版 DIFF-553 技术解读F05/F11/F23 引擎接线、JSON Vault 搜索与命令盘/MCP 的工程实现MooTool Compose 桌面版 DIFF 553 技术解读F05/F11/F23 引擎接线、JSON Vault 搜索与命令盘/MCP 的工程实现 导桌面应用开发工具MooTool Compose 桌面版格式化工具栏按钮启用守卫DIFF-649 F03 *ActionEnabled 接线实践MooTool Compose 桌面版格式化工具栏按钮启用守卫DIFF 649 F03 ActionEnabled 接线实践 本文以 MooTool 仓库 n桌面应用开发工具MooTool 随手记 Vault 导入/拖放打开前的脏笔记保存守卫DIFF-342 设计与 Compose 实现解析MooTool 随手记 Vault 导入/拖放打开前的脏笔记保存守卫DIFF 342 设计与 Compose 实现解析 随手记QuickNote是 Moo桌面应用开发工具上一篇打破单机限制NucleusCoop让你在一台电脑上玩转多人分屏游戏下一篇3步技术解析如何用Nucleus Co-op实现PC游戏分屏多人体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站