import util from "../plugins/utils"; export default { data() { return { sendStatuses: Object.freeze({ INITIAL: 0, SENDING: 1, SENT: 2, CANCELED: 3, FAILED: 4, }), sendingStatus: 0, sendingPromise: null, sendingRootEventId: null, sendingAttachments: [], } }, computed: { attachmentsSentCount() { return this.sendingAttachments ? this.sendingAttachments.reduce((a, elem, ignoredidx, ignoredarray) => elem.status == this.sendStatuses.SENT ? a + 1 : a, 0) : 0 }, attachmentsSending() { return this.sendingAttachments ? this.sendingAttachments.filter(elem => elem.status == this.sendStatuses.INITIAL || elem.status == this.sendStatuses.SENDING) : [] }, attachmentsSent() { this.sortSendingAttachments(); return this.sendingAttachments ? this.sendingAttachments.filter(elem => elem.status == this.sendStatuses.SENT) : [] }, }, methods: { sendAttachments(text, attachments) { this.sendingStatus = this.sendStatuses.SENDING; this.sendingAttachments = attachments.map((attachment) => { let file = (() => { // other than file type image if(attachment instanceof File) { return attachment; } else { if (attachment.scaled && attachment.useScaled) { // Send scaled version of image instead! return attachment.scaled; } else { // Send actual file image when not scaled! return attachment.actualFile; } } })(); let sendInfo = { id: attachment.name, status: this.sendStatuses.INITIAL, statusDate: Date.now, mediaEventId: undefined, attachment: file, preview: attachment.image, progress: 0, randomRotation: 0, randomTranslationX: 0, randomTranslationY: 0 }; attachment.sendInfo = sendInfo; return sendInfo; }); this.sendingPromise = util.sendTextMessage(this.$matrix.matrixClient, this.room.roomId, text) .then((eventId) => { this.sendingRootEventId = eventId; // Use the eventId as a thread root for all the media let promiseChain = Promise.resolve(); const getItemPromise = (index) => { if (index < this.sendingAttachments.length) { const item = this.sendingAttachments[index]; if (item.status !== this.sendStatuses.INITIAL) { return getItemPromise(++index); } item.status = this.sendStatuses.SENDING; const itemPromise = util.sendFile(this.$matrix.matrixClient, this.room.roomId, item.attachment, ({ loaded, total }) => { if (loaded == total) { item.progress = 100; } else if (total > 0) { item.progress = 100 * loaded / total; } }, eventId) .then((mediaEventId) => { // Look at last item rotation, flipping the sign on this, so looks more like a true stack let signR = 1; let signX = 1; let signY = 1; if (this.attachmentsSent.length > 0) { if (this.attachmentsSent[0].randomRotation >= 0) { signR = -1; } if (this.attachmentsSent[0].randomTranslationX >= 0) { signX = -1; } if (this.attachmentsSent[0].randomTranslationY >= 0) { signY = -1; } } item.randomRotation = signR * (2 + Math.random() * 10); item.randomTranslationX = signX * Math.random() * 20; item.randomTranslationY = signY * Math.random() * 20; item.mediaEventId = mediaEventId; item.status = this.sendStatuses.SENT; item.statusDate = Date.now; }).catch(ignorederr => { if (item.promise.aborted) { item.status = this.sendStatuses.CANCELED; } else { console.error("ERROR", ignorederr); item.status = this.sendStatuses.FAILED; } }); item.promise = itemPromise; return itemPromise.then(() => getItemPromise(++index)); } else return Promise.resolve(); }; return promiseChain.then(() => getItemPromise(0)); }) .then(() => { this.sendingStatus = this.sendStatuses.SENT; this.sendingRootEventId = null; }) .catch((err) => { console.error("ERROR", err); }); return this.sendingPromise; }, cancelSendAttachments() { this.sendingAttachments.toReversed().forEach(item => { this.cancelSendAttachmentItem(item); }); this.sendingStatus = this.sendStatuses.CANCELED; if (this.sendingRootEventId && this.room) { // Redact all media we already sent, plus the root event let promises = this.sendingAttachments.filter((item) => item.mediaEventId !== undefined).map((item) => this.$matrix.matrixClient.redactEvent(this.room.roomId, item.mediaEventId, undefined, { reason: "cancel" })); promises.push(this.$matrix.matrixClient.redactEvent(this.room.roomId, this.sendingRootEventId, undefined, { reason: "cancel" })); Promise.allSettled(promises) .then(() => { console.log("Message redacted"); }) .catch((err) => { console.log("Redaction failed: ", err); }); } }, cancelSendAttachmentItem(item) { if (item.promise && item.status != this.sendStatuses.INITIAL) { item.promise.abort(); } item.status = this.sendStatuses.CANCELED; }, sortSendingAttachments() { this.sendingAttachments.sort((a, b) => b.statusDate - a.statusDate); }, } }