diff options
Diffstat (limited to 'src/features/messages.js')
| -rw-r--r-- | src/features/messages.js | 40 |
1 files changed, 34 insertions, 6 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index cde11dc..54c9cfe 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -2507,6 +2507,9 @@ export function messagesFeature(ctx) { ? [...new Set(newest.tags.filter((x) => x[0] === 'p' && /^[0-9a-f]{64}$/.test(x[1] || '')).map((x) => x[1]))] : []; const known = [...threads.keys()]; + // who may ring us when the app is shut: those we've written to (the + // follows ride separately); `known` stays the DM filter's wider list + const rings = known.filter((pk) => wroteTo(pk)); const names = {}; for (const pk of [...follows, ...known]) { const p = profiles.get(pk); @@ -2515,7 +2518,7 @@ export function messagesFeature(ctx) { await saveInbox(wallet._cacheKey(), { pubkey: id.pubkey, sk: id.signer instanceof Uint8Array ? bytesToHex(id.signer) : null, - follows, known, names, hasList: !!newest, updated: Date.now(), + follows, known, rings, names, hasList: !!newest, updated: Date.now(), muted: [...mutesNow().set], // no buzz from a muted sender either }); } catch { inboxAt = 0; } @@ -9091,8 +9094,18 @@ export function messagesFeature(ctx) { return navigator.mediaDevices.getUserMedia(type === 'video' ? { audio, video } : { audio }); } // who may ring: someone you follow, or someone you've written to - const mayRing = (pk) => !hiddenPk(pk) && (followsNow().set.has(pk) - || [...(threads.get(pk) || new Map()).values()].some((m) => m.mine)); + // who may ring: someone you follow, or someone you've written to. Anyone + // else's call doesn't ring but is told of, as a missed call that didn't + // ring (a wife's call must not vanish because you never followed her); + // a muted person's leaves nothing. + const mayRing = (pk) => hiddenPk(pk) ? null + : followsNow().set.has(pk) || wroteTo(pk) ? 'ring' : 'quiet'; + // a message of ours in the conversation — not a call logged there (a + // stranger's unrung call would otherwise let their next one ring) + function wroteTo(pk) { + for (const m of (threads.get(pk) || new Map()).values()) if (m.mine && m.rumor.kind !== CALL_LOG) return true; + return false; + } function callsNow() { if (calls) return calls; calls = createCalls({ @@ -9128,7 +9141,7 @@ export function messagesFeature(ctx) { // devices list it too. A call rung on two of our devices is logged by // both; the conversation shows it once, by its call-id. const callStatus = (rec) => rec.connected ? 'answered' - : rec.reason === 'missed' ? 'missed' + : rec.reason === 'missed' || rec.reason === 'unrung' ? 'missed' : rec.reason === 'declined' || rec.reason === 'peer-declined' ? 'declined' : rec.reason === 'no-answer' ? 'no-answer' : rec.reason === 'busy' ? 'busy' @@ -9157,7 +9170,7 @@ export function messagesFeature(ctx) { kind: CALL_LOG, pubkey: id.pubkey, created_at: Math.floor((rec.at || Date.now()) / 1000), content: callLogText(rec.dir, rec.type, status, rec.seconds), tags: [['p', rec.peer], ['call-id', rec.id], ['call-type', rec.type], ['direction', rec.dir], ['status', status], - ['duration', String(rec.seconds || 0)], ['alt', 'Call log']], + ['duration', String(rec.seconds || 0)], ...(rec.reason === 'unrung' ? [['rang', 'no']] : []), ['alt', 'Call log']], }); noteDM(rec.peer, rumor, true); persistDms(); @@ -9184,11 +9197,15 @@ export function messagesFeature(ctx) { const tag = (k) => (m.rumor.tags.find((x) => x[0] === k) || [])[1]; const type = tag('call-type') === 'video' ? 'video' : 'voice', status = tag('status') || 'failed', dir = tag('direction') || 'out'; const missed = status === 'missed' || (dir === 'in' && status === 'declined'); + // a call that didn't ring (someone you don't follow), saying so — and, + // while that's still so, how to have them ring next time + const unrung = tag('rang') === 'no'; return h('div', { class: 'chat-row call-log' + (missed ? ' missed' : ''), 'data-call-log': tag('call-id') || '' }, h('button', { type: 'button', class: 'call-log-pill', title: t(type === 'video' ? 'callVideo' : 'callVoice'), onClick: () => startCall(peer, type) }, callIcon(type === 'video' ? 'video' : 'phone'), h('span', {}, callLogText(dir, type, status, +tag('duration') || 0)), - h('span', { class: 'chat-time' }, timeLabel(m.rumor.created_at * 1000)))); + h('span', { class: 'chat-time' }, timeLabel(m.rumor.created_at * 1000))), + unrung ? h('div', { class: 'small faint call-log-why' }, t(mayRing(peer) === 'ring' ? 'callLogUnrungWas' : 'callLogUnrung')) : null); } // the call offer a push brought (sw-nwc.js keeps it): rung now, once @@ -9196,6 +9213,17 @@ export function messagesFeature(ctx) { try { if (typeof caches === 'undefined') return; const cache = await caches.open('coinos-call'); + // calls the worker saw from people who don't ring us: logged, unrung + const quiet = await cache.match('/__quiet-calls'); + if (quiet) { + await cache.delete('/__quiet-calls'); + for (const offer of (await quiet.json()) || []) { + if (!offer || !offer.pubkey || !mayRing(offer.pubkey)) continue; + const id = (offer.tags.find((x) => x[0] === 'call-id') || [])[1]; + const type = (offer.tags.find((x) => x[0] === 'call-type') || [])[1] === 'video' ? 'video' : 'voice'; + if (id) logCall({ id, peer: offer.pubkey, type, dir: 'in', reason: 'unrung', seconds: 0, at: offer.created_at * 1000 }).catch(() => {}); + } + } const r = await cache.match('/__pending-call'); if (!r) return; await cache.delete('/__pending-call'); |
