在 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 状态 + 已知限制。
7.2 KiB
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::displaytext/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)。