feat(calls): "Call ended · 41 min · connection was good" toast (#143)
One line in the existing toast style when a call you were in ends: the duration from our own join clock, plus the fork's io.lotus.call_summary readout (fork ≥ 0.25.0-lotus.10) when it arrives — "connection was good", "3 reconnects", "connection was poor for 4 min". Nothing is stored or sent; the summary is one postMessage at hangup. Without the fork summary the toast still shows the duration. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
@@ -49,6 +49,14 @@ export interface LotusCallParticipant {
|
||||
speakingWhileMuted?: boolean;
|
||||
}
|
||||
|
||||
/** [Gitea #143] The fork's one-shot io.lotus.call_summary payload. */
|
||||
export interface LotusCallSummary {
|
||||
durationMs: number;
|
||||
reconnects: number;
|
||||
poorMs: number;
|
||||
verdict: 'good' | 'fair' | 'poor' | 'unknown';
|
||||
}
|
||||
|
||||
export class CallEmbed {
|
||||
private mx: MatrixClient;
|
||||
|
||||
@@ -60,6 +68,12 @@ export class CallEmbed {
|
||||
|
||||
public joined = false;
|
||||
|
||||
/** [Gitea #143] When the first JoinCall landed, for the hangup readout. */
|
||||
public joinedAt: number | undefined;
|
||||
|
||||
/** [Gitea #143] The fork's end-of-call summary, once it arrives. */
|
||||
public lastSummary: LotusCallSummary | undefined;
|
||||
|
||||
// C-M4: set once dispose() has run so the hangup fallback timer can tell
|
||||
// whether the embed was already torn down by the normal Close/Hangup echo.
|
||||
public disposed = false;
|
||||
@@ -390,6 +404,19 @@ export class CallEmbed {
|
||||
this.forkStateRequestListeners.forEach((l) => l());
|
||||
}),
|
||||
);
|
||||
this.disposables.push(
|
||||
this.listenAction('io.lotus.call_summary', (evt) => {
|
||||
const data = (evt.detail as { data?: Partial<LotusCallSummary> } | undefined)?.data;
|
||||
if (data && typeof data.durationMs === 'number') {
|
||||
this.lastSummary = {
|
||||
durationMs: data.durationMs,
|
||||
reconnects: data.reconnects ?? 0,
|
||||
poorMs: data.poorMs ?? 0,
|
||||
verdict: data.verdict ?? 'unknown',
|
||||
};
|
||||
}
|
||||
}),
|
||||
);
|
||||
this.disposables.push(
|
||||
this.listenAction('io.lotus.call_state', (evt) => {
|
||||
const data = (evt.detail as { data?: { participants?: unknown } } | undefined)?.data;
|
||||
@@ -537,6 +564,7 @@ export class CallEmbed {
|
||||
return;
|
||||
}
|
||||
this.joined = true;
|
||||
this.joinedAt = Date.now();
|
||||
// EC ignores io.element.device_mute before join; re-apply desired state now that EC is live
|
||||
this.control.forceState(this.initialState);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user