diff options
| author | Adam Soltys <[email protected]> | 2026-10-18 09:55:40 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-10-18 09:55:40 -0700 |
| commit | d86f7cb039bbd4bf2873be332af278bc6372aeae (patch) | |
| tree | 522cc403f44619ba694f51953ea7578bc310eb41 /src/features | |
| parent | 5869fa2ce351efa485ae6547d618a216b09a47c1 (diff) | |
| download | coinosv3-d86f7cb039bbd4bf2873be332af278bc6372aeae.tar.gz coinosv3-d86f7cb039bbd4bf2873be332af278bc6372aeae.zip | |
Answering a call no longer takes seconds: while it rings, the connection is made with the caller's offer and its routes (TURN's too) gather, and the caller's relays and TURN credentials are looked up — Answer only adds the microphone and camera and replies (3.2 s → 0.2 s on a simulated network). An open conversation warms the same for calling out. A remote signer's offer or answer waits for a direct and a relayed route or 1.5 s, not for all of them (up to 4 s).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_013ZDf1cyCQLkfjftYhymZAg
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/messages.js | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index 54c9cfe..e239aee 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -9120,6 +9120,7 @@ export function messagesFeature(ctx) { mayRing: async (pk) => mayRing(pk), changed: () => { callRing(); render(); }, ended: (rec) => { logCall(rec).catch(() => {}); }, + warm: (pk) => callWarm(pk), // a key of our own signs each candidate at once; a remote signer gets // them all inside the offer or answer instead trickle: () => { try { if (localStorage.getItem('coinos-call-trickle') === '0') return false; } catch {} const id = hook('nostrLoginIdentity'); return !id || id.signer instanceof Uint8Array; }, @@ -9238,6 +9239,17 @@ export function messagesFeature(ctx) { } } catch {} } + // A call with them may be coming (it rings, or their conversation is open): + // their relays looked up, TURN fetched — the seconds the first send or + // answer used to spend on it. Not through Amber: a prompt to open a chat. + const warmed = new Set(); + function callWarm(pk) { + if (!pk || warmed.has(pk)) return; + warmed.add(pk); + inboxFor(pk).catch(() => {}); + const login = hook('nostrLoginIdentity'); + if (!(login && login.signer && login.signer.interactive)) callIce().catch(() => {}); + } function startCall(peer, type) { if (typeof RTCPeerConnection === 'undefined' || !navigator.mediaDevices?.getUserMedia) { toast(t('callUnsupported')); return; } const cur = callsNow().call; @@ -16467,6 +16479,7 @@ export function messagesFeature(ctx) { const peer = ui.msgPeer; if (!peer) { ui.msgView = 'home'; return homeView(); } const thread = threads.get(peer) || new Map(); + if (!isMe(peer)) setTimeout(() => callWarm(peer), 1500); // a call may be next const msgs = foldCallLogs([...thread.values()].sort((a, b) => a.rumor.created_at - b.rumor.created_at)); // a first message may go by White Noise: have their KeyPackage looked up before Send wnKnow(peer); @@ -17312,7 +17325,7 @@ export function messagesFeature(ctx) { clearTimeout(drainTimer); pendingWraps.clear(); dmStarted = false; - if (calls) { try { calls.stop(); } catch {} calls = null; callInbox.clear(); iceCache = null; callRing(); } + if (calls) { try { calls.stop(); } catch {} calls = null; callInbox.clear(); iceCache = null; warmed.clear(); callRing(); } listsSynced = false; if (zapLiveUnsub) { try { zapLiveUnsub(); } catch {} zapLiveUnsub = null; } clearTimeout(zapTimer); zapTimer = null; zapQueue = new Set(); zapRecent = []; |
