mirror of
https://github.com/vector-im/element-web.git
synced 2024-11-17 05:55:00 +08:00
Merge pull request #3612 from matrix-org/t3chguy/remove_bluebird_1
Remove Bluebird: phase 1
This commit is contained in:
commit
58d15acf19
@ -59,40 +59,38 @@ export class UploadCanceledError extends Error {}
|
||||
* and a thumbnail key.
|
||||
*/
|
||||
function createThumbnail(element, inputWidth, inputHeight, mimeType) {
|
||||
const deferred = Promise.defer();
|
||||
return new Promise((resolve) => {
|
||||
let targetWidth = inputWidth;
|
||||
let targetHeight = inputHeight;
|
||||
if (targetHeight > MAX_HEIGHT) {
|
||||
targetWidth = Math.floor(targetWidth * (MAX_HEIGHT / targetHeight));
|
||||
targetHeight = MAX_HEIGHT;
|
||||
}
|
||||
if (targetWidth > MAX_WIDTH) {
|
||||
targetHeight = Math.floor(targetHeight * (MAX_WIDTH / targetWidth));
|
||||
targetWidth = MAX_WIDTH;
|
||||
}
|
||||
|
||||
let targetWidth = inputWidth;
|
||||
let targetHeight = inputHeight;
|
||||
if (targetHeight > MAX_HEIGHT) {
|
||||
targetWidth = Math.floor(targetWidth * (MAX_HEIGHT / targetHeight));
|
||||
targetHeight = MAX_HEIGHT;
|
||||
}
|
||||
if (targetWidth > MAX_WIDTH) {
|
||||
targetHeight = Math.floor(targetHeight * (MAX_WIDTH / targetWidth));
|
||||
targetWidth = MAX_WIDTH;
|
||||
}
|
||||
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = targetWidth;
|
||||
canvas.height = targetHeight;
|
||||
canvas.getContext("2d").drawImage(element, 0, 0, targetWidth, targetHeight);
|
||||
canvas.toBlob(function(thumbnail) {
|
||||
deferred.resolve({
|
||||
info: {
|
||||
thumbnail_info: {
|
||||
w: targetWidth,
|
||||
h: targetHeight,
|
||||
mimetype: thumbnail.type,
|
||||
size: thumbnail.size,
|
||||
const canvas = document.createElement("canvas");
|
||||
canvas.width = targetWidth;
|
||||
canvas.height = targetHeight;
|
||||
canvas.getContext("2d").drawImage(element, 0, 0, targetWidth, targetHeight);
|
||||
canvas.toBlob(function(thumbnail) {
|
||||
resolve({
|
||||
info: {
|
||||
thumbnail_info: {
|
||||
w: targetWidth,
|
||||
h: targetHeight,
|
||||
mimetype: thumbnail.type,
|
||||
size: thumbnail.size,
|
||||
},
|
||||
w: inputWidth,
|
||||
h: inputHeight,
|
||||
},
|
||||
w: inputWidth,
|
||||
h: inputHeight,
|
||||
},
|
||||
thumbnail: thumbnail,
|
||||
});
|
||||
}, mimeType);
|
||||
|
||||
return deferred.promise;
|
||||
thumbnail: thumbnail,
|
||||
});
|
||||
}, mimeType);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -179,30 +177,29 @@ function infoForImageFile(matrixClient, roomId, imageFile) {
|
||||
* @return {Promise} A promise that resolves with the video image element.
|
||||
*/
|
||||
function loadVideoElement(videoFile) {
|
||||
const deferred = Promise.defer();
|
||||
return new Promise((resolve, reject) => {
|
||||
// Load the file into an html element
|
||||
const video = document.createElement("video");
|
||||
|
||||
// Load the file into an html element
|
||||
const video = document.createElement("video");
|
||||
const reader = new FileReader();
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
video.src = e.target.result;
|
||||
reader.onload = function(e) {
|
||||
video.src = e.target.result;
|
||||
|
||||
// Once ready, returns its size
|
||||
// Wait until we have enough data to thumbnail the first frame.
|
||||
video.onloadeddata = function() {
|
||||
deferred.resolve(video);
|
||||
// Once ready, returns its size
|
||||
// Wait until we have enough data to thumbnail the first frame.
|
||||
video.onloadeddata = function() {
|
||||
resolve(video);
|
||||
};
|
||||
video.onerror = function(e) {
|
||||
reject(e);
|
||||
};
|
||||
};
|
||||
video.onerror = function(e) {
|
||||
deferred.reject(e);
|
||||
reader.onerror = function(e) {
|
||||
reject(e);
|
||||
};
|
||||
};
|
||||
reader.onerror = function(e) {
|
||||
deferred.reject(e);
|
||||
};
|
||||
reader.readAsDataURL(videoFile);
|
||||
|
||||
return deferred.promise;
|
||||
reader.readAsDataURL(videoFile);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,16 +233,16 @@ function infoForVideoFile(matrixClient, roomId, videoFile) {
|
||||
* is read.
|
||||
*/
|
||||
function readFileAsArrayBuffer(file) {
|
||||
const deferred = Promise.defer();
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
deferred.resolve(e.target.result);
|
||||
};
|
||||
reader.onerror = function(e) {
|
||||
deferred.reject(e);
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
return deferred.promise;
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
resolve(e.target.result);
|
||||
};
|
||||
reader.onerror = function(e) {
|
||||
reject(e);
|
||||
};
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -461,33 +458,34 @@ export default class ContentMessages {
|
||||
content.info.mimetype = file.type;
|
||||
}
|
||||
|
||||
const def = Promise.defer();
|
||||
if (file.type.indexOf('image/') == 0) {
|
||||
content.msgtype = 'm.image';
|
||||
infoForImageFile(matrixClient, roomId, file).then((imageInfo)=>{
|
||||
extend(content.info, imageInfo);
|
||||
def.resolve();
|
||||
}, (error)=>{
|
||||
console.error(error);
|
||||
const prom = new Promise((resolve) => {
|
||||
if (file.type.indexOf('image/') == 0) {
|
||||
content.msgtype = 'm.image';
|
||||
infoForImageFile(matrixClient, roomId, file).then((imageInfo)=>{
|
||||
extend(content.info, imageInfo);
|
||||
resolve();
|
||||
}, (error)=>{
|
||||
console.error(error);
|
||||
content.msgtype = 'm.file';
|
||||
resolve();
|
||||
});
|
||||
} else if (file.type.indexOf('audio/') == 0) {
|
||||
content.msgtype = 'm.audio';
|
||||
resolve();
|
||||
} else if (file.type.indexOf('video/') == 0) {
|
||||
content.msgtype = 'm.video';
|
||||
infoForVideoFile(matrixClient, roomId, file).then((videoInfo)=>{
|
||||
extend(content.info, videoInfo);
|
||||
resolve();
|
||||
}, (error)=>{
|
||||
content.msgtype = 'm.file';
|
||||
resolve();
|
||||
});
|
||||
} else {
|
||||
content.msgtype = 'm.file';
|
||||
def.resolve();
|
||||
});
|
||||
} else if (file.type.indexOf('audio/') == 0) {
|
||||
content.msgtype = 'm.audio';
|
||||
def.resolve();
|
||||
} else if (file.type.indexOf('video/') == 0) {
|
||||
content.msgtype = 'm.video';
|
||||
infoForVideoFile(matrixClient, roomId, file).then((videoInfo)=>{
|
||||
extend(content.info, videoInfo);
|
||||
def.resolve();
|
||||
}, (error)=>{
|
||||
content.msgtype = 'm.file';
|
||||
def.resolve();
|
||||
});
|
||||
} else {
|
||||
content.msgtype = 'm.file';
|
||||
def.resolve();
|
||||
}
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
|
||||
const upload = {
|
||||
fileName: file.name || 'Attachment',
|
||||
@ -509,7 +507,7 @@ export default class ContentMessages {
|
||||
dis.dispatch({action: 'upload_progress', upload: upload});
|
||||
}
|
||||
|
||||
return def.promise.then(function() {
|
||||
return prom.then(function() {
|
||||
// XXX: upload.promise must be the promise that
|
||||
// is returned by uploadFile as it has an abort()
|
||||
// method hacked onto it.
|
||||
|
@ -313,18 +313,14 @@ async function _restoreFromLocalStorage(opts) {
|
||||
function _handleLoadSessionFailure(e) {
|
||||
console.error("Unable to load session", e);
|
||||
|
||||
const def = Promise.defer();
|
||||
const SessionRestoreErrorDialog =
|
||||
sdk.getComponent('views.dialogs.SessionRestoreErrorDialog');
|
||||
|
||||
Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
|
||||
const modal = Modal.createTrackedDialog('Session Restore Error', '', SessionRestoreErrorDialog, {
|
||||
error: e.message,
|
||||
onFinished: (success) => {
|
||||
def.resolve(success);
|
||||
},
|
||||
});
|
||||
|
||||
return def.promise.then((success) => {
|
||||
return modal.finished.then(([success]) => {
|
||||
if (success) {
|
||||
// user clicked continue.
|
||||
_clearStorage();
|
||||
|
@ -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);
|
||||
|
@ -38,6 +38,7 @@ import FlairStore from '../../stores/FlairStore';
|
||||
import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
||||
import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Permalinks";
|
||||
import {Group} from "matrix-js-sdk";
|
||||
import {sleep} from "../../utils/promise";
|
||||
|
||||
const LONG_DESC_PLACEHOLDER = _td(
|
||||
`<h1>HTML for your community's page</h1>
|
||||
@ -692,7 +693,7 @@ export default createReactClass({
|
||||
|
||||
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
await Promise.delay(500);
|
||||
await sleep(500);
|
||||
|
||||
GroupStore.acceptGroupInvite(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
@ -711,7 +712,7 @@ export default createReactClass({
|
||||
|
||||
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
await Promise.delay(500);
|
||||
await sleep(500);
|
||||
|
||||
GroupStore.leaveGroup(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
@ -735,7 +736,7 @@ export default createReactClass({
|
||||
|
||||
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
await Promise.delay(500);
|
||||
await sleep(500);
|
||||
|
||||
GroupStore.joinGroup(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
@ -787,7 +788,7 @@ export default createReactClass({
|
||||
|
||||
// Wait 500ms to prevent flashing. Do this before sending a request otherwise we risk the
|
||||
// spinner disappearing after we have fetched new group data.
|
||||
await Promise.delay(500);
|
||||
await sleep(500);
|
||||
|
||||
GroupStore.leaveGroup(this.props.groupId).then(() => {
|
||||
// don't reset membershipBusy here: wait for the membership change to come down the sync
|
||||
|
@ -61,6 +61,7 @@ import DMRoomMap from '../../utils/DMRoomMap';
|
||||
import { countRoomsWithNotif } from '../../RoomNotifs';
|
||||
import { setTheme } from "../../theme";
|
||||
import { storeRoomAliasInCache } from '../../RoomAliasCache';
|
||||
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.
|
||||
@ -237,7 +238,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;
|
||||
@ -1267,7 +1268,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');
|
||||
|
||||
|
@ -17,7 +17,6 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import Promise from 'bluebird';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import createReactClass from 'create-react-class';
|
||||
@ -32,6 +31,7 @@ import * as RoomNotifs from '../../../RoomNotifs';
|
||||
import Modal from '../../../Modal';
|
||||
import RoomListActions from '../../../actions/RoomListActions';
|
||||
import RoomViewStore from '../../../stores/RoomViewStore';
|
||||
import {sleep} from "../../../utils/promise";
|
||||
|
||||
module.exports = createReactClass({
|
||||
displayName: 'RoomTileContextMenu',
|
||||
@ -62,7 +62,7 @@ module.exports = createReactClass({
|
||||
|
||||
_toggleTag: function(tagNameOn, tagNameOff) {
|
||||
if (!MatrixClientPeg.get().isGuest()) {
|
||||
Promise.delay(500).then(() => {
|
||||
sleep(500).then(() => {
|
||||
dis.dispatch(RoomListActions.tagRoom(
|
||||
MatrixClientPeg.get(),
|
||||
this.props.room,
|
||||
@ -119,7 +119,7 @@ module.exports = createReactClass({
|
||||
|
||||
Rooms.guessAndSetDMRoom(
|
||||
this.props.room, newIsDirectMessage,
|
||||
).delay(500).finally(() => {
|
||||
).then(sleep(500)).finally(() => {
|
||||
// Close the context menu
|
||||
if (this.props.onFinished) {
|
||||
this.props.onFinished();
|
||||
@ -193,7 +193,7 @@ module.exports = createReactClass({
|
||||
RoomNotifs.setRoomNotifsState(roomId, newState).done(() => {
|
||||
// delay slightly so that the user can see their state change
|
||||
// before closing the menu
|
||||
return Promise.delay(500).then(() => {
|
||||
return sleep(500).then(() => {
|
||||
if (this._unmounted) return;
|
||||
// Close the context menu
|
||||
if (this.props.onFinished) {
|
||||
|
@ -25,13 +25,13 @@ import { _t, _td } from '../../../languageHandler';
|
||||
import sdk from '../../../index';
|
||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
||||
import dis from '../../../dispatcher';
|
||||
import Promise from 'bluebird';
|
||||
import { addressTypes, getAddressType } from '../../../UserAddress.js';
|
||||
import GroupStore from '../../../stores/GroupStore';
|
||||
import * as Email from '../../../email';
|
||||
import IdentityAuthClient from '../../../IdentityAuthClient';
|
||||
import { getDefaultIdentityServerUrl, useDefaultIdentityServer } from '../../../utils/IdentityServerUtils';
|
||||
import { abbreviateUrl } from '../../../utils/UrlUtils';
|
||||
import {sleep} from "../../../utils/promise";
|
||||
|
||||
const TRUNCATE_QUERY_LIST = 40;
|
||||
const QUERY_USER_DIRECTORY_DEBOUNCE_MS = 200;
|
||||
@ -533,7 +533,7 @@ module.exports = createReactClass({
|
||||
};
|
||||
|
||||
// wait a bit to let the user finish typing
|
||||
await Promise.delay(500);
|
||||
await sleep(500);
|
||||
if (cancelled) return null;
|
||||
|
||||
try {
|
||||
|
@ -26,6 +26,7 @@ import { Room } from 'matrix-js-sdk';
|
||||
|
||||
import SettingsStore from "../../../settings/SettingsStore";
|
||||
import Autocompleter from '../../../autocomplete/Autocompleter';
|
||||
import {sleep} from "../../../utils/promise";
|
||||
|
||||
const COMPOSER_SELECTED = 0;
|
||||
|
||||
@ -105,13 +106,11 @@ export default class Autocomplete extends React.Component {
|
||||
autocompleteDelay = 0;
|
||||
}
|
||||
|
||||
const deferred = Promise.defer();
|
||||
this.debounceCompletionsRequest = setTimeout(() => {
|
||||
this.processQuery(query, selection).then(() => {
|
||||
deferred.resolve();
|
||||
});
|
||||
}, autocompleteDelay);
|
||||
return deferred.promise;
|
||||
return new Promise((resolve) => {
|
||||
this.debounceCompletionsRequest = setTimeout(() => {
|
||||
resolve(this.processQuery(query, selection));
|
||||
}, autocompleteDelay);
|
||||
});
|
||||
}
|
||||
|
||||
processQuery(query, selection) {
|
||||
@ -197,16 +196,16 @@ export default class Autocomplete extends React.Component {
|
||||
}
|
||||
|
||||
forceComplete() {
|
||||
const done = Promise.defer();
|
||||
this.setState({
|
||||
forceComplete: true,
|
||||
hide: false,
|
||||
}, () => {
|
||||
this.complete(this.props.query, this.props.selection).then(() => {
|
||||
done.resolve(this.countCompletions());
|
||||
return new Promise((resolve) => {
|
||||
this.setState({
|
||||
forceComplete: true,
|
||||
hide: false,
|
||||
}, () => {
|
||||
this.complete(this.props.query, this.props.selection).then(() => {
|
||||
resolve(this.countCompletions());
|
||||
});
|
||||
});
|
||||
});
|
||||
return done.promise;
|
||||
}
|
||||
|
||||
onCompletionClicked(selectionOffset: number): boolean {
|
||||
|
@ -178,17 +178,12 @@ module.exports = createReactClass({
|
||||
},
|
||||
|
||||
_optionallySetEmail: function() {
|
||||
const deferred = Promise.defer();
|
||||
// Ask for an email otherwise the user has no way to reset their password
|
||||
const SetEmailDialog = sdk.getComponent("dialogs.SetEmailDialog");
|
||||
Modal.createTrackedDialog('Do you want to set an email address?', '', SetEmailDialog, {
|
||||
const modal = Modal.createTrackedDialog('Do you want to set an email address?', '', SetEmailDialog, {
|
||||
title: _t('Do you want to set an email address?'),
|
||||
onFinished: (confirmed) => {
|
||||
// ignore confirmed, setting an email is optional
|
||||
deferred.resolve(confirmed);
|
||||
},
|
||||
});
|
||||
return deferred.promise;
|
||||
return modal.finished.then(([confirmed]) => confirmed);
|
||||
},
|
||||
|
||||
_onExportE2eKeysClicked: function() {
|
||||
|
@ -26,6 +26,7 @@ import { getThreepidsWithBindStatus } from '../../../boundThreepids';
|
||||
import IdentityAuthClient from "../../../IdentityAuthClient";
|
||||
import {abbreviateUrl, unabbreviateUrl} from "../../../utils/UrlUtils";
|
||||
import { getDefaultIdentityServerUrl, doesIdentityServerHaveTerms } from '../../../utils/IdentityServerUtils';
|
||||
import {timeout} from "../../../utils/promise";
|
||||
|
||||
// We'll wait up to this long when checking for 3PID bindings on the IS.
|
||||
const REACHABILITY_TIMEOUT = 10000; // ms
|
||||
@ -245,14 +246,11 @@ export default class SetIdServer extends React.Component {
|
||||
let threepids = [];
|
||||
let currentServerReachable = true;
|
||||
try {
|
||||
threepids = await Promise.race([
|
||||
threepids = await timeout(
|
||||
getThreepidsWithBindStatus(MatrixClientPeg.get()),
|
||||
new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
reject(new Error("Timeout attempting to reach identity server"));
|
||||
}, REACHABILITY_TIMEOUT);
|
||||
}),
|
||||
]);
|
||||
Promise.reject(new Error("Timeout attempting to reach identity server")),
|
||||
REACHABILITY_TIMEOUT,
|
||||
);
|
||||
} catch (e) {
|
||||
currentServerReachable = false;
|
||||
console.warn(
|
||||
|
@ -22,9 +22,9 @@ import MatrixClientPeg from "../../../../../MatrixClientPeg";
|
||||
import * as FormattingUtils from "../../../../../utils/FormattingUtils";
|
||||
import AccessibleButton from "../../../elements/AccessibleButton";
|
||||
import Analytics from "../../../../../Analytics";
|
||||
import Promise from "bluebird";
|
||||
import Modal from "../../../../../Modal";
|
||||
import sdk from "../../../../..";
|
||||
import {sleep} from "../../../../../utils/promise";
|
||||
|
||||
export class IgnoredUser extends React.Component {
|
||||
static propTypes = {
|
||||
@ -129,7 +129,7 @@ export default class SecurityUserSettingsTab extends React.Component {
|
||||
if (e.errcode === "M_LIMIT_EXCEEDED") {
|
||||
// Add a delay between each invite change in order to avoid rate
|
||||
// limiting by the server.
|
||||
await Promise.delay(e.retry_after_ms || 2500);
|
||||
await sleep(e.retry_after_ms || 2500);
|
||||
|
||||
// Redo last action
|
||||
i--;
|
||||
|
@ -105,26 +105,22 @@ export default async function sendBugReport(bugReportEndpoint, opts) {
|
||||
}
|
||||
|
||||
function _submitReport(endpoint, body, progressCallback) {
|
||||
const deferred = Promise.defer();
|
||||
|
||||
const req = new XMLHttpRequest();
|
||||
req.open("POST", endpoint);
|
||||
req.timeout = 5 * 60 * 1000;
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState === XMLHttpRequest.LOADING) {
|
||||
progressCallback(_t("Waiting for response from server"));
|
||||
} else if (req.readyState === XMLHttpRequest.DONE) {
|
||||
on_done();
|
||||
}
|
||||
};
|
||||
req.send(body);
|
||||
return deferred.promise;
|
||||
|
||||
function on_done() {
|
||||
if (req.status < 200 || req.status >= 400) {
|
||||
deferred.reject(new Error(`HTTP ${req.status}`));
|
||||
return;
|
||||
}
|
||||
deferred.resolve();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const req = new XMLHttpRequest();
|
||||
req.open("POST", endpoint);
|
||||
req.timeout = 5 * 60 * 1000;
|
||||
req.onreadystatechange = function() {
|
||||
if (req.readyState === XMLHttpRequest.LOADING) {
|
||||
progressCallback(_t("Waiting for response from server"));
|
||||
} else if (req.readyState === XMLHttpRequest.DONE) {
|
||||
// on done
|
||||
if (req.status < 200 || req.status >= 400) {
|
||||
reject(new Error(`HTTP ${req.status}`));
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
req.send(body);
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
|
49
src/utils/promise.js
Normal file
49
src/utils/promise.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// This is only here to allow access to methods like done for the time being
|
||||
import Promise from "bluebird";
|
||||
|
||||
// @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};
|
||||
}
|
Loading…
Reference in New Issue
Block a user