Support cancel for sending operation.
This commit is contained in:
parent
0602c4c72f
commit
bb3aaf1bed
2 changed files with 90 additions and 57 deletions
|
|
@ -375,7 +375,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import { TimelineWindow, EventTimeline } from "matrix-js-sdk";
|
import { TimelineWindow, EventTimeline, AbortError } from "matrix-js-sdk";
|
||||||
import util from "../plugins/utils";
|
import util from "../plugins/utils";
|
||||||
import MessageOperations from "./messages/MessageOperations.vue";
|
import MessageOperations from "./messages/MessageOperations.vue";
|
||||||
import AvatarOperations from "./messages/AvatarOperations.vue";
|
import AvatarOperations from "./messages/AvatarOperations.vue";
|
||||||
|
|
@ -1078,7 +1078,11 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.currentSendError = err.toLocaleString();
|
if (err instanceof AbortError || err === "Abort") {
|
||||||
|
this.currentSendError = null;
|
||||||
|
} else {
|
||||||
|
this.currentSendError = err.LocaleString();
|
||||||
|
}
|
||||||
this.currentSendOperation = null;
|
this.currentSendOperation = null;
|
||||||
this.currentSendProgress = null;
|
this.currentSendProgress = null;
|
||||||
});
|
});
|
||||||
|
|
@ -1088,7 +1092,7 @@ export default {
|
||||||
cancelSendAttachment() {
|
cancelSendAttachment() {
|
||||||
this.$refs.attachment.value = null;
|
this.$refs.attachment.value = null;
|
||||||
if (this.currentSendOperation) {
|
if (this.currentSendOperation) {
|
||||||
this.currentSendOperation.reject("Canceled");
|
this.currentSendOperation.abort();
|
||||||
}
|
}
|
||||||
this.currentSendOperation = null;
|
this.currentSendOperation = null;
|
||||||
this.currentImageInput = null;
|
this.currentImageInput = null;
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,28 @@ var _browserCanRecordAudioF = function () {
|
||||||
}
|
}
|
||||||
var _browserCanRecordAudio = _browserCanRecordAudioF();
|
var _browserCanRecordAudio = _browserCanRecordAudioF();
|
||||||
|
|
||||||
|
class AbortablePromise extends Promise {
|
||||||
|
constructor(executor) {
|
||||||
|
const aborter = {
|
||||||
|
aborted: false,
|
||||||
|
abortablePromise: undefined,
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalExecutor = function (resolve, reject) {
|
||||||
|
executor(resolve, reject, aborter);
|
||||||
|
};
|
||||||
|
|
||||||
|
super(normalExecutor);
|
||||||
|
this.abort = () => {
|
||||||
|
aborter.aborted = true;
|
||||||
|
if (aborter.abortablePromise) {
|
||||||
|
aborter.abortablePromise.abort();
|
||||||
|
aborter.abortablePromise = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class Util {
|
class Util {
|
||||||
getAttachment(matrixClient, event, progressCallback, asBlob = false) {
|
getAttachment(matrixClient, event, progressCallback, asBlob = false) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
@ -170,7 +192,7 @@ class Util {
|
||||||
}
|
}
|
||||||
let senderContent = replyToEvent.getContent()
|
let senderContent = replyToEvent.getContent()
|
||||||
|
|
||||||
const senderContentBody = Object.getOwnPropertyDescriptor(senderContent,'body') ? senderContent.body : Object.values(senderContent)[0].question.body
|
const senderContentBody = Object.getOwnPropertyDescriptor(senderContent, 'body') ? senderContent.body : Object.values(senderContent)[0].question.body
|
||||||
// Prefix the content with reply info (seems to be a legacy thing)
|
// Prefix the content with reply info (seems to be a legacy thing)
|
||||||
const prefix = senderContentBody.split('\n').map((item, index) => {
|
const prefix = senderContentBody.split('\n').map((item, index) => {
|
||||||
return "> " + (index == 0 ? ("<" + replyToEvent.getSender() + "> ") : "") + item;
|
return "> " + (index == 0 ? ("<" + replyToEvent.getSender() + "> ") : "") + item;
|
||||||
|
|
@ -195,7 +217,7 @@ class Util {
|
||||||
var idx = 0;
|
var idx = 0;
|
||||||
let answerData = answers.map(a => {
|
let answerData = answers.map(a => {
|
||||||
idx++;
|
idx++;
|
||||||
return {id: "" + idx, 'org.matrix.msc1767.text': a.text }
|
return { id: "" + idx, 'org.matrix.msc1767.text': a.text }
|
||||||
});
|
});
|
||||||
const content = {
|
const content = {
|
||||||
'org.matrix.msc3381.poll.start': {
|
'org.matrix.msc3381.poll.start': {
|
||||||
|
|
@ -285,9 +307,14 @@ class Util {
|
||||||
}
|
}
|
||||||
|
|
||||||
sendImage(matrixClient, roomId, file, onUploadProgress) {
|
sendImage(matrixClient, roomId, file, onUploadProgress) {
|
||||||
return new Promise((resolve, reject) => {
|
return new AbortablePromise((resolve, reject, aborter) => {
|
||||||
|
const abortionController = aborter;
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
|
if (abortionController.aborted) {
|
||||||
|
reject("Aborted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const fileContents = e.target.result;
|
const fileContents = e.target.result;
|
||||||
var data = new Uint8Array(fileContents);
|
var data = new Uint8Array(fileContents);
|
||||||
|
|
||||||
|
|
@ -326,7 +353,8 @@ class Util {
|
||||||
|
|
||||||
if (!matrixClient.isRoomEncrypted(roomId)) {
|
if (!matrixClient.isRoomEncrypted(roomId)) {
|
||||||
// Not encrypted.
|
// Not encrypted.
|
||||||
matrixClient.uploadContent(data, opts)
|
abortionController.abortablePromise = matrixClient.uploadContent(data, opts);
|
||||||
|
abortionController.abortablePromise
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
messageContent.url = response.content_uri;
|
messageContent.url = response.content_uri;
|
||||||
return this.sendMessage(matrixClient, roomId, "m.room.message", messageContent)
|
return this.sendMessage(matrixClient, roomId, "m.room.message", messageContent)
|
||||||
|
|
@ -373,7 +401,8 @@ class Util {
|
||||||
// Encrypted data sent as octet-stream!
|
// Encrypted data sent as octet-stream!
|
||||||
opts.type = "application/octet-stream";
|
opts.type = "application/octet-stream";
|
||||||
|
|
||||||
matrixClient.uploadContent(data, opts)
|
abortionController.abortablePromise = matrixClient.uploadContent(data, opts);
|
||||||
|
abortionController.abortablePromise
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.error) {
|
if (response.error) {
|
||||||
return reject(response.error);
|
return reject(response.error);
|
||||||
|
|
@ -604,57 +633,57 @@ class Util {
|
||||||
|
|
||||||
loadAvatarFromFile(event, onLoad) {
|
loadAvatarFromFile(event, onLoad) {
|
||||||
if (event.target.files && event.target.files[0]) {
|
if (event.target.files && event.target.files[0]) {
|
||||||
var reader = new FileReader();
|
var reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
const file = event.target.files[0];
|
const file = event.target.files[0];
|
||||||
if (file.type.startsWith("image/")) {
|
if (file.type.startsWith("image/")) {
|
||||||
try {
|
try {
|
||||||
var image = e.target.result;
|
var image = e.target.result;
|
||||||
|
|
||||||
var dimens = sizeOf(dataUriToBuffer(e.target.result));
|
var dimens = sizeOf(dataUriToBuffer(e.target.result));
|
||||||
|
|
||||||
// Need to resize?
|
// Need to resize?
|
||||||
const w = dimens.width;
|
const w = dimens.width;
|
||||||
const h = dimens.height;
|
const h = dimens.height;
|
||||||
if (w > 640 || h > 640) {
|
if (w > 640 || h > 640) {
|
||||||
var aspect = w / h;
|
var aspect = w / h;
|
||||||
var newWidth = parseInt((w > h ? 640 : 640 * aspect).toFixed());
|
var newWidth = parseInt((w > h ? 640 : 640 * aspect).toFixed());
|
||||||
var newHeight = parseInt(
|
var newHeight = parseInt(
|
||||||
(w > h ? 640 / aspect : 640).toFixed()
|
(w > h ? 640 / aspect : 640).toFixed()
|
||||||
);
|
);
|
||||||
var imageResize = new ImageResize({
|
var imageResize = new ImageResize({
|
||||||
format: "png",
|
format: "png",
|
||||||
width: newWidth,
|
width: newWidth,
|
||||||
height: newHeight,
|
height: newHeight,
|
||||||
outputType: "blob",
|
outputType: "blob",
|
||||||
});
|
});
|
||||||
imageResize
|
imageResize
|
||||||
.play(event.target)
|
.play(event.target)
|
||||||
.then((img) => {
|
.then((img) => {
|
||||||
var resizedImageFile = new File([img], file.name, {
|
var resizedImageFile = new File([img], file.name, {
|
||||||
type: img.type,
|
type: img.type,
|
||||||
lastModified: Date.now(),
|
lastModified: Date.now(),
|
||||||
});
|
});
|
||||||
var reader2 = new FileReader();
|
var reader2 = new FileReader();
|
||||||
reader2.onload = (e) => {
|
reader2.onload = (e) => {
|
||||||
onLoad(e.target.result);
|
onLoad(e.target.result);
|
||||||
};
|
};
|
||||||
reader2.readAsDataURL(resizedImageFile);
|
reader2.readAsDataURL(resizedImageFile);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error("Resize failed:", err);
|
console.error("Resize failed:", err);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
onLoad(image);
|
onLoad(image);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to get image dimensions: " + error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
};
|
||||||
console.error("Failed to get image dimensions: " + error);
|
reader.readAsDataURL(event.target.files[0]);
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(event.target.files[0]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return number of whole days between the timestamps, at end of that day.
|
* Return number of whole days between the timestamps, at end of that day.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue