mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-05 20:26:19 +02:00
Add devtools for Rtc
This commit is contained in:
parent
e83ddbc98a
commit
e668d4461e
@ -26,6 +26,7 @@ import CopyableText from "../elements/CopyableText";
|
||||
import RoomNotifications from "./devtools/RoomNotifications";
|
||||
import { Crypto } from "./devtools/Crypto";
|
||||
import SettingsField from "../elements/SettingsField.tsx";
|
||||
import MatrixRtcDebug from "./devtools/MatrixRtcDebug.tsx";
|
||||
|
||||
enum Category {
|
||||
Room,
|
||||
@ -46,6 +47,7 @@ const Tools: Record<Category, [label: TranslationKey, tool: Tool][]> = {
|
||||
[_td("devtools|view_servers_in_room"), ServersInRoom],
|
||||
[_td("devtools|notifications_debug"), RoomNotifications],
|
||||
[_td("devtools|active_widgets"), WidgetExplorer],
|
||||
[_td("devtools|matrix_rtc_debug"), MatrixRtcDebug],
|
||||
],
|
||||
[Category.Other]: [
|
||||
[_td("devtools|explore_account_data"), AccountDataExplorer],
|
||||
|
||||
170
src/components/views/dialogs/devtools/MatrixRtcDebug.tsx
Normal file
170
src/components/views/dialogs/devtools/MatrixRtcDebug.tsx
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
Copyright 2024 New Vector Ltd.
|
||||
Copyright 2023 The Matrix.org Foundation C.I.C.
|
||||
|
||||
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
import React, { type JSX, useContext, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext.tsx";
|
||||
import { _t, _td } from "../../../../languageHandler.tsx";
|
||||
import BaseTool, { DevtoolsContext, type IDevtoolsProps } from "./BaseTool.tsx";
|
||||
import { useTypedEventEmitter, useTypedEventEmitterState } from "../../../../hooks/useEventEmitter.ts";
|
||||
import { MatrixRTCSessionManagerEvents } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSessionManager.ts";
|
||||
import { CallMembership, MatrixRTCSession, MatrixRTCSessionEvent } from "matrix-js-sdk/src/matrixrtc/index.ts";
|
||||
import { Badge } from "@vector-im/compound-web";
|
||||
import { useCall } from "../../../../hooks/useCall.ts";
|
||||
import { ElementCall } from "../../../../models/Call.ts";
|
||||
|
||||
function MatrixRTCSessionInfo({
|
||||
session,
|
||||
active,
|
||||
call,
|
||||
}: {
|
||||
session: MatrixRTCSession;
|
||||
active: boolean;
|
||||
call?: ElementCall;
|
||||
}): JSX.Element {
|
||||
const memberships = useTypedEventEmitterState(
|
||||
session,
|
||||
MatrixRTCSessionEvent.MembershipsChanged,
|
||||
(_old, newMembership) => (newMembership ? newMembership : session.memberships),
|
||||
) as CallMembership[];
|
||||
const latestChange = useTypedEventEmitterState(
|
||||
session,
|
||||
MatrixRTCSessionEvent.MembershipsChanged,
|
||||
(_old, newMembership) => (newMembership ? { members: newMembership, changeTs: new Date() } : undefined),
|
||||
) as { members: CallMembership[]; changeTs: Date } | undefined;
|
||||
|
||||
// Re-check when memberships change.
|
||||
const focus = useMemo(() => session.getActiveFocus(), [memberships]);
|
||||
return (
|
||||
<section>
|
||||
<h3>
|
||||
{session.sessionDescription.application} {session.callId}{" "}
|
||||
<Badge kind={active ? "green" : "grey"}>
|
||||
{active ? _t("devtools|matrix_rtc|session_active") : _t("devtools|matrix_rtc|session_ended")}
|
||||
</Badge>
|
||||
</h3>
|
||||
{latestChange && (
|
||||
<p>{`${latestChange.members.map((m) => m.membershipID).join(", ")} ${latestChange.changeTs.toTimeString()}`}</p>
|
||||
)}
|
||||
<p>
|
||||
{_t("devtools|matrix_rtc|call_intent")}: {session.getConsensusCallIntent() ?? "mixed"}
|
||||
</p>
|
||||
{focus && (
|
||||
<details>
|
||||
<summary>{_t("devtools|matrix_rtc|active_focus")}</summary>
|
||||
<pre>{JSON.stringify(focus, undefined, 2)}</pre>
|
||||
</details>
|
||||
)}
|
||||
{memberships.length === 0 ? (
|
||||
<p>No members connected.</p>
|
||||
) : (
|
||||
<>
|
||||
<p>{_t("common|n_members", { count: memberships.length })}:</p>
|
||||
<ul>
|
||||
{memberships.map((member) => (
|
||||
<li>
|
||||
<code>
|
||||
{member.sender} {member.deviceId}
|
||||
</code>
|
||||
{member.isExpired() && "(expired)"}{" "}
|
||||
<details>
|
||||
<summary>Inspect</summary>
|
||||
<pre>{JSON.stringify(member, undefined, 2)}</pre>
|
||||
</details>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{call && (
|
||||
<>
|
||||
<h4>{_t("voip|element_call")}</h4>
|
||||
<p>
|
||||
{_t("devtools|matrix_rtc|connection_state")}: {call.connectionState}
|
||||
</p>
|
||||
{call.participants.size === 0 ? (
|
||||
<p>No call participants.</p>
|
||||
) : (
|
||||
<>
|
||||
<p>{_t("devtools|matrix_rtc|participants")}:</p>
|
||||
<ul>
|
||||
{[...call.participants.entries()].map(([roomMember, deviceIds]) => (
|
||||
<li>
|
||||
{roomMember.userId} {[...deviceIds].join(", ")}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
<details>
|
||||
<summary>Widget Params</summary>
|
||||
<pre>{JSON.stringify(call.widgetGenerationParameters, undefined, 2)}</pre>
|
||||
</details>
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
export default function MatrixRtcDebug({ onBack }: IDevtoolsProps): JSX.Element {
|
||||
const context = useContext(DevtoolsContext);
|
||||
const client = useMatrixClientContext();
|
||||
const call = useCall(context.room.roomId);
|
||||
let [sessions, setSession] = useState<{ session: MatrixRTCSession; active: boolean; start: Date }[]>([]);
|
||||
useTypedEventEmitter(
|
||||
client.matrixRTC,
|
||||
MatrixRTCSessionManagerEvents.SessionStarted,
|
||||
(roomId: string, sesh: MatrixRTCSession) => {
|
||||
if (context.room.roomId !== roomId) {
|
||||
return;
|
||||
}
|
||||
console.log(roomId, sesh);
|
||||
setSession((sessions) => [...sessions, { session: sesh, active: true, start: new Date() }]);
|
||||
},
|
||||
);
|
||||
useTypedEventEmitter(
|
||||
client.matrixRTC,
|
||||
MatrixRTCSessionManagerEvents.SessionEnded,
|
||||
(roomId: string, sesh: MatrixRTCSession) => {
|
||||
if (context.room.roomId !== roomId) {
|
||||
return;
|
||||
}
|
||||
const existingSessionData = sessions.find((s) => s.session === sesh);
|
||||
if (!existingSessionData) {
|
||||
return;
|
||||
}
|
||||
setSession((sessions) => [
|
||||
...sessions.filter((s) => s.session !== sesh),
|
||||
{ ...existingSessionData, active: false },
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const existingSession = client.matrixRTC.getActiveRoomSession(context.room);
|
||||
if (existingSession) {
|
||||
setSession([{ session: existingSession, active: true, start: new Date() }]);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<BaseTool onBack={onBack}>
|
||||
{sessions.length === 0 ? (
|
||||
<p>{_t("devtools|matrix_rtc|no_active_sessions")}</p>
|
||||
) : (
|
||||
sessions.map((s) => (
|
||||
<MatrixRTCSessionInfo
|
||||
{...s}
|
||||
call={(call as ElementCall)?.session === s.session ? (call as ElementCall) : undefined}
|
||||
key={s.start.toString()}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</BaseTool>
|
||||
);
|
||||
}
|
||||
@ -826,6 +826,16 @@
|
||||
"low_bandwidth_mode_description": "Requires compatible homeserver.",
|
||||
"main_timeline": "Main timeline",
|
||||
"manual_device_verification": "Manual device verification",
|
||||
"matrix_rtc": {
|
||||
"active_focus": "Active focus",
|
||||
"call_intent": "Call intent",
|
||||
"connection_state": "Connection state",
|
||||
"no_active_sessions": "There are no active Matrix RTC sessions",
|
||||
"participants": "Participants",
|
||||
"session_active": "Session active",
|
||||
"session_ended": "Session ended"
|
||||
},
|
||||
"matrix_rtc_debug": "Matrix RTC debug",
|
||||
"no_receipt_found": "No receipt found",
|
||||
"notification_state": "Notification state is <strong>%(notificationState)s</strong>",
|
||||
"notifications_debug": "Notifications debug",
|
||||
|
||||
@ -138,7 +138,7 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
||||
const clientUserId = MatrixClientPeg.safeGet().getSafeUserId();
|
||||
// For the legacy membership type
|
||||
this.allowedCapabilities.add(
|
||||
WidgetEventCapability.forStateEvent(EventDirection.Send, "org.matrix.msc3401.call.member", clientUserId)
|
||||
WidgetEventCapability.forStateEvent(EventDirection.Send, EventType.GroupCallMemberPrefix, clientUserId)
|
||||
.raw,
|
||||
);
|
||||
const clientDeviceId = MatrixClientPeg.safeGet().getDeviceId();
|
||||
@ -148,14 +148,14 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
||||
this.allowedCapabilities.add(
|
||||
WidgetEventCapability.forStateEvent(
|
||||
EventDirection.Send,
|
||||
"org.matrix.msc3401.call.member",
|
||||
EventType.GroupCallMemberPrefix,
|
||||
`_${clientUserId}_${clientDeviceId}`,
|
||||
).raw,
|
||||
);
|
||||
this.allowedCapabilities.add(
|
||||
WidgetEventCapability.forStateEvent(
|
||||
EventDirection.Send,
|
||||
"org.matrix.msc3401.call.member",
|
||||
EventType.GroupCallMemberPrefix,
|
||||
`_${clientUserId}_${clientDeviceId}_m.call`,
|
||||
).raw,
|
||||
);
|
||||
@ -163,20 +163,20 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
||||
this.allowedCapabilities.add(
|
||||
WidgetEventCapability.forStateEvent(
|
||||
EventDirection.Send,
|
||||
"org.matrix.msc3401.call.member",
|
||||
EventType.GroupCallMemberPrefix,
|
||||
`${clientUserId}_${clientDeviceId}`,
|
||||
).raw,
|
||||
);
|
||||
this.allowedCapabilities.add(
|
||||
WidgetEventCapability.forStateEvent(
|
||||
EventDirection.Send,
|
||||
"org.matrix.msc3401.call.member",
|
||||
EventType.GroupCallMemberPrefix,
|
||||
`${clientUserId}_${clientDeviceId}_m.call`,
|
||||
).raw,
|
||||
);
|
||||
}
|
||||
this.allowedCapabilities.add(
|
||||
WidgetEventCapability.forStateEvent(EventDirection.Receive, "org.matrix.msc3401.call.member").raw,
|
||||
WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.GroupCallMemberPrefix).raw,
|
||||
);
|
||||
// for determining auth rules specific to the room version
|
||||
this.allowedCapabilities.add(
|
||||
@ -193,6 +193,8 @@ export class StopGapWidgetDriver extends WidgetDriver {
|
||||
// MSC4310: Add dev and final event to ease future transition,
|
||||
EventType.RTCDecline,
|
||||
"m.rtc.decline",
|
||||
// For sticky events
|
||||
EventType.GroupCallMemberPrefix,
|
||||
];
|
||||
for (const eventType of [...sendRoomEvents, ...sendRecvRoomEvents])
|
||||
this.allowedCapabilities.add(WidgetEventCapability.forRoomEvent(EventDirection.Send, eventType).raw);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user