☰
MooTool Next Flutter 界面体系设计解析:沉浸式工具区、主题 Token 与快捷键规范(ADR 007)
2026/10/16 2:48:14 网站建设 项目流程
  • 桌面应用
  • 开发工具

【免费下载链接】MooTool

Handy tool set for developers

项目地址:https://gitcode.com/gh_mirrors/mo/MooTool
点击查看免费下载

本文围绕 next-flutter/docs/adr/007-ui.md 这份已采纳的架构决策记录展开,深入讲解 MooTool Next Flutter 桌面端在界面布局、主题系统、导航模式与键盘快捷键上的具体设计约定,并结合仓库内 Dart 源码、设置页与单元测试,说明每一项约定在代码中的落地方式。读完本文,你将掌握 MooTool 这套"沉浸式工具区 + 主题 Token 换肤 + 快捷键双平台映射"的界面架构如何工作,以及哪些参数在设置界面中真实可调、哪些行为仍是规划中的状态。

一、ADR 007 决策概览

ADR(Architecture Decision Record)007 记录的是 MooTool Next Flutter 产品在 UI 层面的一组关键设计决策,状态为「已采纳」,日期为 2026-09-08。它一共锁定了五类约定:

  1. 沉浸式工具区:工具页面不使用大标题、面包屑或整页卡片,界面直接呈现工具内容本身。
  2. Token 主题体系:以modern风格为主指南色板,并为产品补齐quiet、hero、smartisan、miui-v5、claude五套独立 workspace/sidebar/accent token;选择风格会真实改变表面色与强调色,而不是一个"假开关"。
  3. 强调色预设:6 个预设 id(yellow/coral/blue/green/red/purple)会进入ColorScheme,同时旧配置值#4f83cc仍能正常解析。
  4. 导航模式:默认classic;grouped显示组标题;card尚无独立视觉。
  5. 快捷键:⌘/Ctrl+K 搜索、⌘/Ctrl+, 设置、⌘/Ctrl+F 查找、⌘/Ctrl+S 保存、⌘/Ctrl+Enter 格式化;macOS 上显示 Command 符号,同时通过LogicalKeyboardKey监听 Control。
  6. 分离窗口:在 P2 阶段是"同一 engine 内的状态机",并非原生独立 NSWindow。

下面逐条对应源码展开。

二、沉浸式工具区:没有标题栏和卡片壳的工具页

ADR 的第一条约定是工具区不再承载"大标题 / 面包屑 / 整页卡片"这类装饰性容器。这一点从工作台布局上可以直接印证:在 next-flutter/lib/features/workbench/workbench.dart 中,Workbench的正文区由侧边栏_sidebar(tokens)与工作区_workspace(tokens)组成,工作区根据当前工具 id 直接分发到对应的工具页面(见该文件的_workspace方法,如'json' => JsonToolPage(...)、'http' => HttpToolPage(...)、'pdf' => PdfToolPage(...)),工具页外层没有任何统一的标题条或面包屑组件。

各工具页本身也延续了这种"直接干活"的风格。以 JSON 工具为例,next-flutter/lib/features/json/json_tool.dart 的页面结构是「工具栏 → 查找栏(按需展开)→ 分栏(文档库 / 编辑器 / 检视器)」,工具栏上只有与任务直接相关的操作按钮,不存在页面级大标题。从代码结构可以推断,沉浸式布局的收益是让工具内容占满可用区域,并让快捷键与右键操作成为主要交互入口。

三、主题 Token 体系:从枚举到六套真实色板

ADR 要求主题体系具备"真实换肤"能力,而不是只换一个开关的外观。仓库中的实现分为三层:枚举定义 → Token 生成 → 主题构建。

3.1 风格枚举与配置持久化

界面风格在 next-flutter/lib/app/settings.dart 中定义为枚举:

enum InterfaceStyle { modern, quiet, hero, smartisan, miuiV5, claude }

该枚举通过AppSettings.interfaceStyle字段持久化到 JSON(settings.interfaceStyle.name),默认值是modern。也就是说,风格选择是写入设置文件的真实配置,重启后仍然生效。

3.2 Token 生成器:六套独立色板

