Make call silencing more flexible

Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
pull/21833/head
Šimon Brandner 2021-06-19 19:30:19 +02:00
parent f96c366aa4
commit ccfc7fe421
No known key found for this signature in database
GPG Key ID: 9760693FDD98A790
2 changed files with 51 additions and 5 deletions

View File

@ -99,7 +99,7 @@ const CHECK_PROTOCOLS_ATTEMPTS = 3;
// (and store the ID of their native room) // (and store the ID of their native room)
export const VIRTUAL_ROOM_EVENT_TYPE = 'im.vector.is_virtual_room'; export const VIRTUAL_ROOM_EVENT_TYPE = 'im.vector.is_virtual_room';
export enum AudioID { enum AudioID {
Ring = 'ringAudio', Ring = 'ringAudio',
Ringback = 'ringbackAudio', Ringback = 'ringbackAudio',
CallEnd = 'callendAudio', CallEnd = 'callendAudio',
@ -142,6 +142,7 @@ export enum PlaceCallType {
export enum CallHandlerEvent { export enum CallHandlerEvent {
CallsChanged = "calls_changed", CallsChanged = "calls_changed",
CallChangeRoom = "call_change_room", CallChangeRoom = "call_change_room",
SilencedCallsChanged = "silenced_calls_changed",
} }
export default class CallHandler extends EventEmitter { export default class CallHandler extends EventEmitter {
@ -164,6 +165,8 @@ export default class CallHandler extends EventEmitter {
// do the async lookup when we get new information and then store these mappings here // do the async lookup when we get new information and then store these mappings here
private assertedIdentityNativeUsers = new Map<string, string>(); private assertedIdentityNativeUsers = new Map<string, string>();
private silencedCalls = new Map<string, boolean>(); // callId -> silenced
static sharedInstance() { static sharedInstance() {
if (!window.mxCallHandler) { if (!window.mxCallHandler) {
window.mxCallHandler = new CallHandler() window.mxCallHandler = new CallHandler()
@ -224,6 +227,33 @@ export default class CallHandler extends EventEmitter {
} }
} }
public silenceCall(callId: string) {
this.silencedCalls.set(callId, true);
this.emit(CallHandlerEvent.SilencedCallsChanged, this.silencedCalls);
// Don't pause audio if we have calls which are still ringing
if (this.areAnyCallsUnsilenced()) return;
this.pause(AudioID.Ring);
}
public unSilenceCall(callId: string) {
this.silencedCalls.set(callId, false);
this.emit(CallHandlerEvent.SilencedCallsChanged, this.silencedCalls);
this.play(AudioID.Ring);
}
public isCallSilenced(callId: string): boolean {
return this.silencedCalls.get(callId);
}
/**
* Returns true if there is at least one unsilenced call
* @returns {boolean}
*/
private areAnyCallsUnsilenced(): boolean {
return [...this.silencedCalls.values()].includes(false);
}
private async checkProtocols(maxTries) { private async checkProtocols(maxTries) {
try { try {
const protocols = await MatrixClientPeg.get().getThirdpartyProtocols(); const protocols = await MatrixClientPeg.get().getThirdpartyProtocols();
@ -616,6 +646,8 @@ export default class CallHandler extends EventEmitter {
private removeCallForRoom(roomId: string) { private removeCallForRoom(roomId: string) {
console.log("Removing call for room ", roomId); console.log("Removing call for room ", roomId);
this.silencedCalls.delete(this.calls.get(roomId).callId);
this.emit(CallHandlerEvent.SilencedCallsChanged, this.silencedCalls);
this.calls.delete(roomId); this.calls.delete(roomId);
this.emit(CallHandlerEvent.CallsChanged, this.calls); this.emit(CallHandlerEvent.CallsChanged, this.calls);
} }
@ -825,6 +857,8 @@ export default class CallHandler extends EventEmitter {
console.log("Adding call for room ", mappedRoomId); console.log("Adding call for room ", mappedRoomId);
this.calls.set(mappedRoomId, call) this.calls.set(mappedRoomId, call)
this.emit(CallHandlerEvent.CallsChanged, this.calls); this.emit(CallHandlerEvent.CallsChanged, this.calls);
this.silencedCalls.set(call.callId, false);
this.emit(CallHandlerEvent.SilencedCallsChanged, this.silencedCalls);
this.setCallListeners(call); this.setCallListeners(call);
// get ready to send encrypted events in the room, so if the user does answer // get ready to send encrypted events in the room, so if the user does answer

View File

@ -21,7 +21,7 @@ import {MatrixClientPeg} from '../../../MatrixClientPeg';
import dis from '../../../dispatcher/dispatcher'; import dis from '../../../dispatcher/dispatcher';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
import { ActionPayload } from '../../../dispatcher/payloads'; import { ActionPayload } from '../../../dispatcher/payloads';
import CallHandler, { AudioID } from '../../../CallHandler'; import CallHandler, { CallHandlerEvent } from '../../../CallHandler';
import RoomAvatar from '../avatars/RoomAvatar'; import RoomAvatar from '../avatars/RoomAvatar';
import FormButton from '../elements/FormButton'; import FormButton from '../elements/FormButton';
import { CallState } from 'matrix-js-sdk/src/webrtc/call'; import { CallState } from 'matrix-js-sdk/src/webrtc/call';
@ -51,8 +51,13 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
}; };
} }
componentDidMount = () => {
CallHandler.sharedInstance().addListener(CallHandlerEvent.SilencedCallsChanged, this.onSilencedCallsChanged);
}
public componentWillUnmount() { public componentWillUnmount() {
dis.unregister(this.dispatcherRef); dis.unregister(this.dispatcherRef);
CallHandler.sharedInstance().removeListener(CallHandlerEvent.SilencedCallsChanged, this.onSilencedCallsChanged);
} }
private onAction = (payload: ActionPayload) => { private onAction = (payload: ActionPayload) => {
@ -73,6 +78,12 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
} }
}; };
private onSilencedCallsChanged = () => {
const callId = this.state.incomingCall?.callId;
if (!callId) return;
this.setState({ silenced: CallHandler.sharedInstance().isCallSilenced(callId) });
}
private onAnswerClick: React.MouseEventHandler = (e) => { private onAnswerClick: React.MouseEventHandler = (e) => {
e.stopPropagation(); e.stopPropagation();
dis.dispatch({ dis.dispatch({
@ -91,9 +102,10 @@ export default class IncomingCallBox extends React.Component<IProps, IState> {
private onSilenceClick: React.MouseEventHandler = (e) => { private onSilenceClick: React.MouseEventHandler = (e) => {
e.stopPropagation(); e.stopPropagation();
const newState = !this.state.silenced const callId = this.state.incomingCall.callId;
this.setState({silenced: newState}); this.state.silenced ?
newState ? CallHandler.sharedInstance().pause(AudioID.Ring) : CallHandler.sharedInstance().play(AudioID.Ring); CallHandler.sharedInstance().unSilenceCall(callId):
CallHandler.sharedInstance().silenceCall(callId);
} }
public render() { public render() {