PowerToys SCOOBE 升级引导(What's New 对话框):从设计规格到仓库实现
导读
PowerToys 在每次升级后都会面对一个老问题:用户如何在升级第一时间获知新特性与修复?本文以仓库内《SCOOBE Dialog 设计规格》(Draft 状态,作者 Deondre Davis)为主线,系统讲解 "Second Chance OOBE"(SCOOBE)升级引导的设计目标、功能需求、页面内容组织、度量体系,并结合 ScoobeWindow.xaml.cs 等当前实现源码,剖析它是如何通过 GitHub Releases API 拉取发布数据、按版本分组并以 Markdown 渲染"发布亮点"的。读完本文,你将掌握该对话框从产品规格到工程落地的完整链路,以及其中每个设计决策在代码中的对应物。
1. 背景与动机:为什么需要 SCOOBE
PowerToys 的版本信息(release notes)此前主要发布在主仓库与 Microsoft Docs 上,二者都位于应用之外。这意味着:用户只有主动去查阅才能知道"这个版本改了什么",或者只能在使用中碰巧发现行为变化。规格文档把这类体验归纳为两个痛点:
- 信息与产品"隔离",升级上下文被打断;
- 依赖用户主动性与运气,新特性触达率低。
作为应对,PowerToys 希望在升级后启动一个 SCOOBE(Second Chance Out of Box Experience) 对话框,把"最新版本包含哪些新增与改进"以可浏览的形态直接带到用户面前。它与首次安装的 OOBE(Out of Box Experience)同源:首次安装展示 "Welcome to PowerToys",升级之后则展示 "What's New",前者是"第一次机会",后者是"第二次机会"。
规格出处:SCOOBE Dialog 规格文档 第 1.1/1.2 节。
2. 目标与非目标
目标(Goals)
- 创建一个引导式(guided)对话框,让用户快速浏览当前版本新增的特性与改进概览。
非目标(Non-Goals)
- 不做成仓库 release notes 的"逐字复制品"。规格明确要求信息必须易于消化,并且需要尽可能附带新行为的可视化演示——而这类视觉内容往往在仓库 release notes 里无法表达或不必要出现。
这一"非目标"在实现里得到了直接体现:渲染层不是简单把 release notes 文本原样铺开,而是做了一系列结构化加工(见第 7.3 节),例如剥离 "Installer Hashes" 段、提取 Hero 图、将 #PR号 自动转为链接等,保证展示内容"可消费"而非"可归档"。
3. 目标用户与成功度量
3.1 目标用户
既有与新增的 power users 和开发者——即那些希望通过调优 Windows 体验提升生产力的人群。规格特别指出:PowerToys 用户群体对 SCOOBE 这类弹窗普遍有抵触情绪,因此对话框必须在第一时间提供可见价值,以提高用户完整走完引导、发现全部新特性的可能性。
3.2 预期的用户与技术成果指标
规格定义了三个量化目标(属于设计文档层面的预期指标,用于度量该功能的成败):
| 指标 | 目标值 | 含义 |
|---|---|---|
| 高可靠性 | 崩溃率 < 0.1% | SCOOBE 展示与浏览过程稳定 |
| 激活率提升 | 已使用相关工具的用户对新增特性/工具的采用率 ≥ 50% | What's New 内容确实驱动了新功能的激活 |
| 高留存 | 升级后 28 天内活跃 PowerToys 用户 ≥ 25% | SCOOBE 有助于维持长期活跃 |
3.3 度量需求(Measure Requirements)
为了回答"SCOOBE 是否有效",规格设计了 6 项埋点度量,覆盖用户行为与设备特征:
| No. | 度量项 | 设计用途 | 优先级 |
|---|---|---|---|
| 1 | 升级后首次运行的日期/时间 | 按接触过 SCOOBE 的用户群体归类使用与留存趋势 | P0 |
| 2 | 查看过的 SCOOBE 区块(section) | 衡量 SCOOBE 对话框激活情况;SCOOBE 上线后当前版本应达到 100% | P0 |
| 3 | 对文档链接的访问 | 评估用户想深入了解的 PowerToys 模块 | P1 |
| 4 | 对设置页面的访问 | 评估对话框中呈现的设置项是否满足用户需要 | P1 |
| 5 | SCOOBE 窗口活跃期间启动的 PowerToys 功能 | 追踪用户在浏览内容时的实际功能参与度 | P1 |
| 6 | 屏幕尺寸 | 为内容展示所需的最小/最大窗口尺寸提供依据 | P2 |
其中"窗口打开"这一事件在实现中已有对应物:App.xaml.cs 的 OpenScoobe() 会先写入遥测事件再创建窗口,相关事件类位于 ScoobeStartedEvent.cs:
public void OpenScoobe()
{
PowerToysTelemetry.Log.WriteEvent(new ScoobeStartedEvent());
// ... 创建 ScoobeWindow 实例
}
——引自 App.xaml.cs。
4. 功能需求规格
4.1 功能需求总览(Functional Requirements)
SCOOBE 对话框基于已有 OOBE 对话框(最初源自社区的设计草图)扩展而来。规格给出的功能需求如下:
| No. | 需求 | 优先级 |
|---|---|---|
| 1 | PowerToys 被升级后运行时,SCOOBE 对话框应立即启动 | P0 |
| 2 | SCOOBE 应承载在既有 OOBE 对话框中独立的"What's New"页内(见 mock-up) | P0 |
| 3 | SCOOBE 内容应外置于应用,存放于 PowerToys GitHub 上每个 release 独立的 wiki 页中 | P0 |
| 4 | 打开"What's New"页时,内容从上述 wiki 页加载(前提:用户设备联网) | P0 |
| 6 | SCOOBE 展示的是用户已安装/升级到的那一版本所发生的更新 | P0 |
| 7 | 若为首次安装,应先展示 OOBE 的"Welcome to PowerToys"页,而非 SCOOBE 的"What's New"页 | P0 |
| 8 | SCOOBE 页面内容结构须遵循下文"页面内容"约束 | P0 |
| 9 | 首次查看后,用户仍可随时重新打开 OOBE 窗口并选择"What's New"页再次访问 | P1 |
关于需求 3 的规格注释(重要设计权衡): 内容存放于应用外部,团队便不必被 PowerToys 的发布节奏捆绑,可以在任意时刻更新/修正文案。这对于处理错误表述或信息纠偏尤为关键——若内容随版本打包进本地应用,一旦出错几乎难以在已发布的版本上修正。规格预计内容将以归档形式维护在 PowerToys GitHub Wiki 中。
4.2 页面内容规格(Page Content)
"What's New" 页面的内容组织规则如下:
| No. | 需求 | 优先级 |
|---|---|---|
| 1 | 页面应展示用户已安装的 PowerToys 版本号 | P0 |
| 2 | 信息分两个区段:"New Features & Improvements"(新特性与改进)与 "Bug fixes Highlights"(修复亮点) | P0 |
| 3 | 新特性与改进区段收录新增/更新的用户功能 | P0 |
| 4 | 新特性与改进区段按被更新的实用工具细分(如 Color Picker、FancyZones 等) | P1 |
| 5 | 修复亮点区段收录值得注意的已修正问题/错误 | P0 |
| 6 | 若有相关可视化素材,应与说明文字一并展示 | P1 |
| 8 | 内容超出可视范围时对话框应支持滚动 | P0 |
| 10 | 页面底部提供指向 PowerToys releases 页的链接,以查看完整版本列表与发布说明 | P1 |
值得注意:本需求表中的编号 7/9 在规格原文中空缺,属该 Draft 文档的草稿痕迹,不影响对内容约束的理解。
4.3 从"wiki 页存放"到"Releases API 拉取":实现的演进
规格第 4.1 节假设内容存放在 GitHub Wiki 页,而当前仓库的实现改为消费 GitHub Releases API:ScoobeWindow.xaml.cs 中通过 HTTP GET 请求 PowerToys 官方仓库的 Releases 端点(per_page=100),把返回 JSON 反序列化为 release 对象列表,再就地加工渲染。每个 release 对象携带正文(release notes 的 Markdown)、版本号、发布日期、预发布标记等字段——TagName、Name、PublishedDate、ReleaseNotes、IsPrerelease 均可从源码直接看到被使用。
两者目标一致(内容外置、不随包发布、可随时修订),实现上则把"外置内容"从人维护的 wiki 页换成了"仓库发布物本身",并让应用在本地完成裁剪与再排版。规格文档是 Draft 状态,本文以仓库代码的实际行为为准。
5. 用户价值与适用场景
从产品角度,SCOOBE 面向两类诉求:
- 升级后发现式引导:升级 PowerToys 后第一次运行即弹出,用户无需离开应用即可了解新东西;
- 随时回看:错过首次弹窗后,仍可从设置界面等处重新进入 What's New。
规格中的 P0/P1 分级恰好反映这一形态:P0 保证"升级后必达 + 内容正确组织",P1 提供"回访入口 + 低门槛信息分区"。
6. 规格到代码:仓库中的落地实现
规格中的设计在当前仓库已有完整实现。核心组件位于设置 UI 工程:
6.1 入口与启动时机
窗口的启动由命令行参数驱动。App.xaml.cs 中:
- 解析
ShowScoobeWindow参数并赋值ShowScoobe; - 用
if (!ShowOobe && !ShowScoobe)区分普通启动(直接进入设置主界面)与需要展示引导窗口的启动; - 当
ShowScoobe为真时调用OpenScoobe(),先发送ScoobeStartedEvent遥测事件,再实例化ScoobeWindow。
这与规格需求 1(升级后立即展示)与需求 7(首次安装展示 Welcome 而非 What's New)对应:首次安装走 OOBE 窗口,升级走 SCOOBE 窗口,二者互斥分流。OOBE 侧的窗口与逐模块视图分别位于 OobeWindow.xaml 和 OOBE/Views 目录(内含每个工具独立的一对 Oobe*.xaml/.cs)。
6.2 窗口结构与取数流程
ScoobeWindow.xaml 是一个基于 WinUIEx.WindowEx 的 WinUI 3 窗口,默认尺寸 1100×700、最小 480×480,使用 MicaBackdrop 背景;ScoobeWindow.xaml.cs 中的加载流程为:
- 窗口内
NavigationView_Loaded触发异步LoadReleasesAsync(); - 显示
LoadingProgressRing,随后调用FetchReleasesFromGitHubAsync(); - 取数使用带系统代理的
HttpClient(DefaultProxyCredentials、WebRequest.GetSystemWebProxy()),请求头设置User-Agent: PowerToys,向 GitHub Releases API 请求最多 100 条 release; - 通过源生成(source generation)的
JsonSerializer上下文反序列化 JSON; - 失败时展示
ErrorInfoBar(加载错误 + "重试"按钮),对应规格"需要联网"的前提约束。
6.3 版本分组:NavigationView 左侧导航
CreateReleaseGroups() 实现规格"按版本展示"的诉求:
- 若应显示预发布(用户设置开启
IncludePrereleaseUpdates,或当前自身是 preview 渠道构建),则先把最新的 10 条预发布作为一组放入列表; - 稳定的 release 取最近 20 条,按
major.minor(如0.96)做GroupBy聚合成组; - 每组对应 ScoobeReleaseGroupViewModel.cs:
VersionText由TagName去掉前缀v(如v0.96.0→0.96.0),DateText显示发布日期所在月(如 "December 2025"),预发布组单独标记; - 分组结果显示在左侧
NavigationView.MenuItems(日期为主标题、版本为副标题),默认选中第一组。
选中任一版本组后,NavigationFrame.Navigate(typeof(ScoobeReleaseNotesPage), viewModel.Releases) 把该组的所有 release 对象传给内容页——这就是"展示用户升级到的那一版本的更新内容"的数据基础。
6.4 内容页渲染:Markdown 加工流水线
ScoobeReleaseNotesPage.xaml.cs 使用 CommunityToolkit 的 MarkdownTextBlock 渲染,其 ProcessReleaseNotesMarkdown() 对每个 release 正文执行一串正则与文本加工,正好落实规格"不能照搬 release notes、必须易于消费"的非目标:
| 加工步骤 | 实现方式 | 目的 |
|---|---|---|
| 多版本合并 | 版本间插入 --- 分隔线与空行 |
一组内可连续浏览多个小版本 |
| 预发布标记 | 追加 Preview 徽章文案 | 让用户知晓内容对应非稳定版 |
| 标题与日期 | 生成 # {release.Name} + 本地化月份日期 + "View on GitHub" 链接 |
明确版本与出处 |
| 剔除哈希段 | 正则删除 ## Installer Hashes 及之后内容(分带 ## Highlights 与热修复无 Highlights 两种情形) |
展示区不出现安装包哈希等技术噪音 |
| Hero 图提取 | 正则匹配 alt 文本含 "Hero" 的图片,仅取最后一张置于页首大图位,并从正文移除 | 兼顾视觉亮点与正文整洁 |
| PR/Issue 链接化 | 用负向断言 (?<!\[)#(\d+)(?!\]) 将裸 #数字 转为对应 Pull Request 链接 |
引用可点击、可溯源 |
| 主题自愈 | 由于 MarkdownTextBlock 会把标题/链接画刷锚定在 OS 主题,代码在明暗主题切换时重设 RequestedTheme 并回填标题与链接画刷 |
保证浅色/深色主题下标题与链接可读 |
规格 5.1.3 给出的"按工具分组 + 两级列表"文案结构(见第 8 节示例)在真实发布正文中由社区按规范书写,应用侧以 Markdown 原样保留其 ## 分级结构,正文中以 ## New Features & Improvements / ## Bug fixes Highlights 呈现两区段,工具名再作为下级标题细分——与规格 4.2 的内容约束一致。
6.5 回访入口与开关
规格需求 9(可随时重新访问)在 UI 侧有多处入口:
- 设置主界面 DashboardPage.xaml 提供 "What's new" 按钮;
- 更新状态控件 UpdateStatusControl.xaml 中的
SeeWhatsNew按钮(x:Uid="SeeWhatsNew")与 ShellPage.xaml 的WhatIsNew_NavViewItem均可再次拉起 What's New 内容; - GeneralPage.xaml 提供 "升级后显示 What's new" 复选框(
ShowWhatsNewAfterUpdates),允许用户在常规设置中关闭升级后自动弹窗——这与规格中"用户群体对弹窗有抵触"的预期相匹配。
窗口底部还内置"打开设置"入口(Scoobe_OpenSettings 导航项),对应规格"浏览内容后一键进入配置"的体验闭环。
6.6 本地化、测试与既有验证
- 所有可展示文案均通过
x:Uid绑定到 en-us/Resources.resw 等语言资源文件(如ScoobeWindow_Title、Oobe_WhatsNew_LoadingError、Scoobe_OpenSettings、ScoobeReleaseNotes_PreviewBadge、ScoobeReleaseNotes_ViewOnGitHub等),并经由ResourceLoaderInstance读取,天然具备多语言能力; - 分组逻辑存在单元测试覆盖:ScoobeReleaseTests.cs;
- 启动遥测事件定义于 ScoobeStartedEvent.cs。
7. 内容结构示意(规格示例)
规格 5.1.3 给出了升级内容的结构化示例,展示"What's New"文案应如何组织为"两区段 → 工具 → 要点"的形式。以下为规格原文示例(用于说明文案的书写格式,非当前版本实际内容):
v0.29 → v0.31:
- New Features & Improvements
- FancyZones
- Dark mode for the editor
- Certain settings(如分区数量、间距设置)现可对单个布局分别设置
- PowerToys Run
- 服务管理插件(Start、stop…)
- 注册表键插件
- 系统操作插件(Reboot、lock...)
- FancyZones
- Bug fixes Highlights
- Fixed OneDrive SVG Bug (#9999)
- SVG 在提供 view box 时按比例缩放 (#9999)
v0.31 → v0.33:
- New Features & Improvements
- General
- 新增"首次加载"体验,以轻量快速的方式了解基础功能
- FancyZones
- 新增切换分区激活算法的选项
- PowerToys Run
- 插件管理器移入设置,可直接开关、纳入通用搜索、修改 action key
- 通过抽象 shell 进程调用来改进对其他窗口管理器的支持
- Folder 插件中
~将解析为用户主目录
- General
- Bug fixes Highlights
- 修复 PT Run 在不支持的 OS 版本上注册热键的问题 (#9999)
v0.33 → v0.35:
- New Features & Improvements
- Color Picker
- 可用 Esc 退出取色器编辑
- FancyZones
- 自定义布局支持热键与快速交换:在编辑器中分配热键后,可用
Ctrl+Win+Alt+数字或拖拽窗口时按热键快速套用分区
- 自定义布局支持热键与快速交换:在编辑器中分配热键后,可用
- PowerToys Run
- 可指定启动器窗口的显示位置
- 新增插件支持打开近期使用的 VS Code 工作区、远程机器(SSH 或 Codespaces)与容器(默认关闭,启用后用
{查询) - Shell 历史现在保存原始命令而非解析后命令(如
%appdata%不再被保存为绝对路径)
- Color Picker
- Bug fixes Highlights
- PowerToys 将在 0.35.x 之后要求 Windows 10 v1903 或更高版本 (#9999)
- 修复任务栏垂直时 FancyZones 的布局算法 (#9999)
这些示例正文体现的两点设计原则延续至今:每个工具一个小节(便于快速定位感兴趣的功能)、每个要点一行(便于滚动扫读)。
8. 界面布局 Mock-up
规格附带的线框稿展示了预期界面布局。下图为规格 5.1.1 的 SCOOBE 对话框布局:顶部含窗口标题栏与"What's New"主导航,左侧为按版本组织的条目,右侧为某版本的新特性/改进说明区域,支持按工具展开阅读:
下图为规格 5.1.2 的 OOBE Welcome 页面——首次安装(非升级)时用户首先看到的是它,而不是 What's New:
两图共同说明了规格需求 2 与需求 7:SCOOBE 内容在形态上沿用 OOBE 的对话框框架,但按启动场景(升级 vs 首次安装)决定默认呈现哪一页。
9. 限制与边界说明
结合规格与实现,使用 SCOOBE 时需注意以下事实性边界:
- 需要联网:内容实时取自 GitHub Releases API,离线或代理异常时窗口会显示错误条并支持重试(规格同样假设"设备已连接互联网");
- 非归档副本:规格明确它不是 release notes 的复制品;实现进一步做了剔除哈希、提取 Hero 图、PR 号链接化等精简处理,正文仍以 GitHub 为最终来源;
- 属于可关闭体验:用户可在常规设置中关闭"升级后显示 What's new",避免打扰;
- 规格为草稿:
doc/specs/SCOOBE.md标注 Spec Status 为 Draft,部分条目编号存在空缺(如 4.1 表缺 5/8、4.2 表缺 7/9),个别设计假设(wiki 页存放内容)与当前实现(Releases API)存在差异——阅读与引用时以仓库代码为准。
10. 延伸阅读
- 设计规格全文:SCOOBE Dialog 规格文档
- SCOOBE 窗口实现:ScoobeWindow.xaml 与 ScoobeWindow.xaml.cs
- 内容渲染页:ScoobeReleaseNotesPage.xaml.cs(含完整的 Markdown 加工流水线)
- 版本分组 ViewModel:ScoobeReleaseGroupViewModel.cs
- 启动分流与窗口打开:App.xaml.cs
- 首次安装体验(OOBE)窗口与逐工具视图:OobeWindow.xaml、OOBE/Views 目录
- 单元测试与遥测事件:ScoobeReleaseTests.cs、ScoobeStartedEvent.cs
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00

