- 桌面应用
- 开发工具
【免费下载链接】MooTool
Handy tool set for developers
导读
本文是 MooTool 开源仓库中 MooTool Next Flutter(Flutter 桌面产品线)在 2026-09-09 P6 阶段验收记录(results.md)的深度解读与源码级还原。文档记录了本次验收的核心结论:flutter analyze无任何问题、flutter test test/unit共 83 个用例全部通过,以及 P6 阶段"截图裁剪、屏幕取色、六种风格 token"三大功能点完成的具体边界。读完后你将掌握该产品线桌面通道的实现方式、验收命令与范围划分,以及"显式未完成"项的后续演进方向。
验收命令与结果
完整验收命令
本次验收在 macOS(darwin 25.6 x86_64)上执行,环境记录详见 environment.md,涉及 Flutter 3.47.2 / Dart 3.13.2(位于$HOME/sdk/flutter)。验收由两条命令构成:
export PATH="$HOME/sdk/flutter/bin:$PATH" cd next-flutter flutter analyze flutter test test/unit --reporter compactflutter analyze对next-flutter全目录做静态分析,结果"No issues found! (ran in 2.2s)",即整个 Flutter 代码库无警告、无错误。flutter test test/unit --reporter compact运行 test/unit 目录下的全部单元测试,使用compact单行报告器输出,结果为"All tests passed!",共83个用例全部通过。
需要说明的是,flutter run -d macos在本次验收中仍未作为验收标准,与本机只有 Command Line Tools、没有完整 Xcode 时插件可能无法链接有关(参见 README.md 环境一节)。这与本次验收"代码侧落地、运行侧待补"的整体边界保持一致。
83 个用例的构成
test/unit目录下共 16 个测试文件,分别覆盖产品核心域(workspace_test.dart、json_engine_test.dart)、网络与系统(network_test.dart、p5_system_test.dart)、本次 P6 相关(p6_capture_test.dart、p6_desktop_test.dart、p6_media_test.dart、p6_window_test.dart)以及回归与运行时(review_regression_test.dart、review_runtime_test.dart)等。83 个通过用例是对既有功能不回归与 P6 新能力同时成立的证据。
验收范围:P6 三大功能点
功能一:截图捕获与裁剪(截图草稿机制)
已对齐:截图捕获后可以裁剪、保存全图或取消,取消不写库。这一行为由 app_controller.dart 的三段式流程实现:
- 捕获:
captureScreenshotToLibrary()调用desktopHost.captureScreenRegion()获取主屏 PNG 字节,成功后解析像素尺寸,将字节放入screenshotDraft,并把默认裁剪区域初始化为全图(X=0, Y=0, W=宽度, H=高度),同时提示用户"X/Y/W/H"四参数与 8×6 像素测试图默认尺寸; - 确认:
confirmScreenshotDraft({required bool crop})根据crop参数决定走cropImageBytes裁剪还是直接保存原图,落库文件名按时间戳生成Screenshot-<millisecondsSinceEpoch>.png,随后刷新图片库列表并清空草稿; - 取消:
cancelScreenshotDraft()直接置空screenshotDraft并退出截图面板,不产生任何落库副作用。
对应的 UI 在 image_page.dart:截图面板_panel渲染 X/Y/W/H 四个裁剪输入框,以及「保存全图 / 裁剪确认 / 取消」三个按钮,分别绑定crop: false、crop: true与cancelScreenshotDraft。
裁剪核心算法在 image_process.dart:cropImageBytes先对宽高做非空校验(width <= 0 || height <= 0抛出FormatException),再把 left/top 用clamp(0, 宽/高)限制在图像内、宽高用clamp(1, 剩余最大)兜底,最后通过image包的copyCrop完成像素级裁剪并重新编码为 PNG。
测试覆盖见 p6_capture_test.dart:首条用例验证「裁剪保留目标区域、拒绝空裁剪」,用程序生成的 8×6 纯色 PNG 裁剪出 4×3 后校验尺寸,并断言宽为 0 时抛FormatException;第二条用MemoryDesktopHost走完整「捕获 → 裁剪 → 落库 → 再捕获 → 取消」链路,验证最终库内仅剩 1 张图片;第三条则验证缺失截图字节是显式 miss 而非假写库——宿主能力声明支持截图但返回空字节时,图片库保持为空且出现提示,杜绝了"假成功"。
功能二:屏幕取色通道
已对齐:取色失败不改色值。入口pickScreenColorInto(String toolId)在 app_controller.dart:调用desktopHost.pickScreenColor()获取十六进制色值;若返回null,则按能力声明分别提示「拒绝」或「待支持」,不触碰目标工具(如 colorBoard)的现有色值;成功时才把取到的色写入对应会话的left字段。
macOS 原生实现位于 MainFlutterWindow.swift:取色使用系统NSColorSampler(要求 macOS 10.15+),弹窗前先将自身窗口orderOut隐藏避免遮挡,回调里把取到的颜色转换到 sRGB 后格式化为#RRGGBB字符串回传,取色完成后再恢复窗口。测试同样覆盖了"能力声明支持取色但宿主返回空 → 色板值保持不变"的场景(p6_capture_test.dart)。
功能三:六种界面风格 token
已对齐:六种风格使用相互独立的设计 token,而不是复用 modern 风格。InterfaceStyle枚举定义在 settings.dart,取值依次为modern、quiet、hero、smartisan、miuiV5、claude;其持久化以interfaceStyle字段读写 settings JSON,反序列化时未知枚举值回退到modern(settings.dart)。设置页以ChoiceChip列表让用户切换,见 settings_page.dart。
每种风格在 theme.dart 的tokensFor(style, brightness)中分别定义明暗两套MooTokens,覆盖 workspace、surface、sidebar、toolbar、border、textPrimary、textSecondary、accent、onAccent、focus 十个颜色槽位:
| 风格 | 浅色 workspace | 浅色 accent | 深色 workspace | 深色 accent | 视觉取向 |
|---|---|---|---|---|---|
| modern | #FAFBFC | #356CB8 | #17191D | #8AB8F8 | 中性蓝灰 |
| quiet | #F7F7F5 | #5C5C56 | #141414 | #8F8F8F | 低饱和灰 |
| hero | #F3F6FB | #1F5FBF | #101826 | #5B8DEF | 深蓝高对比 |
| smartisan | #F6EFE6 | #C45C26 | #1C1612 | #E08A5A | 暖棕橙 |
| miuiV5 | #F0F3F7 | #0D84FF | #101418 | #4DA3FF | 明亮蓝 |
| claude | #F7F4EF | #D97757 | #1A1714 | #E09A7A | 米白陶土 |
测试在 p6_capture_test.dart 中对五种非 modern 风格逐一断言"关键 token 与 modern 不同",并额外验证 quiet 在暗色下的 workspace 同样与 modern 暗色不同,防止未来某风格退化成对 modern 的别名。
桌面通道:Dart 与 macOS 原生的桥接
上述截图与取色能力都依赖DesktopHost抽象,定义在 desktop_host.dart:它用DesktopCapabilities声明平台能力(preventDisplaySleep / screenshot / screenColor / tray / clipboardImage五个布尔位),抽象接口包含捕获屏幕区域、取色、读剪贴板图片、应用窗口策略等方法。
- 生产实现
ChannelDesktopHost通过名为com.rememberber.mootool.next.flutter/desktop的MethodChannel与原生通信,对MissingPluginException / PlatformException统一返回空值(desktop_host.dart)。 - 测试实现
MemoryDesktopHost内存模拟所有能力与返回值,让控制器在无原生环境(flutter test仅 Dart VM)下可完整走查业务逻辑(desktop_host.dart)。 - macOS 侧MainFlutterWindow.swift 在
registerDesktopChannel中注册同名通道,处理capabilities / captureScreenRegion / pickScreenColor / readClipboardImage / applyWindowPolicy / performCloseAction等调用。capabilities恒返回screenshot: true、screenColor: true(MainFlutterWindow.swift),并在状态栏菜单中提供 Screenshot 与 Color 两个快捷入口(MainFlutterWindow.swift)。
已知差异与明确未完成项
对照文档 parity.md 如实记录了与既定目标的差距,本次验收不回避未完成项:
- macOS 截图实现为
CGDisplayCreateImage(CGMainDisplayID())主屏整屏捕获([MainFlutterWindow.swift](https://link.gitcode.com/i/761edd6c2f9af5e916363ac63aa63393#L172-L189,捕获前会短暂隐藏自身窗口并延时 80ms 等窗口收起再截),不是 ScreenCaptureKit 的多屏选区; - 区域裁剪是捕获后的像素矩形(Dart 侧
copyCrop),不是系统级拖拽选区 overlay; - Swift 侧未在本机用 Xcode 编译运行,与
flutter run -d macos不作为验收一致; - 仍无第二 Flutter engine,因此多窗口/独立截图预览引擎的能力尚未落地;
- P7 安装包未完成,当前仅
pubspec.yaml版本 0.1.0+1、打包脚本未签名(见 README.md)。
如何复现本次验收
在仓库根目录执行以下命令即可复现相同验收(建议先flutter pub get):
export PATH="$HOME/sdk/flutter/bin:$PATH" cd next-flutter flutter pub get flutter analyze flutter test test/unit --reporter compact测试数据统一使用系统临时目录(Directory.systemTemp.createTempSync)而非真实 Application Support 路径,避免污染真实用户数据;产品完整运行与打包可参考 README.md 的flutter run -d macos -- --data-dir /tmp/mootool-next-flutter-dev与scripts/package.sh macos。
小结
P6 阶段验收确立了三条事实基线:静态分析零问题、83 个单元测试全部通过、三大功能点(截图裁剪、取色通道、六风格 token)代码侧完成且行为可测;同时把"多屏截图、拖拽选区 overlay、第二 engine、P7 安装包"四件事明确列为后续工作。对后续开发者而言,p6_capture_test.dart、theme.dart、MainFlutterWindow.swift 分别是验证截图/取色业务、扩充风格 token、扩展原生通道时的直接参考文件。
- 桌面应用
- 开发工具
【免费下载链接】MooTool
Handy tool set for developers
相关推荐
MooTool Next Flutter 桌面能力对齐:截图裁剪、屏幕取色与六种风格 Token 的实现与验收
MooTool Next Flutter 桌面能力对齐:截图裁剪、屏幕取色与六种风格 Token 的实现与验收 本篇指南聚焦 MooTool Next Flut
桌面应用开发工具MooTool Next Flutter 桌面能力实现指南:P6 剪贴板图片、关闭策略、托盘通道与分离持久化
MooTool Next Flutter 桌面能力实现指南:P6 剪贴板图片、关闭策略、托盘通道与分离持久化 本文基于 MooTool 仓库中 next flu
桌面应用开发工具MooTool Next Flutter P3 阶段验收全解析:flutter analyze 零告警与 33+ 项单元测试的技术实现
MooTool Next Flutter P3 阶段验收全解析:flutter analyze 零告警与 33+ 项单元测试的技术实现 MooTool Next
桌面应用开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考