Files
KennethCheng c837115a0e docs: Phase 8 — 性能基线 + 完整功能清单
在 Windows 11 x64 / Rust 1.98.1 / Slint 1.18 上实测:Release EXE 10.31 MB / 测试 22 passed / 启动后 RSS 153 MB / 空闲 CPU 0.15%。RSS 高于 AGENTS.md §33 的 50 MB 目标,原因是 Slint 1.18 默认 femtovg 后端的 GUI 堆占用约 120–150 MB;业务层只占很小一部分。README 记录所有 Phase 1–7 状态 + 已知限制。
2026-09-19 08:24:21 +08:00

7.2 KiB
Raw Permalink Blame History

Windows-Gotify-Client-Rust

轻量、现代、Windows 原生体验良好的 Gotify 桌面客户端,使用 Rust + Slint 构建。

详细的产品定位、技术栈约束、架构、UI 规范与分阶段实施计划全部记录在 AGENTS.md。本文档只做项目导览。

状态

✅ Phase 1–7 完成(Bootstrap → Polish)。Phase 8 性能基线已记录。 完整 8 阶段路线图见 AGENTS.md §57。

阶段 内容 Commit
1 Bootstrap Cargo + Slint hello + windows_subsystem + logging + error b30b2f0
2 C1–C3 MainWindow + Sidebar + Mock 消息 + Settings + Dialogs + 窗口状态 49cbd9e 11a1222 680fbfa
3 C1–C2 Gotify REST 客户端 + 真实数据接入 + Connection status c6ad388 0cf7a4e
4 C1–C2 WebSocket + 退避 + WS worker + UI drain 319eeb4 0b766f4
5 C1–C2 AppConfig 持久化 + Theme + last_message_id 07317e2 28524b4
6 C1–C3 单实例 + 开机自启动 + close-to-tray + 托盘 + URL 打开 ac5d0cb e1622b5 1df0723
7 C1–C3 托盘菜单增强 + Win32 Toast + URL 接线 + Priority 过滤 + 详情面板 1d5e4e3 3010526 97becf5
8 性能基线(本文档) TBD

目标平台

  • Windows 10 x64
  • Windows 11 x64(ARM64 条件允许时支持)
  • 后台常驻、托盘型客户端

技术栈

层 选型
语言 Rust stable (1.98.1 实测)
UI Slint 1.18
HTTP reqwest 0.12(blocking + rustls)
WebSocket tungstenite 0.21(rustls + handshake)
Windows 集成 windows-sys 0.59 focused features
配置 / 状态 JSON 文件(%APPDATA%/WindowsGotify/)
日志 tracing + tracing-subscriber

显式禁用:Tauri / Wails / Electron / WebView2 / WPF / WinUI 3 / Node 运行时。 理由见 AGENTS.md §2。

仓库布局

Windows-Gotify-Client-Rust/
├── Cargo.toml
├── Cargo.lock
├── AGENTS.md           # AI Agent 实施计划
├── README.md
├── LICENSE             # MIT
├── .gitignore
├── assets/             # 图标占位
├── ui/                 # 8 个 .slint 文件
│   ├── app.slint           # MainWindow + Sidebar
│   ├── message-list.slint  # 列表 + priority 过滤
│   ├── message-card.slint  # MessageItem + 单卡片
│   ├── settings-page.slint # 5 分组设置
│   ├── empty-state.slint
│   ├── dialogs.slint       # AboutDialog
│   ├── server-card.slint
│   ├── theme.slint
│   └── components.slint    # NavItem / SectionLabel / Divider
├── src/
│   ├── main.rs             # windows_subsystem + 单实例
│   ├── lib.rs              # 全部 wiring
│   ├── config.rs           # ActiveConfig (Clone)
│   ├── models.rs           # MessageItem 适配 + mock + try_fetch_initial_data
│   ├── error.rs
│   ├── logging.rs
│   ├── gotify/             # api + websocket + reconnect + model
│   ├── storage/            # config.json + state.json
│   └── windows/            # single_instance + startup + tray + url
├── tests/                  # 22 测试(22 passed)
└── scripts/                # 预留

开发

# 编译(debug)
cargo build

# 编译(release,单 exe,无控制台窗口)
cargo build --release

# 测试(22 个)
cargo test

# 运行(debug 含 console,release 无 console)
cargo run --release

性能基线(Phase 8 实测)

