Files
Windows-Gotify-Client-Rust/README.md
T
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

156 lines
7.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Windows-Gotify-Client-Rust
轻量、现代、Windows 原生体验良好的 Gotify 桌面客户端,使用 **Rust + Slint** 构建。
> 详细的产品定位、技术栈约束、架构、UI 规范与分阶段实施计划全部记录在 [`AGENTS.md`](./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/ # 预留
```
## 开发
```powershell
# 编译(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](./LICENSE))。