1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-08-09 10:22:46 +03:00

Add the call object to Call events

As explained in the comment. I've added it to the end so this should
be completely backwards compatible (although it would be much nicer
if it were the first arg, probably).
This commit is contained in:
David Baker
2023-03-24 14:09:22 +00:00
parent 254f043ab0
commit d7b75e4b9e
4 changed files with 75 additions and 47 deletions

View File

@@ -737,7 +737,7 @@ describe("Call", function () {
const dataChannel = call.createDataChannel("data_channel_label", { id: 123 });
expect(dataChannelCallback).toHaveBeenCalledWith(dataChannel);
expect(dataChannelCallback).toHaveBeenCalledWith(dataChannel, call);
expect(dataChannel.label).toBe("data_channel_label");
expect(dataChannel.id).toBe(123);
});
@@ -1604,7 +1604,7 @@ describe("Call", function () {
hasAdvancedBy += advanceBy;
expect(lengthChangedListener).toHaveBeenCalledTimes(hasAdvancedBy);
expect(lengthChangedListener).toHaveBeenCalledWith(hasAdvancedBy);
expect(lengthChangedListener).toHaveBeenCalledWith(hasAdvancedBy, call);
}
});

View File

@@ -102,7 +102,7 @@ describe("CallFeed", () => {
[CallState.Connected, true],
[CallState.Connecting, false],
])("should react to call state, when !isLocal()", (state: CallState, expected: Boolean) => {
call.emit(CallEvent.State, state);
call.emit(CallEvent.State, state, CallState.InviteSent, call.typed());
expect(feed.connected).toBe(expected);
});

View File

