From 2ea239d1923170ef9d226eeae99dcfc12432dc30 Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Tue, 12 Nov 2019 11:45:28 +0000
Subject: [PATCH] Replace rest of defer usages using small shim. Add homebrew
 promise utils

(cherry picked from commit 6850c147393ba7be8b98d97dfc8d7244fa503461)
---
 src/Modal.js                            |  3 +-
 src/components/structures/MatrixChat.js |  5 +--
 src/utils/MultiInviter.js               |  3 +-
 src/utils/promise.js                    | 46 +++++++++++++++++++++++++
 4 files changed, 53 insertions(+), 4 deletions(-)
 create mode 100644 src/utils/promise.js

diff --git a/src/Modal.js b/src/Modal.js
index 26c9da8bbb..cb19731f01 100644
--- a/src/Modal.js
+++ b/src/Modal.js
@@ -24,6 +24,7 @@ import sdk from './index';
 import dis from './dispatcher';
 import { _t } from './languageHandler';
 import Promise from "bluebird";
+import {defer} from "./utils/promise";
 
 const DIALOG_CONTAINER_ID = "mx_Dialog_Container";
 const STATIC_DIALOG_CONTAINER_ID = "mx_Dialog_StaticContainer";
@@ -202,7 +203,7 @@ class ModalManager {
     }
 
     _getCloseFn(modal, props) {
-        const deferred = Promise.defer();
+        const deferred = defer();
         return [(...args) => {
             deferred.resolve(args);
             if (props && props.onFinished) props.onFinished.apply(null, args);
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index da67416400..d12eba88f7 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -60,6 +60,7 @@ import AutoDiscoveryUtils from "../../utils/AutoDiscoveryUtils";
 import DMRoomMap from '../../utils/DMRoomMap';
 import { countRoomsWithNotif } from '../../RoomNotifs';
 import { setTheme } from "../../theme";
+import {defer} from "../../utils/promise";
 
 // Disable warnings for now: we use deprecated bluebird functions
 // and need to migrate, but they spam the console with warnings.
@@ -236,7 +237,7 @@ export default createReactClass({
 
         // Used by _viewRoom before getting state from sync
         this.firstSyncComplete = false;
-        this.firstSyncPromise = Promise.defer();
+        this.firstSyncPromise = defer();
 
         if (this.props.config.sync_timeline_limit) {
             MatrixClientPeg.opts.initialSyncLimit = this.props.config.sync_timeline_limit;
@@ -1261,7 +1262,7 @@ export default createReactClass({
         // since we're about to start the client and therefore about
         // to do the first sync
         this.firstSyncComplete = false;
-        this.firstSyncPromise = Promise.defer();
+        this.firstSyncPromise = defer();
         const cli = MatrixClientPeg.get();
         const IncomingSasDialog = sdk.getComponent('views.dialogs.IncomingSasDialog');
 
diff --git a/src/utils/MultiInviter.js b/src/utils/MultiInviter.js
index e8995b46d7..de5c2e7610 100644
--- a/src/utils/MultiInviter.js
+++ b/src/utils/MultiInviter.js
@@ -24,6 +24,7 @@ import {_t} from "../languageHandler";
 import sdk from "../index";
 import Modal from "../Modal";
 import SettingsStore from "../settings/SettingsStore";
+import {defer} from "./promise";
 
 /**
  * Invites multiple addresses to a room or group, handling rate limiting from the server
@@ -71,7 +72,7 @@ export default class MultiInviter {
                 };
             }
         }
-        this.deferred = Promise.defer();
+        this.deferred = defer();
         this._inviteMore(0);
 
         return this.deferred.promise;
diff --git a/src/utils/promise.js b/src/utils/promise.js
new file mode 100644
index 0000000000..dd10f7fdd7
--- /dev/null
+++ b/src/utils/promise.js
@@ -0,0 +1,46 @@
+/*
+Copyright 2019 The Matrix.org Foundation C.I.C.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// @flow
+
+// Returns a promise which resolves with a given value after the given number of ms
+export const sleep = (ms: number, value: any): Promise => new Promise((resolve => { setTimeout(resolve, ms, value); }));
+
+// Returns a promise which resolves when the input promise resolves with its value
+// or when the timeout of ms is reached with the value of given timeoutValue
+export async function timeout(promise: Promise, timeoutValue: any, ms: number): Promise {
+    const timeoutPromise = new Promise((resolve) => {
+        const timeoutId = setTimeout(resolve, ms, timeoutValue);
+        promise.then(() => {
+            clearTimeout(timeoutId);
+        });
+    });
+
+    return Promise.race([promise, timeoutPromise]);
+}
+
+// Returns a Deferred
+export function defer(): {resolve: () => {}, reject: () => {}, promise: Promise} {
+    let resolve;
+    let reject;
+
+    const promise = new Promise((_resolve, _reject) => {
+        resolve = _resolve;
+        reject = _reject;
+    });
+
+    return {resolve, reject, promise};
+}