feat: tray, window-state, sqlite cache, decrypt worker

System tray (desktop)
- tauri tray-icon feature + tray with menu (Öffnen/Ausblenden/Beenden)
- Left-click toggles main window; right-click shows menu
- JS emits tray-unread-update event, Rust mirrors into tooltip +
  macOS dock badge via set_badge_label
- ConversationsContext wires totalUnread → tray

Window state persistence
- tauri-plugin-window-state (desktop-only target guard)
- Auto-restore size/position/maximized between restarts

Local SQLite message cache
- tauri-plugin-sql hydration of conversation view on mount
- persistMessages after each refresh, deleteCachedMessage on realtime
  DELETE, pruneCache keeps latest 1000 per conversation
- Stores plaintext only (same trust boundary as stronghold device
  key; cache never leaves the device, E2EE w.r.t. server unchanged)

Web Worker for decryption
- workers/decrypt.worker.ts runs crypto_secretbox_open_easy + utf-8
  decode off the main thread with its own libsodium instance
- lib/decryptWorker.ts is a request/response wrapper with inline
  fallback when Worker spawn fails
- shared decryptMessages accepts aeadBatchDelegate so key lookup
  stays on the main thread while the AEAD loop offloads

Build fix
- Enable tauri tray-icon feature
- Import Listener + Manager traits, clone tray handle for the
  event listener, conditional icon attach
This commit is contained in:
2026-04-21 10:07:20 +02:00
parent 24fdfee738
commit 228608ef2c
11 changed files with 607 additions and 11 deletions
+2 -1
View File
@@ -14,7 +14,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
tauri-build = { version = "2", features = [] }
[dependencies]
tauri = { version = "2", features = ["devtools"] }
tauri = { version = "2", features = ["devtools", "tray-icon"] }
tauri-plugin-notification = "2"
tauri-plugin-sql = { version = "2", features = ["sqlite"] }
tauri-plugin-stronghold = "2"
@@ -25,6 +25,7 @@ serde_json = "1"
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
tauri-plugin-global-shortcut = "2"
tauri-plugin-updater = "2"
tauri-plugin-window-state = "2"
[features]
# This feature is used for production builds or when `devPath` points to the filesystem