@@ -792,7 +792,7 @@ describe("Group Call", function () {
call.isLocalVideoMuted = jest.fn().mockReturnValue(true);
call.setLocalVideoMuted = jest.fn();
call.emit(CallEvent.State, CallState.Connected);
call.emit(CallEvent.State, CallState.Connected, CallState.InviteSent, call);
expect(call.setMicrophoneMuted).toHaveBeenCalledWith(false);
expect(call.setLocalVideoMuted).toHaveBeenCalledWith(false);
@@ -1080,7 +1080,7 @@ describe("Group Call", function () {
});
it("handles regular case", () => {
oldMockCall.emit(CallEvent.Replaced, newMockCall.typed());
oldMockCall.emit(CallEvent.Replaced, newMockCall.typed(), oldMockCall.typed());
expect(oldMockCall.hangup).toHaveBeenCalled();
expect(callChangedListener).toHaveBeenCalledWith(newCallsMap);
@@ -1091,7 +1091,7 @@ describe("Group Call", function () {
it("handles case where call is missing from the calls map", () => {
// @ts-ignore
groupCall.calls = new Map();
oldMockCall.emit(CallEvent.Replaced, newMockCall.typed());
oldMockCall.emit(CallEvent.Replaced, newMockCall.typed(), oldMockCall.typed());
expect(oldMockCall.hangup).toHaveBeenCalled();
expect(callChangedListener).toHaveBeenCalledWith(newCallsMap);

View File

@@ -296,20 +296,34 @@ export interface VoipEvent {
content: Record<string, unknown>;
}
/**
* These now all have the call object as an argument. Why? Well, to know which call a given event is
* about you have three options:
* 1. Use a closure as the callback that remembers what call it's listening to. This can be
* a pain because you need to pass the listener function again when you remove the listener,
* which might be somewhere else.
* 2. Use not-very-well-known fact that EventEmitter sets 'this' to the emitter object in the
* callback. This doesn't really play well with modern Typescript and eslint and doesn't work
* with our pattern of re-emitting events.
* 3. Pass the object in question as an argument to the callback.
*
* Now that we have group calls which have to deal with multiple call objects, this will
* become more important, and I think methods 1 and 2 are just going to cause issues.
*/
export type CallEventHandlerMap = {
[CallEvent.DataChannel]: (channel: RTCDataChannel) => void;
[CallEvent.FeedsChanged]: (feeds: CallFeed[]) => void;
[CallEvent.Replaced]: (newCall: MatrixCall) => void;
[CallEvent.Error]: (error: CallError) => void;
[CallEvent.RemoteHoldUnhold]: (onHold: boolean) => void;
[CallEvent.LocalHoldUnhold]: (onHold: boolean) => void;
[CallEvent.LengthChanged]: (length: number) => void;
[CallEvent.State]: (state: CallState, oldState?: CallState) => void;
[CallEvent.DataChannel]: (channel: RTCDataChannel, call: MatrixCall) => void;
[CallEvent.FeedsChanged]: (feeds: CallFeed[], call: MatrixCall) => void;
[CallEvent.Replaced]: (newCall: MatrixCall, oldCall: MatrixCall) => void;
[CallEvent.Error]: (error: CallError, call: MatrixCall) => void;
[CallEvent.RemoteHoldUnhold]: (onHold: boolean, call: MatrixCall) => void;
[CallEvent.LocalHoldUnhold]: (onHold: boolean, call: MatrixCall) => void;
[CallEvent.LengthChanged]: (length: number, call: MatrixCall) => void;
[CallEvent.State]: (state: CallState, oldState: CallState, call: MatrixCall) => void;
[CallEvent.Hangup]: (call: MatrixCall) => void;
[CallEvent.AssertedIdentityChanged]: () => void;
[CallEvent.AssertedIdentityChanged]: (call: MatrixCall) => void;
/* @deprecated */
[CallEvent.HoldUnhold]: (onHold: boolean) => void;
[CallEvent.SendVoipEvent]: (event: VoipEvent) => void;
[CallEvent.SendVoipEvent]: (event: VoipEvent, call: MatrixCall) => void;
};
// The key of the transceiver map (purpose + media type, separated by ':')
@@ -459,7 +473,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
*/
public createDataChannel(label: string, options: RTCDataChannelInit | undefined): RTCDataChannel {
const dataChannel = this.peerConn!.createDataChannel(label, options);
this.emit(CallEvent.DataChannel, dataChannel);
this.emit(CallEvent.DataChannel, dataChannel, this);
return dataChannel;
}
@@ -494,7 +508,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
private set state(state: CallState) {
const oldState = this._state;
this._state = state;
this.emit(CallEvent.State, state, oldState);
this.emit(CallEvent.State, state, oldState, this);
}
public get type(): CallType {
@@ -684,7 +698,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
}),
);
this.emit(CallEvent.FeedsChanged, this.feeds);
this.emit(CallEvent.FeedsChanged, this.feeds, this);
logger.info(
`Call ${this.callId} pushRemoteFeed() pushed stream (streamId=${stream.id}, active=${stream.active}, purpose=${purpose})`,
@@ -732,7 +746,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
}),
);
this.emit(CallEvent.FeedsChanged, this.feeds);
this.emit(CallEvent.FeedsChanged, this.feeds, this);
logger.info(
`Call ${this.callId} pushRemoteFeedWithoutMetadata() pushed stream (streamId=${stream.id}, active=${stream.active})`,
@@ -832,7 +846,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
`Call ${this.callId} pushLocalFeed() pushed stream (id=${callFeed.stream.id}, active=${callFeed.stream.active}, purpose=${callFeed.purpose})`,
);
this.emit(CallEvent.FeedsChanged, this.feeds);
this.emit(CallEvent.FeedsChanged, this.feeds, this);
}
/**
@@ -869,7 +883,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
}
this.feeds = [];
this.emit(CallEvent.FeedsChanged, this.feeds);
this.emit(CallEvent.FeedsChanged, this.feeds, this);
}
private deleteFeedByStream(stream: MediaStream): void {
@@ -886,7 +900,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
private deleteFeed(feed: CallFeed): void {
feed.dispose();
this.feeds.splice(this.feeds.indexOf(feed), 1);
this.emit(CallEvent.FeedsChanged, this.feeds);
this.emit(CallEvent.FeedsChanged, this.feeds, this);
}
// The typescript definitions have this type as 'any' :(
@@ -1117,7 +1131,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
}
}
this.successor = newCall;
this.emit(CallEvent.Replaced, newCall);
this.emit(CallEvent.Replaced, newCall, this);
this.hangup(CallErrorCode.Replaced, true);
}
@@ -1188,6 +1202,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.emit(
CallEvent.Error,
new CallError(CallErrorCode.NoUserMedia, "Failed to get camera access: ", <Error>error),
this,
);
}
}
@@ -1513,7 +1528,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.updateMuteStatus();
this.sendMetadataUpdate();
this.emit(CallEvent.RemoteHoldUnhold, this.remoteOnHold);
this.emit(CallEvent.RemoteHoldUnhold, this.remoteOnHold, this);
}
/**
@@ -1638,7 +1653,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
code = CallErrorCode.UnknownDevices;
message = "Unknown devices present in the room";
}
this.emit(CallEvent.Error, new CallError(code, message, <Error>error));
this.emit(CallEvent.Error, new CallError(code, message, <Error>error), this);
throw error;
}
@@ -1987,7 +2002,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
const newLocalOnHold = this.isLocalOnHold();
if (prevLocalOnHold !== newLocalOnHold) {
this.emit(CallEvent.LocalHoldUnhold, newLocalOnHold);
this.emit(CallEvent.LocalHoldUnhold, newLocalOnHold, this);
// also this one for backwards compat
this.emit(CallEvent.HoldUnhold, newLocalOnHold);
}
@@ -2018,7 +2033,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
id: content.asserted_identity.id,
displayName: content.asserted_identity.display_name,
};
this.emit(CallEvent.AssertedIdentityChanged);
this.emit(CallEvent.AssertedIdentityChanged, this);
}
public callHasEnded(): boolean {
@@ -2134,7 +2149,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
message = "Unknown devices present in the room";
}
this.emit(CallEvent.Error, new CallError(code, message, <Error>error));
this.emit(CallEvent.Error, new CallError(code, message, <Error>error), this);
this.terminate(CallParty.Local, code, false);
// no need to carry on & send the candidate queue, but we also
@@ -2158,7 +2173,11 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
private getLocalOfferFailed = (err: Error): void => {
logger.error(`Call ${this.callId} getLocalOfferFailed() running`, err);
this.emit(CallEvent.Error, new CallError(CallErrorCode.LocalOfferFailed, "Failed to get local offer!", err));
this.emit(
CallEvent.Error,
new CallError(CallErrorCode.LocalOfferFailed, "Failed to get local offer!", err),
this,
);
this.terminate(CallParty.Local, CallErrorCode.LocalOfferFailed, false);
};
@@ -2177,6 +2196,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
"Couldn't start capturing media! Is your microphone set up and " + "does this app have permission?",
err,
),
this,
);
this.terminate(CallParty.Local, CallErrorCode.NoUserMedia, false);
};
@@ -2200,7 +2220,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.callStartTime = Date.now();
this.callLengthInterval = setInterval(() => {
this.emit(CallEvent.LengthChanged, Math.round((Date.now() - this.callStartTime!) / 1000));
this.emit(CallEvent.LengthChanged, Math.round((Date.now() - this.callStartTime!) / 1000), this);
}, CALL_LENGTH_INTERVAL);
}
} else if (this.peerConn?.iceConnectionState == "failed") {
@@ -2267,7 +2287,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
};
private onDataChannel = (ev: RTCDataChannelEvent): void => {
this.emit(CallEvent.DataChannel, ev.channel);
this.emit(CallEvent.DataChannel, ev.channel, this);
};
/**
@@ -2380,13 +2400,17 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
[ToDeviceMessageId]: uuidv4(),
};
this.emit(CallEvent.SendVoipEvent, {
this.emit(
CallEvent.SendVoipEvent,
{
type: "toDevice",
eventType,
userId: this.invitee || this.getOpponentMember()?.userId,
opponentDeviceId: this.opponentDeviceId,
content,
});
},
this,
);
const userId = this.invitee || this.getOpponentMember()!.userId;
if (this.client.getUseE2eForGroupCall()) {
@@ -2415,13 +2439,17 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
});
}
} else {
this.emit(CallEvent.SendVoipEvent, {
this.emit(
CallEvent.SendVoipEvent,
{
type: "sendEvent",
eventType,
roomId: this.roomId,
content: realContent,
userId: this.invitee || this.getOpponentMember()?.userId,
});
},
this,
);
await this.client.sendEvent(this.roomId!, eventType, realContent);
}
@@ -2670,7 +2698,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
const code = CallErrorCode.SignallingFailed;
const message = "Signalling failed";
this.emit(CallEvent.Error, new CallError(code, message, <Error>error));
this.emit(CallEvent.Error, new CallError(code, message, <Error>error), this);
this.hangup(code, false);
return;