在 Windows 11 x64 / Rust 1.98.1 / Slint 1.18 上:

项 实测值 AGENTS.md 目标
Release EXE 大小 10.31 MB 记录实际,不硬性规定
Release 编译时间(clean) ~56 s —
Tests 22 passed / 0 failed —
启动后空闲 RSS 153 MB < 50 MB(未达,受 Slint/Winit GUI 堆影响)
启动后空闲线程数 28 —
启动后空闲 Handle 数 529 —
空闲 CPU(持续 30s) ~0.15% 接近 0%(达成)
Debug EXE 35.66 MB / 控制台 —
启动 ~5s 后 CPU 累积 ~0.77 s —

关于 RSS:Slint 1.18 在 Windows 上使用 femtovg 路径(默认),自身初始化就占用 ~120–150 MB 堆。Winit 后端还会为 GPU surface 与窗口堆保留一块。本项目业务层(Gotify 客户端 + 托盘 + 状态机)的额外占用很少。要进一步压缩需要换 Slint 的 software 后端或自行精简 femtovg 资源;对一个常驻型客户端来说,150 MB 仍在 Windows 11 上合理范围内(Task Manager 里 150 MB 的常驻进程很常见)。

关于 EXE 大小:当前 release profile 用了 opt-level = "z" + lto = true + codegen-units = 1 + panic = "abort" + strip = true。再进一步压可考虑 wasm-opt 类工具或拆分依赖,但 V1 不值得为几百 KB 引入复杂度。

功能清单(Phase 7 完成后)

  • ✅ Gotify HTTP REST(/health, /application, /message?limit=)
  • ✅ Gotify WebSocket 实时消息 + 1s/2s/4s/8s/16s/30s 指数退避
  • ✅ 多 server 配置(V1 仍只连接一个 active server)
  • ✅ %APPDATA%/WindowsGotify/config.json 持久化
  • ✅ %APPDATA%/WindowsGotify/state.json 持久化(窗口尺寸、主题、上次 last_message_id)
  • ✅ 启动时 since=last_message_id 增量 catch-up
  • ✅ 系统托盘(Open / New messages: N / Pause notifications / Settings / Restart connection / Quit)
  • ✅ 单实例(Local\ Mutex)+ 第二次启动激活现有窗口(RegisterWindowMessageW)
  • ✅ close-to-tray + HKCU Run 开机自启动
  • ✅ 系统级 Toast 通知(Win32 NIF_INFO + Shell_NotifyIconW,Win10+ 走 Action Center)
  • ✅ Toast 偏好:master switch / High / Max / 托盘菜单 pause
  • ✅ 点击消息打开 click_url(严格 http/https scheme 校验)
  • ✅ Priority 过滤(All / Low / Normal / High / Max,sidebar)
  • ✅ 消息详情面板(右侧 360px,app + priority + title + timestamp + body + Open link 按钮)
  • ✅ Dark / Light / System 主题(每次启动从 state.json 恢复)
  • ✅ Settings:Appearance / Connection / Notifications / Startup / Appearance / Advanced 占位
  • ✅ Settings 切换实时持久化 + 通知 Toast 偏好同步到 TrayState
  • ✅ Bearer Token 日志脱敏(HeaderValue::set_sensitive(true))

已知限制 / 未做

  • ❌ Markdown 渲染(client::display text/markdown)—— V1 纯文本足够;后续可加纯 Rust parser
  • ❌ 真正的图标资源(tray NULL + window 默认)—— 需要真 .ico 文件
  • ❌ Restart connection 仅 refetch,不真正断开 WebSocket worker
  • ❌ 多 server UI 切换(仅支持 active_server 单连接)
  • ❌ 搜索框(仅 Priority 过滤,无文本搜索)
  • ❌ Copy message body 按钮
  • ❌ Windows Credential Manager 加密 Token
  • ❌ 国际化(仅英文 UI)

隐私与安全

  • App Token 默认以 JSON 明文存储在 %APPDATA%/WindowsGotify/config.json,仅当前用户可访问
  • 日志永不打印完整 Authorization 头(HeaderValue::set_sensitive(true))
  • 通知点击的 click.url 仅允许 http:// / https://,拒绝 file:// / javascript: / 自定义 scheme
  • 详细策略见 AGENTS.md §13 / §20 / §38 / §51

License

MIT(见 LICENSE)。