feat(web): host_unreachable phase copy for dm_call_undeliverable (TDD)

This commit is contained in:
Jannis Braun
2026-04-24 00:51:30 +02:00
parent 314df6c5a1
commit 5e509cf3df
2 changed files with 39 additions and 1 deletions
@@ -9,6 +9,9 @@
* - `reject`: the rejector's relay to the host failed; state was already cleared
* locally, so non-terminal info toast only.
* - `end`: the ender's relay to the host failed; state was already cleared locally.
* - `host_unreachable`: the call was terminated by the sentinel worker because the
* host peer became permanently unreachable. Always terminal. A single failure entry
* is expected; multiple fall back to a generic line.
*
* Extracted from `useWebSocket.ts` so it can be unit-tested without pulling in
* the full WS handler graph (livekit / audio deps).
@@ -16,7 +19,7 @@
export function buildCallUndeliverableToast(
failures: Array<{ reason: string; peerOrigin?: string; peerLabel?: string }>,
terminal: boolean,
phase: 'start' | 'accept' | 'reject' | 'end' = 'start',
phase: 'start' | 'accept' | 'reject' | 'end' | 'host_unreachable' = 'start',
): string {
const primary = failures[0];
const labelFor = (f: { peerLabel?: string; peerOrigin?: string }) =>
@@ -37,6 +40,21 @@ export function buildCallUndeliverableToast(
return `Couldn't notify ${labels} that you hung up. Remote participants may see the call for up to 60 seconds.`;
}
// host_unreachable: call terminated because the host peer became unreachable.
// Terminal is always true in this phase. A single failure entry is expected;
// zero or multiple fall back to a generic line.
if (phase === 'host_unreachable') {
const [f] = failures;
if (!f || failures.length !== 1) {
return 'Call ended — host instance became unreachable.';
}
const label = f.peerLabel || f.peerOrigin?.replace(/^https?:\/\//, '') || 'the host instance';
if (f.reason === 'peer_rejected') {
return `Call ended — this instance is no longer peered with ${label}.`;
}
return `Call ended — ${label} became unreachable.`;
}
// phase === 'start' (default + legacy)
if (!terminal) {
const labels = failures.map(labelFor).join(', ');