v0.9.4 — Mobile UX, Message Actions, and Sync Reliability
[0.9.4] — 2026-08-11 — Mobile UX, Message Actions, and Sync Reliability
Highlights
- Full mobile chat screen redesign — input pinned to the bottom, conversation scrolls internally, 2×2 button grid replaces the old crowded row
- Stop, Edit, and Regenerate controls on the last exchange
- ZynkSync no longer silently re-enables itself after you pause it
Features
- Stop generation — the Send button turns red while streaming; a single tap aborts the in-flight LLM call and clears the send guard so you can retry immediately
- Edit last message — a pencil icon on your most recent user message opens an inline editor; Save & Regenerate updates the message in place, drops the stale assistant reply, and re-runs inference without duplicating the prompt in the log
- Regenerate — a button on the last assistant response re-runs the same prompt (useful when you want a different take without retyping)
- 2×2 mobile button grid — Ensemble | Clear / Memory Manager | Send-Stop, all visible without opening the keyboard
- Recent Memories widget hidden on mobile (still reachable via the Memory Manager button) — gives the conversation view more vertical room
- Mobile textarea shrunk to 3 rows / 60–135px for the same reason
- Scroll-to-bottom button appears reliably on mobile — fires on mount, triggers at 80px from the bottom (was 200px), and re-registers as new messages arrive
Bug Fixes
- ZynkSync panel re-enabled sync after user pause — the panel's mount effect was calling `start_zynksync` any time it saw the backend stopped but peers existed, which silently overrode the pause every time the panel was reopened. The backend already persists sync state and honors it on launch; the panel now only reflects that state instead of driving it.
- Duplicate Save Key button in Memory Manager — the toolbar had a Save Key button next to the 🔑 Key button, but the Key button already opened the same save flow; the duplicate was removed
- Keyboard covered the message input on older Android tablets — Chrome 64 WebView on Android 8 (Galaxy Tab S3) doesn't understand `dvh` viewport units, so the flex-column layout couldn't reflow when the keyboard appeared. The mobile-flex layout is now gated on `@supports (height: 100dvh)`, and older WebViews fall back to natural body flow where Android's default `adjustResize` handles the keyboard correctly
- Proper flex-column mobile layout replaces the previous `position: sticky` approach — input always visible at the bottom, conversation history scrolls internally, works cleanly even when the message list is empty
Deferred
- Cloud backup (Cloudflare R2) — the initial v0.9.4 build included an encrypted zero-knowledge R2 backup feature, but the export path did not serialize memory embeddings, so restored memories were invisible to semantic retrieval. Pulled from the release rather than shipping broken. Being redesigned on `feature/cloud-backup-r2` with a mesh-epoch sync model so restore state converges cleanly across all paired devices (including devices that were offline during the restore). Will land in a later release.
Internal
- Cloud backup code archived on `feature/cloud-backup-r2` branch (~1000 lines, 3 crate deps) for later redesign
- Cargo dependency footprint reduced (`aes-gcm`, `argon2`, `hmac` removed with cloud backup)
See the CHANGELOG for details.