Skip to content

ZH Windows 11 WinUI Guide

SlimRG edited this page Aug 23, 2026 · 1 revision

Windows 11 / WinUI 3 指南

本文定义当前 UI 设计与实现规则,不是迁移历史。

Shell

  • Shadowsocks.WinUI 是唯一主桌面 UI。
  • 使用现有 NavigationView 和 Settings entry。
  • 支持时使用 Mica Base。
  • 关闭窗口只隐藏;tray 一直运行到显式 Quit。
  • Persistent settings 放在主设置页面;tray 只保留快速 runtime actions。
  • tray/QR/power 集成属于 Shadowsocks.Windows.WinUI;基础 Shadowsocks.Windows 保持 WinUI-free。

布局与字体

  • 标准页面 gutter:24 epx;compact navigation:12 epx。
  • 尺寸优先使用 4 的倍数。
  • 使用 WinUI typography resources,如 TitleTextBlockStyleBodyTextBlockStyleCaptionTextBlockStyle
  • UI 文案使用 sentence case。
  • 状态不能只依赖颜色,需结合文字、glyph 或 selection state。

推荐控件

  • NavigationView:导航;
  • ContentDialog:模态确认;
  • InfoBar:非阻塞状态/错误;
  • TeachingTip:上下文提示;
  • NumberBox:端口/超时;
  • ToggleSwitch:布尔设置;
  • ComboBox:固定选项。

不要为了某个控件重新引入 WinForms/WPF。

Traffic / Game Mode

用户可选 traffic mode 只有:

  • User Mode;
  • Administrator Mode。

Game Mode 是自动状态,不是第三种 mode。Admin Mode 显示 UAC/shield,并显示 NetworkService、WinDivert、TCP/UDP capture 状态。

Servers / Plugins

Server Name 位于 Server IP 之前。

Plugin 使用 ComboBoxNone + PluginManager 已安装插件。Plugin Options / Plugin Arguments 是 per-server 设置。

Plugins 页面负责 install/remove;built-in Install 下载 latest Windows x64 release。导入引用已知 built-in plugin 但尚未安装的 ss:// 时,UI 会先提供安装,也明确提供不安装直接导入或取消。Catalog-installed plugin 提供 Automatic updates,在未被使用时每天自动检查一次,也可通过 Check updates 手动检查。正在使用的 package 会被推迟,manual ZIP/TAR.GZ import 永不进行后台网络更新。任意 repository 字段在 repository trust/asset-selection 设计完成前保持不可用。UI 不暴露任意 PATH/absolute executable fallback。

手工创建的 server 可以显示密码;由 ss:// 或 online configuration 导入的 credentials 保持 reveal-protected。

Logs

Logs toolbar 始终可见。Viewer 使用可选择文本的 RichTextBlock,不恢复旧 ListView。长行不得破坏页面 layout;WARN/ERROR/FATAL 保留明显样式。

Top Most 使用 WinUI/AppWindow,不使用 WinForms/WPF。

PAC / GeoSite

Local routing 固定为 managed C#,不再显示 backend selector。Local PAC 模式下页面显示 effective mode、snapshot generation/source、rule counts、DIRECT/PROXY counters、Admin managed-routing state,并提供 Open user-rule.txt 编辑用户 ABP/EasyList-style 规则。

Online PAC 是独立显式模式。选中后隐藏 Local managed routing、Local user rules 与本地 GeoSite source 卡片。

首次安装/验证/激活 DNSCrypt 时,UI 全程显示活动的 ProgressRing/ProgressBar 与操作文本;暂不可用的 DNS 设置隐藏,避免整页 disabled 给用户造成卡死错觉。

本地化

  • UI 通过 ILocalizationService
  • shell/pages/tray 共享同一 service instance。
  • 持久化 enum/config value 不能使用翻译后的 label。
  • CSV locale 顺序:en,ru-RU,zh-CN,zh-TW,ja,ko,fr
  • 唯一 runtime localization source 是 embedded i18n.csv

启动生命周期

Program.Main 执行 AppInstance redirect 与 ProcessSingleInstanceGuard,然后通过公共 Application.Start 启动 WinUI。App 保持 parameterless,以兼容 generated XAML。

上下文可见性与操作状态

  • 仅在特定场景有意义的 controls 应在无关时隐藏,而不是留下大块 disabled UI,例如 Plugin=None、No forward proxy、Online PAC 与 Local PAC、以及非 Admin runtime 下的 Admin diagnostics。
  • 依赖 selection 的操作在有效选择前保持禁用;Save/Discard 必须反映真实未保存状态;重复项的 Add 保持禁用。
  • 长时间 network/package 操作必须显示可见进度,并在完成前阻止冲突编辑/操作;适用于 DNSCrypt、GeoSite refresh、online configurations、plugins 与 application update。
  • Online PAC URL 在页面和 tray 使用完全相同的校验,仅接受绝对 HTTP/HTTPS URL;保存的 URL 无效时必须先修正才能启用 Online PAC。
  • 不应因为暂时取消上下文选项就销毁隐藏字段中的未保存值;应在真正 Save 时再进行规范化/清空。
  • 如果操作含义随上下文变化,label 与 tooltip 必须同步更新(例如 Plugins 的 InstallReinstall)。
  • 如果操作因未保存的前置状态而被有意禁用,应使用可见的本地化文本明确说明原因,而不是让用户自行猜测(例如 GeoSite sources 必须先保存才能 refresh)。

Accessibility

非显而易见的 control 应同时有本地化 ToolTip 和 AutomationProperties.HelpText。键盘导航与 selection 不得只依赖鼠标或颜色。

Windows App SDK 升级检查

升级包后执行 clean restore/build,并 smoke-test:

  • NavigationView;
  • ContentDialog;
  • InfoBar;
  • TeachingTip;
  • NumberBox;
  • ToggleSwitch;
  • tray;
  • QR import;
  • main window lifecycle。

DNSCrypt 解析器目录引导

Shadowsocks Reborn 由应用自身刷新已签名的 DNSCrypt 解析器目录,不允许 dnscrypt-proxy 通过 bootstrap DNS 解析远程 source 主机名。主解析路径为 Cloudflare DoH(1.1.1.1,TLS/SNI cloudflare-dns.com),备用路径为 Google DoH(8.8.8.8,TLS/SNI dns.google);两条 DoH HTTPS 连接都通过当前本地 Shadowsocks SOCKS5 打开。源主机名经该 DoH 路径解析后,public-resolvers.md.minisig 的 HTTPS 下载同样通过 Shadowsocks。

下载大小受到限制,并在发布前使用固定的 DNSCrypt 公共 Minisign 密钥验证。随后 dnscrypt-proxy 只获得本地认证缓存,配置为 urls = []bootstrap_resolvers = []ignore_system_dns = true。如果刷新暂时失败,可以继续使用已有且签名有效的缓存;若不存在有效缓存,则操作 fail-closed,并保留之前的 DNS 模式。

Clone this wiki locally