Fix upload cancel in e2e rooms
This is a bit of a mess of passing promises around - we weren't taking the right promise to pass to cancelUpload. Also e2e uploads take time to read into memory & encrypt, so allow cancelling them during those phases too, even though we can't abort those phases before they're done - we do mark the upload as cancelled though so filter the current uploads for cancelled ones. Fixes https://github.com/vector-im/riot-web/issues/4891
This commit is contained in:
parent
054011f5f8
commit
59210564b7
3 changed files with 30 additions and 14 deletions
|
@ -34,6 +34,7 @@ import "blueimp-canvas-to-blob";
|
||||||
const MAX_WIDTH = 800;
|
const MAX_WIDTH = 800;
|
||||||
const MAX_HEIGHT = 600;
|
const MAX_HEIGHT = 600;
|
||||||
|
|
||||||
|
export class UploadCancelledError extends Error {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a thumbnail for a image DOM element.
|
* Create a thumbnail for a image DOM element.
|
||||||
|
@ -236,17 +237,25 @@ function uploadFile(matrixClient, roomId, file, progressHandler) {
|
||||||
if (matrixClient.isRoomEncrypted(roomId)) {
|
if (matrixClient.isRoomEncrypted(roomId)) {
|
||||||
// If the room is encrypted then encrypt the file before uploading it.
|
// If the room is encrypted then encrypt the file before uploading it.
|
||||||
// First read the file into memory.
|
// First read the file into memory.
|
||||||
return readFileAsArrayBuffer(file).then(function(data) {
|
let cancelled = false;
|
||||||
|
let uploadPromise;
|
||||||
|
let encryptInfo;
|
||||||
|
const prom = readFileAsArrayBuffer(file).then(function(data) {
|
||||||
|
if (cancelled) throw new UploadCancelledError();
|
||||||
// Then encrypt the file.
|
// Then encrypt the file.
|
||||||
return encrypt.encryptAttachment(data);
|
return encrypt.encryptAttachment(data);
|
||||||
}).then(function(encryptResult) {
|
}).then(function(encryptResult) {
|
||||||
|
if (cancelled) throw new UploadCancelledError();
|
||||||
// Record the information needed to decrypt the attachment.
|
// Record the information needed to decrypt the attachment.
|
||||||
const encryptInfo = encryptResult.info;
|
encryptInfo = encryptResult.info;
|
||||||
// Pass the encrypted data as a Blob to the uploader.
|
// Pass the encrypted data as a Blob to the uploader.
|
||||||
const blob = new Blob([encryptResult.data]);
|
const blob = new Blob([encryptResult.data]);
|
||||||
return matrixClient.uploadContent(blob, {
|
uploadPromise = matrixClient.uploadContent(blob, {
|
||||||
progressHandler: progressHandler,
|
progressHandler: progressHandler,
|
||||||
includeFilename: false,
|
includeFilename: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
return uploadPromise;
|
||||||
}).then(function(url) {
|
}).then(function(url) {
|
||||||
// If the attachment is encrypted then bundle the URL along
|
// If the attachment is encrypted then bundle the URL along
|
||||||
// with the information needed to decrypt the attachment and
|
// with the information needed to decrypt the attachment and
|
||||||
|
@ -257,7 +266,11 @@ function uploadFile(matrixClient, roomId, file, progressHandler) {
|
||||||
}
|
}
|
||||||
return {"file": encryptInfo};
|
return {"file": encryptInfo};
|
||||||
});
|
});
|
||||||
});
|
prom.abort = () => {
|
||||||
|
cancelled = true;
|
||||||
|
if (uploadPromise) MatrixClientPeg.get().cancelUpload(uploadPromise);
|
||||||
|
};
|
||||||
|
return prom;
|
||||||
} else {
|
} else {
|
||||||
const basePromise = matrixClient.uploadContent(file, {
|
const basePromise = matrixClient.uploadContent(file, {
|
||||||
progressHandler: progressHandler,
|
progressHandler: progressHandler,
|
||||||
|
@ -513,7 +526,7 @@ export default class ContentMessages {
|
||||||
}
|
}
|
||||||
|
|
||||||
getCurrentUploads() {
|
getCurrentUploads() {
|
||||||
return this.inprogress;
|
return this.inprogress.filter(u => !u.canceled);
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelUpload(promise) {
|
cancelUpload(promise) {
|
||||||
|
@ -529,6 +542,7 @@ export default class ContentMessages {
|
||||||
if (upload) {
|
if (upload) {
|
||||||
upload.canceled = true;
|
upload.canceled = true;
|
||||||
MatrixClientPeg.get().cancelUpload(upload.promise);
|
MatrixClientPeg.get().cancelUpload(upload.promise);
|
||||||
|
dis.dispatch({action: 'upload_canceled', upload});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -543,6 +543,7 @@ module.exports = React.createClass({
|
||||||
case 'notifier_enabled':
|
case 'notifier_enabled':
|
||||||
case 'upload_started':
|
case 'upload_started':
|
||||||
case 'upload_finished':
|
case 'upload_finished':
|
||||||
|
case 'upload_canceled':
|
||||||
this.forceUpdate();
|
this.forceUpdate();
|
||||||
break;
|
break;
|
||||||
case 'call_state':
|
case 'call_state':
|
||||||
|
|
|
@ -16,7 +16,7 @@ limitations under the License.
|
||||||
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
const ContentMessages = require('../../ContentMessages');
|
import ContentMessages from '../../ContentMessages';
|
||||||
const dis = require('../../dispatcher');
|
const dis = require('../../dispatcher');
|
||||||
const filesize = require('filesize');
|
const filesize = require('filesize');
|
||||||
import { _t } from '../../languageHandler';
|
import { _t } from '../../languageHandler';
|
||||||
|
@ -40,6 +40,7 @@ module.exports = React.createClass({displayName: 'UploadBar',
|
||||||
switch (payload.action) {
|
switch (payload.action) {
|
||||||
case 'upload_progress':
|
case 'upload_progress':
|
||||||
case 'upload_finished':
|
case 'upload_finished':
|
||||||
|
case 'upload_canceled':
|
||||||
case 'upload_failed':
|
case 'upload_failed':
|
||||||
if (this.mounted) this.forceUpdate();
|
if (this.mounted) this.forceUpdate();
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue