feat(call): Details card for the call-ended toast (#253)
The call-ended toast gets a Details button (and stays 10 s) that opens a card with who was in the call and the peak, connection verdict and reconnects, how long your / each person's / everyone's connection was poor (likely the server when everyone), RTT, packet loss and jitter, and your talk, mute, deafen and screenshare time, in technical wording. Deafened time is tracked by CallEmbed; the rest comes from the fork's new io.lotus.call_summary `details` (lotus.29). Settings → Calls gets "Summary After Calls" (on by default). Fixes #253 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
8784a8158c
commit
8645a55769
@@ -3,7 +3,10 @@ import { useSetAtom } from 'jotai';
|
||||
import { CallEmbed } from '../plugins/call';
|
||||
import { useCallHangupEvent } from './useCallEmbed';
|
||||
import { toastQueueAtom } from '../state/toast';
|
||||
import { describeCallEnd } from '../utils/callSummary';
|
||||
import { describeCallDetails, describeCallEnd } from '../utils/callSummary';
|
||||
import { callSummaryViewAtom } from '../state/callSummary';
|
||||
import { useSetting } from '../state/hooks/settings';
|
||||
import { settingsAtom } from '../state/settings';
|
||||
|
||||
// The fork sends io.lotus.call_summary on SFU disconnect, which normally lands
|
||||
// before Element Call's hangup echo; give a late one this long before toasting.
|
||||
@@ -16,6 +19,8 @@ const SUMMARY_GRACE_MS = 400;
|
||||
*/
|
||||
export function useCallEndedToast(embed: CallEmbed): void {
|
||||
const setToast = useSetAtom(toastQueueAtom);
|
||||
const setSummaryView = useSetAtom(callSummaryViewAtom);
|
||||
const [callSummaryToast] = useSetting(settingsAtom, 'callSummaryToast');
|
||||
const fired = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -25,14 +30,25 @@ export function useCallEndedToast(embed: CallEmbed): void {
|
||||
useCallHangupEvent(embed, () => {
|
||||
if (fired.current || !embed.joined || embed.joinedAt === undefined) return;
|
||||
fired.current = true;
|
||||
if (!callSummaryToast) return;
|
||||
const durationMs = Date.now() - embed.joinedAt;
|
||||
const deafenedMs = embed.deafenedMs();
|
||||
const roomName = embed.room.name ?? 'Voice call';
|
||||
const nameOf = (userId: string) => embed.room.getMember(userId)?.name ?? userId;
|
||||
const toast = () =>
|
||||
setToast({
|
||||
id: `call-ended-${Date.now()}`,
|
||||
displayName: 'Lotus Chat',
|
||||
body: describeCallEnd(durationMs, embed.lastSummary),
|
||||
roomName: embed.room.name ?? 'Voice call',
|
||||
roomName,
|
||||
roomId: embed.roomId,
|
||||
// [Gitea #253] The full breakdown, snapshotted at hangup.
|
||||
actionLabel: 'Details',
|
||||
onAction: () =>
|
||||
setSummaryView({
|
||||
roomName,
|
||||
sections: describeCallDetails(embed.lastSummary, durationMs, deafenedMs, nameOf),
|
||||
}),
|
||||
});
|
||||
if (embed.lastSummary) toast();
|
||||
else setTimeout(toast, SUMMARY_GRACE_MS);
|
||||
|
||||
Reference in New Issue
Block a user