From 510eae208956415c2faf149f27fc55bdb0e7711d Mon Sep 17 00:00:00 2001 From: Siavash Sameni Date: Fri, 10 Apr 2026 11:03:36 +0400 Subject: [PATCH] feat(direct-call): call history, recent contacts, deregister button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Persistent JSON-backed call history for the direct-call screen so users can see what they've placed / received / missed and dial back with one click. Also fixes two small latent UX issues reported alongside. Backend (Rust) - new crate/module desktop/src-tauri/src/history.rs: thread-safe in- process store (OnceLock>>) backed by /call_history.json. Atomic writes via temp+rename. Max 200 entries, FIFO pruning. CallDirection { Placed, Received, Missed }. - Log hooks in the signal loop + commands: * place_call → Placed entry (with target fingerprint) * DirectCallOffer → Missed entry up front; upgraded to Received inside answer_call when accept_mode != Reject via history::mark_received_if_pending(call_id). If user rejects or never answers, it stays Missed. - New Tauri commands: * get_call_history() → all entries, newest first * get_recent_contacts() → unique peers by fp, newest interaction first * clear_call_history() → wipes JSON + in-memory * deregister() → tears down signal transport + endpoint Backend emits `history-changed` events so the UI can live-refresh without polling. Frontend (main.ts + index.html + style.css) - Direct-call panel now has: * Recent contacts chip row (top 6 unique peers). Click a chip → dial. * Call history list (up to 50 rows). Direction icon (↗ placed, ↙ received, ✗ missed), peer alias/fp, relative timestamp, callback button. Both click handlers populate target-fp and fire place_call. * Deregister button in the "registered" header — calls the new deregister command, tears down the signal transport, returns the UI to the pre-register state. * Clear-history link in the history header. - Subscribes to `history-changed` events so the list updates the moment the backend logs a new entry. Also refreshed on register + after a clear. - Nothing is rendered until there is data — empty sections stay hidden. Tasks #20 + #21 (small UX items bundled in) - Default room "general" for new installations: the html input value attribute is now "general" and loadSettings() defaults match. Existing users' localStorage still wins. - Random alias on desktop: already latent but confirmed working — the startup IIFE at main.ts:374 calls get_app_info() and prefills the alias input from derive_alias(seed) when the input is empty. No code change needed, just verified it flows through the same path as the Android client. Known follow-ups (deferred to step 6 polish) - Call duration tracking (currently all entries have no duration field) - Hangup signal from an unanswered incoming should emit history-changed so the missed state is visible even when the user never tapped accept - Android UI layout fit-check on the smaller Nothing screen --- desktop/index.html | 23 ++++- desktop/src-tauri/src/history.rs | 161 +++++++++++++++++++++++++++++++ desktop/src-tauri/src/lib.rs | 78 ++++++++++++++- desktop/src/main.ts | 131 ++++++++++++++++++++++++- desktop/src/style.css | 139 ++++++++++++++++++++++++++ 5 files changed, 525 insertions(+), 7 deletions(-) create mode 100644 desktop/src-tauri/src/history.rs diff --git a/desktop/index.html b/desktop/index.html index eef1b05..bea31aa 100644 --- a/desktop/index.html +++ b/desktop/index.html @@ -21,7 +21,7 @@