核心实现在 next-flutter/lib/design/theme.dart:

  • MooTokens extends ThemeExtension<MooTokens>定义了一组语义化颜色字段:workspace、surface、sidebar、toolbar、border、textPrimary、textSecondary、accent、onAccent、focus,并给出light/dark两套内置常量。
  • tokensFor(InterfaceStyle style, Brightness brightness)通过switch为每种风格各自返回一套完整的明/暗 token。例如:
    • quiet采用接近灰阶的中性色,accent 也是低饱和的灰色(#5C5C56/ 暗色下#8F8F8F);
    • hero使用深蓝主视觉,accent 为#1F5FBF(暗色#5B8DEF);
    • smartisan走暖棕色调,accent 为#C45C26(暗色#E08A5A);
    • miuiV5是明亮蓝,accent 为#0D84FF(暗色#4DA3FF);
    • claude是米白暖色系,accent 为#D97757(暗色#E09A7A)。
  • tokensOf(BuildContext context)通过Theme.of(context).extension<MooTokens>()取回当前 token,供各页面使用。

单元测试 next-flutter/test/unit/p6_capture_test.dart 中专门有一条测试验证"每种风格使用独立 token 而非复用 modern":它逐项断言quiet.workspace、hero.sidebar、smartisan.accent、miui.accent、claude.workspace都isNot对应位置的modern值。这说明"不是假开关"是有测试约束的设计事实。

3.3 主题构建:Token 与 ColorScheme 汇合

buildTheme(...)(同样位于 theme.dart)负责把 token 与 Material 3 的ColorScheme结合:

final tokens = tokensFor(style, brightness); final scheme = ColorScheme.fromSeed( seedColor: accent ?? tokens.accent, brightness: brightness, surface: tokens.surface, );

可以看到ColorScheme.fromSeed的种子色优先使用用户强调色accent,未指定时才回退到当前风格 token 的 accent;scaffoldBackgroundColor直接取tokens.workspace。同时MooTokens通过extensions: [tokens.copyWith(accent: accent ?? tokens.accent)]挂进 ThemeData,供全局组件读取。因此强调色选择确实会"进入ColorScheme"(ADR 原文表述),同时也会覆盖 token 的 accent 通道。

主入口 next-flutter/lib/main.dart 在构建MaterialApp时分别调用buildTheme(brightness: Brightness.light/dark, ...),并把controller.settings.interfaceStyle和_accent(controller.settings.accentColor)传入;themeMode由ThemePreference(system/light/dark)决定。

3.4 字体缩放

buildTheme还实现了全局字体缩放:以 13px 为基准(final factor = uiFontSize / 13),对 Material 的 display/headline/title/body/label 全套文字样式统一乘系数,并强制套用tokens.textPrimary作为前景色。这对应设置中的「界面字号」滑块(11~18)。

四、强调色:6 个预设 id 与旧值兼容

ADR 明确写有:强调色 6 个预设 id 会进入ColorScheme,且旧值#4f83cc仍能解析。这两条都在 next-flutter/lib/app/settings.dart 有直接实现:

const accentColorPresets = { 'yellow': '#e0b22b', 'coral': '#de8f7d', 'blue': '#4f83cc', 'green': '#4e9275', 'red': '#c96761', 'purple': '#8a72b5', }; String resolveAccentHex(String value) { if (accentColorPresets.containsKey(value)) return accentColorPresets[value]!; if (RegExp(r'^#[0-9a-fA-F]{6}$').hasMatch(value)) return value; return accentColorPresets['blue']!; }

resolveAccentHex的解析顺序是:

  1. 命中预设 id(如blue)→ 返回预设十六进制;
  2. 否则若匹配#RRGGBB格式(如旧配置里的#4f83cc)→ 原样返回,从而保证历史配置可解析;
  3. 兜底返回blue(#4f83cc)。

设置页 next-flutter/lib/features/settings/settings_page.dart 的「外观」分类中用六个圆形色块渲染accentColorPresets,点击即把accentColor写为预设 id;main.dart里的_accent再通过resolveAccentHex把它变成Color喂给buildTheme。整条链路(设置项 → 持久化 → 解析 → ColorScheme 种子 → token accent)构成了一个真实生效的强调色系统。

五、导航模式:classic 默认,grouped 有视觉,card 未实现

导航模式在 settings.dart 中定义为:

enum NavigationStyle { classic, card, grouped }

在 next-flutter/lib/features/workbench/workbench.dart 的侧边栏渲染中,只有两种模式有实际分支:

  • classic(默认):工具项按toolGroups顺序平铺成列表,不显示组标题;
  • grouped:在自定义组(customGroups)与内置组(toolGroups)之前渲染组名标题(tokens.textSecondary的 11px 小字);
  • card:代码中没有对应的样式分支,与 ADR 记录的"card 尚未单独视觉"一致。

需要留意的是,侧边栏只有在未折叠(!collapsed)且未开启「隐藏导航标题」时才显示文字,折叠态(宽度 84)下只保留图标,这是与 next-flutter/lib/features/settings/settings_page.dart「布局」分类中hideNavigationTitles、showRecent、compactNavigation等开关共同作用的。

六、快捷键体系:双平台 LogicalKeySet 映射

ADR 记录的快捷键全部通过 Flutter 的Shortcuts+LogicalKeySet实现,macOS 用meta(⌘),其他平台同时注册control,因此同一套代码在两类键盘上都能触发。各快捷键的落点如下:

快捷键作用实现位置
⌘/Ctrl+K打开工具搜索workbench.dart_SearchIntent;另在 main.dart 的CallbackShortcuts中兜底绑定
⌘/Ctrl+,打开设置workbench.dart_SettingsIntent
Escape关闭浮层workbench.dart_EscapeIntent(调用controller.closeOverlays)
⌘/Ctrl+F查找(JSON 工具)json_tool.dart_FindIntent
⌘/Ctrl+S保存(JSON 工具)json_tool.dart_SaveIntent(对应saveJsonDocument)
⌘/Ctrl+Enter格式化(JSON 工具)json_tool.dart_FormatIntent(对应formatJson)

侧边栏的搜索按钮 tooltip 会根据平台动态拼接⌘K或Ctrl+K(defaultTargetPlatform == TargetPlatform.macOS),设置页「快捷键」分类中也以⌘/Ctrl + K、⌘/Ctrl + ,的格式展示了主要组合,这正是 ADR 所述"macOS 显示 Command"的 UI 呈现。

从源码结构看,这类meta + key与control + key成对注册的写法同样复用在编辑器(next-flutter/lib/design/widgets.dart 中的撤销/重做meta/control + Z、meta/control + shift + Z)、JSON 工具与快捷笔记(quick_note_page.dart 的 F/S/Z)中,是项目统一的快捷键模式。

七、分离窗口:同 engine 状态机而非原生 NSWindow

ADR 最后一条约束了分离窗口的实现边界:P2 阶段采用"同一 engine 的状态机",而不是原生独立 NSWindow。源码中的佐证是 next-flutter/lib/core/window/session_transfer.dart 的SessionCoordinator:它用一张_owners表维护"每个 session 当前由哪个 window 持有写入权",通过beginTransfer/ack/abort三个操作完成单写者会话的移交(beginTransfer会校验"源窗口必须是写入所有者",ack校验目标窗口与修订号匹配后才更新所有权)。

在应用层,AppController通过detachedToolIds集合标记"已分离"的工具(见 app_controller.dart 及 workbench.dart 的_navTile:分离工具带open_in_new小图标,长按侧边栏项可在 detach/dock 间切换)。也就是说,"分离"在 P2 是通过 workbench 内的状态与 SessionCoordinator 的会话所有权管理来实现的,与原生多窗口渲染是两个不同阶段的能力。

八、配置项速查与进阶阅读

8.1 与 UI 相关的可配置项一览

以下配置项在 settings.dart 中均有默认值与 JSON 持久化实现,并可在设置页的「外观 / 布局」分类中操作:

配置字段默认值可选值 / 范围说明
themesystemsystem/light/dark决定ThemeMode
interfaceStylemodernmodern/quiet/hero/smartisan/miuiV5/claude切换整套 surface/强调色 token
accentColorblueyellow/coral/blue/green/red/purple或#RRGGBB作为 ColorScheme 种子并覆盖 token accent
uiFontSize1311~18全局界面字号缩放基准
navigationStyleclassicclassic/card/groupedcard目前无独立视觉
compactNavigation/hideNavigationTitles/showSidebarDividerfalse/false/true布尔侧边栏显隐细节
sidebarWidth248220~280(clamp)侧边栏宽度

8.2 深入阅读源码

  • 主题与 Token:next-flutter/lib/design/theme.dart
  • 设置模型与强调色解析:next-flutter/lib/app/settings.dart
  • 工作台与快捷键绑定:next-flutter/lib/features/workbench/workbench.dart
  • 设置页各分类实现:next-flutter/lib/features/settings/settings_page.dart
  • 应用入口与主题装配:next-flutter/lib/main.dart
  • 会话移交状态机:next-flutter/lib/core/window/session_transfer.dart
  • 风格独立性的测试约束:next-flutter/test/unit/p6_capture_test.dart

九、小结

ADR 007 实际上为 MooTool Next Flutter 划定了一条清晰的界面路线:工具页只做沉浸式内容区、主题体系用语义化 Token 支撑六套真实风格与可配置强调色、导航以 classic 为基线逐步演进、快捷键统一走双平台LogicalKeySet映射,而分离窗口在 P2 以同 engine 状态机先行。这些约定在仓库中均有对应源码、设置入口与测试三重印证,阅读本文后,你可以直接在设置页验证风格/强调色/导航模式的真实行为,也可以顺着上文给出的文件路径继续跟踪每一层实现。

  • 桌面应用
  • 开发工具

【免费下载链接】MooTool

Handy tool set for developers

项目地址:https://gitcode.com/gh_mirrors/mo/MooTool
点击查看免费下载

相关推荐

上一篇:LeetCode-Book 精讲:LCR 173「点名」——用二分法在排序数组中定位缺失数字
下一篇:如何用一条命令拆出游戏资源:QuickBMS 完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询