Merge branch 'main' into audio-observability

This commit is contained in:
Robin Townsend
2023-04-05 12:50:38 -04:00
29 changed files with 1014 additions and 184 deletions

View File

@@ -28,10 +28,20 @@ import ReactJson, { CollapsedFieldProps } from "react-json-view";
import mermaid from "mermaid";
import { Item } from "@react-stately/collections";
import { MatrixEvent, IContent } from "matrix-js-sdk/src/models/event";
import { GroupCall } from "matrix-js-sdk/src/webrtc/groupCall";
import {
GroupCall,
GroupCallError,
GroupCallEvent,
} from "matrix-js-sdk/src/webrtc/groupCall";
import { ClientEvent, MatrixClient } from "matrix-js-sdk/src/client";
import { RoomStateEvent } from "matrix-js-sdk/src/models/room-state";
import { CallEvent, VoipEvent } from "matrix-js-sdk/src/webrtc/call";
import {
CallEvent,
CallState,
CallError,
MatrixCall,
VoipEvent,
} from "matrix-js-sdk/src/webrtc/call";
import styles from "./GroupCallInspector.module.css";
import { SelectInput } from "../input/SelectInput";
@@ -388,26 +398,49 @@ function useGroupCallState(
function onReceivedVoipEvent(event: MatrixEvent) {
dispatch({ type: ClientEvent.ReceivedVoipEvent, event });
otelGroupCallMembership?.onReceivedVoipEvent(event);
}
function onSendVoipEvent(event: VoipEvent) {
function onSendVoipEvent(event: VoipEvent, call: MatrixCall) {
dispatch({ type: CallEvent.SendVoipEvent, rawEvent: event });
otelGroupCallMembership?.onSendEvent(event);
otelGroupCallMembership?.onSendEvent(call, event);
}
function onCallStateChange(
newState: CallState,
_: CallState,
call: MatrixCall
) {
otelGroupCallMembership?.onCallStateChange(call, newState);
}
function onCallError(error: CallError, call: MatrixCall) {
otelGroupCallMembership.onCallError(error, call);
}
function onGroupCallError(error: GroupCallError) {
otelGroupCallMembership.onGroupCallError(error);
}
function onUndecryptableToDevice(event: MatrixEvent) {
dispatch({ type: ClientEvent.ReceivedVoipEvent, event });
Sentry.captureMessage("Undecryptable to-device Event");
// probably unnecessary if it's now captured via otel?
PosthogAnalytics.instance.eventUndecryptableToDevice.track(
groupCall.groupCallId
);
otelGroupCallMembership.onUndecryptableToDevice(event);
}
client.on(RoomStateEvent.Events, onUpdateRoomState);
//groupCall.on("calls_changed", onCallsChanged);
groupCall.on(CallEvent.SendVoipEvent, onSendVoipEvent);
groupCall.on(CallEvent.State, onCallStateChange);
groupCall.on(CallEvent.Error, onCallError);
groupCall.on(GroupCallEvent.Error, onGroupCallError);
//client.on("state", onCallsChanged);
//client.on("hangup", onCallHangup);
client.on(ClientEvent.ReceivedVoipEvent, onReceivedVoipEvent);
@@ -417,8 +450,10 @@ function useGroupCallState(
return () => {
client.removeListener(RoomStateEvent.Events, onUpdateRoomState);
//groupCall.removeListener("calls_changed", onCallsChanged);
groupCall.removeListener(CallEvent.SendVoipEvent, onSendVoipEvent);
groupCall.removeListener(CallEvent.State, onCallStateChange);
groupCall.removeListener(CallEvent.Error, onCallError);
groupCall.removeListener(GroupCallEvent.Error, onGroupCallError);
//client.removeListener("state", onCallsChanged);
//client.removeListener("hangup", onCallHangup);
client.removeListener(ClientEvent.ReceivedVoipEvent, onReceivedVoipEvent);

View File

@@ -27,6 +27,7 @@ import { useUrlParams } from "../UrlParams";
import { MediaHandlerProvider } from "../settings/useMediaHandler";
import { useRegisterPasswordlessUser } from "../auth/useRegisterPasswordlessUser";
import { translatedError } from "../TranslatedError";
import { useOptInAnalytics } from "../settings/useSetting";
export const RoomPage: FC = () => {
const { t } = useTranslation();
@@ -46,9 +47,15 @@ export const RoomPage: FC = () => {
const roomIdOrAlias = roomId ?? roomAlias;
if (!roomIdOrAlias) throw translatedError("No room specified", t);
const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
const { registerPasswordlessUser } = useRegisterPasswordlessUser();
const [isRegistering, setIsRegistering] = useState(false);
useEffect(() => {
// During the beta, opt into analytics by default
if (optInAnalytics === null) setOptInAnalytics(true);
}, [optInAnalytics, setOptInAnalytics]);
useEffect(() => {
// If we've finished loading, are not already authed and we've been given a display name as
// a URL param, automatically register a passwordless user

View File

@@ -22,12 +22,19 @@ import {
GroupCallErrorCode,
GroupCallUnknownDeviceError,
GroupCallError,
GroupCallStatsReportEvent,
GroupCallStatsReport,
} from "matrix-js-sdk/src/webrtc/groupCall";
import { CallFeed, CallFeedEvent } from "matrix-js-sdk/src/webrtc/callFeed";
import { RoomMember } from "matrix-js-sdk/src/models/room-member";
import { useTranslation } from "react-i18next";
import { IWidgetApiRequest } from "matrix-widget-api";
import { MatrixClient } from "matrix-js-sdk";
import {
ByteSentStatsReport,
ConnectionStatsReport,
SummaryStatsReport,
} from "matrix-js-sdk/src/webrtc/stats/statsReport";
import { usePageUnload } from "./usePageUnload";
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
@@ -173,6 +180,8 @@ export function useGroupCall(
});
if (groupCallOTelMembershipGroupCallId !== groupCall.groupCallId) {
if (groupCallOTelMembership) groupCallOTelMembership.dispose();
// If the user disables analytics, this will stay around until they leave the call
// so analytics will be disabled once they leave.
if (ElementCallOpenTelemetry.instance) {
@@ -200,6 +209,11 @@ export function useGroupCall(
[]
);
const leaveCall = useCallback(() => {
groupCallOTelMembership?.onLeaveCall();
groupCall.leave();
}, [groupCall]);
useEffect(() => {
// disable the media action keys, otherwise audio elements get paused when
// the user presses media keys or unplugs headphones, etc.
@@ -214,7 +228,7 @@ export function useGroupCall(
];
for (const mediaAction of mediaActions) {
navigator.mediaSession.setActionHandler(
navigator.mediaSession?.setActionHandler(
mediaAction,
doNothingMediaActionCallback
);
@@ -222,7 +236,7 @@ export function useGroupCall(
return () => {
for (const mediaAction of mediaActions) {
navigator.mediaSession.setActionHandler(mediaAction, null);
navigator.mediaSession?.setActionHandler(mediaAction, null);
}
};
}, [doNothingMediaActionCallback]);
@@ -330,6 +344,24 @@ export function useGroupCall(
}
}
function onConnectionStatsReport(
report: GroupCallStatsReport<ConnectionStatsReport>
): void {
groupCallOTelMembership?.onConnectionStatsReport(report);
}
function onByteSentStatsReport(
report: GroupCallStatsReport<ByteSentStatsReport>
): void {
groupCallOTelMembership?.onByteSentStatsReport(report);
}
function onSummaryStatsReport(
report: GroupCallStatsReport<SummaryStatsReport>
): void {
groupCallOTelMembership?.onSummaryStatsReport(report);
}
groupCall.on(GroupCallEvent.GroupCallStateChanged, onGroupCallStateChanged);
groupCall.on(GroupCallEvent.UserMediaFeedsChanged, onUserMediaFeedsChanged);
groupCall.on(
@@ -346,6 +378,18 @@ export function useGroupCall(
groupCall.on(GroupCallEvent.ParticipantsChanged, onParticipantsChanged);
groupCall.on(GroupCallEvent.Error, onError);
groupCall.on(
GroupCallStatsReportEvent.ConnectionStats,
onConnectionStatsReport
);
groupCall.on(
GroupCallStatsReportEvent.ByteSentStats,
onByteSentStatsReport
);
groupCall.on(GroupCallStatsReportEvent.SummaryStats, onSummaryStatsReport);
updateState({
error: null,
state: groupCall.state,
@@ -392,12 +436,24 @@ export function useGroupCall(
onParticipantsChanged
);
groupCall.removeListener(GroupCallEvent.Error, onError);
groupCall.leave();
groupCall.removeListener(
GroupCallStatsReportEvent.ConnectionStats,
onConnectionStatsReport
);
groupCall.removeListener(
GroupCallStatsReportEvent.ByteSentStats,
onByteSentStatsReport
);
groupCall.removeListener(
GroupCallStatsReportEvent.SummaryStats,
onSummaryStatsReport
);
leaveCall();
};
}, [groupCall, updateState]);
}, [groupCall, updateState, leaveCall]);
usePageUnload(() => {
groupCall.leave();
leaveCall();
});
const initLocalCallFeed = useCallback(
@@ -416,19 +472,16 @@ export function useGroupCall(
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
PosthogAnalytics.instance.eventCallStarted.track(groupCall.groupCallId);
// This must be called before we start trying to join the call, as we need to
// have started tracking by the time calls start getting created.
groupCallOTelMembership?.onJoinCall();
groupCall.enter().catch((error) => {
console.error(error);
updateState({ error });
});
groupCallOTelMembership?.onJoinCall();
}, [groupCall, updateState]);
const leave = useCallback(() => {
groupCallOTelMembership?.onLeaveCall();
groupCall.leave();
}, [groupCall]);
const toggleLocalVideoMuted = useCallback(() => {
const toggleToMute = !groupCall.isLocalVideoMuted();
groupCall.setLocalVideoMuted(toggleToMute);
@@ -561,7 +614,7 @@ export function useGroupCall(
error,
initLocalCallFeed,
enter,
leave,
leave: leaveCall,
toggleLocalVideoMuted,
toggleMicrophoneMuted,
toggleScreensharing,