report attachment upload progress

This commit is contained in:
Bruno Windels 2020-11-16 10:45:46 +01:00
parent 1dd46b875b
commit 83cbe78cd6
4 changed files with 31 additions and 10 deletions

View file

@ -110,6 +110,7 @@ export class HomeServerApi {
headers,
body: encodedBody,
timeout: options?.timeout,
uploadProgress: options?.uploadProgress,
format: "json" // response format
});

View file

@ -35,12 +35,17 @@ export class AttachmentUpload {
this._aborted = false;
this._error = null;
this._status = new ObservableValue(UploadStatus.Waiting);
this._progress = new ObservableValue(0);
}
get status() {
return this._status;
}
get uploadProgress() {
return this._progress;
}
async upload() {
if (this._status.get() === UploadStatus.Waiting) {
this._upload();
@ -66,9 +71,13 @@ export class AttachmentUpload {
if (this._aborted) {
throw new AbortError("upload aborted during encryption");
}
this._progress.set(0);
this._status.set(UploadStatus.Uploading);
this._uploadRequest = this._hsApi.uploadAttachment(transferredBlob, this._filename);
this._uploadRequest = this._hsApi.uploadAttachment(transferredBlob, this._filename, {
uploadProgress: sentBytes => this._progress.set(sentBytes / transferredBlob.size)
});
const {content_uri} = await this._uploadRequest.response();
this._progress.set(1);
this._mxcUrl = content_uri;
this._transferredBlob = transferredBlob;
this._status.set(UploadStatus.Uploaded);

View file

@ -21,6 +21,7 @@ import {
} from "../../../../matrix/error.js";
import {abortOnTimeout} from "./timeout.js";
import {addCacheBuster} from "./common.js";
import {xhrRequest} from "./xhr.js";
class RequestResult {
constructor(promise, controller) {
@ -51,7 +52,12 @@ class RequestResult {
}
export function createFetchRequest(createTimeout) {
return function fetchRequest(url, {method, headers, body, timeout, format, cache = false}) {
return function fetchRequest(url, requestOptions) {
// fetch doesn't do upload progress yet, delegate to xhr
if (requestOptions?.uploadProgress) {
return xhrRequest(url, requestOptions);
}
let {method, headers, body, timeout, format, cache = false} = requestOptions;
const controller = typeof AbortController === "function" ? new AbortController() : null;
// if a BlobHandle, take native blob
if (body?.nativeBlob) {

View file

@ -35,7 +35,7 @@ class RequestResult {
}
}
function send(url, {method, headers, timeout, body, format}) {
function createXhr(url, {method, headers, timeout, format, uploadProgress}) {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
@ -52,11 +52,9 @@ function send(url, {method, headers, timeout, body, format}) {
xhr.timeout = timeout;
}
// if a BlobHandle, take native blob
if (body?.nativeBlob) {
body = body.nativeBlob;
if (uploadProgress) {
xhr.upload.addEventListener("progress", evt => uploadProgress(evt.loaded));
}
xhr.send(body || null);
return xhr;
}
@ -71,12 +69,12 @@ function xhrAsPromise(xhr, method, url) {
}
export function xhrRequest(url, options) {
const {cache, format} = options;
let {cache, format, body, method} = options;
if (!cache) {
url = addCacheBuster(url);
}
const xhr = send(url, options);
const promise = xhrAsPromise(xhr, options.method, url).then(xhr => {
const xhr = createXhr(url, options);
const promise = xhrAsPromise(xhr, method, url).then(xhr => {
const {status} = xhr;
let body = null;
if (format === "buffer") {
@ -86,5 +84,12 @@ export function xhrRequest(url, options) {
}
return {status, body};
});
// if a BlobHandle, take native blob
if (body?.nativeBlob) {
body = body.nativeBlob;
}
xhr.send(body || null);
return new RequestResult(promise, xhr);
}