From 37059a3fcd95ce6a70b5e02c51280bae9c8dfb4b Mon Sep 17 00:00:00 2001
From: David Baker <dave@matrix.org>
Date: Mon, 23 Nov 2020 16:20:15 +0000
Subject: [PATCH 1/2] Move call listener out of MatrixChat

and into callhandler
---
 src/CallHandler.tsx                      | 24 +++++++++++++++++++++++-
 src/Lifecycle.ts                         |  3 +++
 src/components/structures/MatrixChat.tsx | 12 ------------
 3 files changed, 26 insertions(+), 13 deletions(-)

diff --git a/src/CallHandler.tsx b/src/CallHandler.tsx
index 710eded2cd..3be203ab98 100644
--- a/src/CallHandler.tsx
+++ b/src/CallHandler.tsx
@@ -79,6 +79,7 @@ import { ElementWidgetActions } from "./stores/widgets/ElementWidgetActions";
 import { MatrixCall, CallErrorCode, CallState, CallEvent, CallParty, CallType } from "matrix-js-sdk/src/webrtc/call";
 import Analytics from './Analytics';
 import CountlyAnalytics from "./CountlyAnalytics";
+import {UIFeature} from "./settings/UIFeature";
 
 enum AudioID {
     Ring = 'ringAudio',
@@ -124,7 +125,7 @@ export default class CallHandler {
         return window.mxCallHandler;
     }
 
-    constructor() {
+    start() {
         dis.register(this.onAction);
         // add empty handlers for media actions, otherwise the media keys
         // end up causing the audio elements with our ring/ringback etc
@@ -137,6 +138,27 @@ export default class CallHandler {
             navigator.mediaSession.setActionHandler('previoustrack', function() {});
             navigator.mediaSession.setActionHandler('nexttrack', function() {});
         }
+
+        if (SettingsStore.getValue(UIFeature.Voip)) {
+            MatrixClientPeg.get().on('Call.incoming', this.onCallIncoming);
+        }
+    }
+
+    stop() {
+        const cli = MatrixClientPeg.get();
+        if (cli) {
+            cli.removeListener('Call.incoming', this.onCallIncoming);
+        }
+    }
+
+    private onCallIncoming = (call) => {
+        // we dispatch this synchronously to make sure that the event
+        // handlers on the call are set up immediately (so that if
+        // we get an immediate hangup, we don't get a stuck call)
+        dis.dispatch({
+            action: 'incoming_call',
+            call: call,
+        }, true);
     }
 
     getCallForRoom(roomId: string): MatrixCall {
diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts
index 7469624f5c..84ecda9de6 100644
--- a/src/Lifecycle.ts
+++ b/src/Lifecycle.ts
@@ -48,6 +48,7 @@ import {Jitsi} from "./widgets/Jitsi";
 import {SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY} from "./BasePlatform";
 import ThreepidInviteStore from "./stores/ThreepidInviteStore";
 import CountlyAnalytics from "./CountlyAnalytics";
+import CallHandler from './CallHandler';
 
 const HOMESERVER_URL_KEY = "mx_hs_url";
 const ID_SERVER_URL_KEY = "mx_is_url";
@@ -665,6 +666,7 @@ async function startMatrixClient(startSyncing = true): Promise<void> {
     DMRoomMap.makeShared().start();
     IntegrationManagers.sharedInstance().startWatching();
     ActiveWidgetStore.start();
+    CallHandler.sharedInstance().start();
 
     // Start Mjolnir even though we haven't checked the feature flag yet. Starting
     // the thing just wastes CPU cycles, but should result in no actual functionality
@@ -760,6 +762,7 @@ async function clearStorage(opts?: { deleteEverything?: boolean }): Promise<void
  */
 export function stopMatrixClient(unsetClient = true): void {
     Notifier.stop();
+    CallHandler.sharedInstance().start();
     UserActivity.sharedInstance().stop();
     TypingStore.sharedInstance().reset();
     Presence.stop();
diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx
index 114347196a..9fede15aa6 100644
--- a/src/components/structures/MatrixChat.tsx
+++ b/src/components/structures/MatrixChat.tsx
@@ -1353,18 +1353,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
             });
         });
 
-        if (SettingsStore.getValue(UIFeature.Voip)) {
-            cli.on('Call.incoming', function(call) {
-                // we dispatch this synchronously to make sure that the event
-                // handlers on the call are set up immediately (so that if
-                // we get an immediate hangup, we don't get a stuck call)
-                dis.dispatch({
-                    action: 'incoming_call',
-                    call: call,
-                }, true);
-            });
-        }
-
         cli.on('Session.logged_out', function(errObj) {
             if (Lifecycle.isLoggingOut()) return;
 

From bc2fd7cf05ac3c1b32d9068dc834579158f23ac6 Mon Sep 17 00:00:00 2001
From: David Baker <dave@matrix.org>
Date: Mon, 23 Nov 2020 16:41:57 +0000
Subject: [PATCH 2/2] Start is not stop

---
 src/Lifecycle.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts
index 84ecda9de6..8451568dd1 100644
--- a/src/Lifecycle.ts
+++ b/src/Lifecycle.ts
@@ -762,7 +762,7 @@ async function clearStorage(opts?: { deleteEverything?: boolean }): Promise<void
  */
 export function stopMatrixClient(unsetClient = true): void {
     Notifier.stop();
-    CallHandler.sharedInstance().start();
+    CallHandler.sharedInstance().stop();
     UserActivity.sharedInstance().stop();
     TypingStore.sharedInstance().reset();
     Presence.stop();