Resolve "when uploading multiple media files, send and display it as a thread"

This commit is contained in:
N Pex 2023-08-09 15:24:50 +00:00
parent a5ff54842c
commit 5ac61eac7c
7 changed files with 369 additions and 173 deletions

View file

@ -44,7 +44,7 @@
sendCurrentTextMessage();
}
" />
<v-btn @click="send" :disabled="!attachments || attachments.length == 0">{{ $t("menu.send") }}</v-btn>
<v-btn @click="sendAll" :disabled="!attachments || attachments.length == 0">{{ $t("menu.send") }}</v-btn>
</div>
</div>
</template>
@ -54,13 +54,13 @@
v-if="attachments && attachments.length > 0 && (status == mainStatuses.SENDING || status == mainStatuses.SENT)">
<div class="attachment-wrapper">
<div class="file-drop-sent-stack" ref="stackContainer">
<div v-if="status == mainStatuses.SENDING && countSent == 0" class="no-items">
<div v-if="status == mainStatuses.SENDING && attachmentsSentCount == 0" class="no-items">
<div class="file-drop-stack-item direct" :style="stackItemTransform(null, -1)"></div>
<div>{{ $t('file_mode.sending_progress') }}</div>
</div>
<div v-else v-for="(item, index) in sentItems" :key="item.id" class="file-drop-stack-item animated"
:style="stackItemTransform(item, index)">
<v-img v-if="item.attachment && item.attachment.image" :src="item.attachment.image" />
<div v-else v-for="(info, index) in attachmentsSent" :key="info.id" class="file-drop-stack-item animated"
:style="stackItemTransform(info, index)">
<v-img v-if="info.preview" :src="info.preview" />
</div>
<div v-if="status == mainStatuses.SENT" class="items-sent" :style="stackItemTransform(null, -1)">
<v-icon>$vuetify.icons.ic_check_circle</v-icon>
@ -69,18 +69,18 @@
<!-- Middle section -->
<div v-if="status == mainStatuses.SENDING" class="file-drop-sending-container">
<div class="file-drop-sending-item" v-for="(info, index) in sendingItems" :key="index">
<v-img v-if="info.attachment && info.attachment.image" :src="info.attachment.image" />
<div class="file-drop-sending-item" v-for="(info, index) in attachmentsSending" :key="index">
<v-img v-if="info.preview" :src="info.preview" />
<div v-else class="filename">{{ info.attachment.name }}</div>
<v-progress-linear :value="info.progress"></v-progress-linear>
<div class="file-drop-cancel clickable" @click.stop="cancelSendingItem(info)">
<div class="file-drop-cancel clickable" @click.stop="cancelSendAttachmentItem(info)">
<v-icon size="14" color="white">close</v-icon>
</div>
</div>
</div>
<div v-else-if="status == mainStatuses.SENT" class="file-drop-sending-container">
<div class="file-drop-files-sent">{{ $tc((this.messageInput && this.messageInput.length > 0) ?
"file_mode.files_sent_with_note" : "file_mode.files_sent", sentItems.length) }}</div>
"file_mode.files_sent_with_note" : "file_mode.files_sent", attachmentsSent.length) }}</div>
<div class="file-drop-section">
<v-textarea disabled full-width solo flat auto-grow v-model="messageInput" no-resize class="input-area-text"
rows="1" hide-details background-color="transparent" />
@ -105,11 +105,11 @@
<script>
import messageMixin from "../messages/messageMixin";
import util from "../../plugins/utils";
import sendAttachmentsMixin from "../sendAttachmentsMixin";
const prettyBytes = require("pretty-bytes");
export default {
mixins: [messageMixin],
mixins: [messageMixin, sendAttachmentsMixin],
components: {},
props: {
attachments: {
@ -129,13 +129,6 @@ export default {
SENT: 2,
}),
status: 0,
statuses: Object.freeze({
INITIAL: 0,
SENT: 1,
CANCELED: 2,
FAILED: 3,
}),
sendInfo: [],
dropTarget: false,
};
},
@ -151,20 +144,6 @@ export default {
return this.currentItemIndex >= 0 && this.currentItemIndex < this.attachments.length &&
this.attachments[this.currentItemIndex].image
},
countSent() {
return this.sendInfo ? this.sendInfo.reduce((a, elem, ignoredidx, ignoredarray) => elem.status == this.statuses.SENT ? a + 1 : a, 0) : 0
},
sendingItems() {
return this.sendInfo ? this.sendInfo.filter(elem => elem.status == this.statuses.INITIAL) : []
},
sentItems() {
this.sortSendinfo();
return this.sendInfo ? this.sendInfo.filter(elem => elem.status == this.statuses.SENT) : []
},
sentItemsReversed() {
const array = this.sentItems;
return array.map((ignoreditem, idx) => array[array.length - 1 - idx])
}
},
watch: {
attachments(newValue, oldValue) {
@ -207,7 +186,7 @@ export default {
},
reset() {
this.$emit('reset');
this.sendInfo = [];
this.sendingAttachments = [];
this.status = this.mainStatuses.SELECTING;
this.messageInput = "";
this.currentItemIndex = 0;
@ -218,97 +197,13 @@ export default {
console.log("Error leaving", err);
});
},
send() {
sendAll() {
this.status = this.mainStatuses.SENDING;
this.sendInfo = this.attachments.map((attachment) => {
return {
id: attachment.name,
status: this.statuses.INITIAL,
statusDate: Date.now,
attachment: attachment.actualFile || attachment,
progress: 0,
randomRotation: 0,
randomTranslationX: 0,
randomTranslationY: 0
}
});
const text = (this.messageInput && this.messageInput.length > 0) ? this.messageInput : this.$t('file_mode.files');
util.sendTextMessage(this.$matrix.matrixClient, this.room.roomId, text)
.then((eventId) => {
// Use the eventId as a thread root for all the media
let promiseChain = Promise.resolve();
const getItemPromise = (index) => {
if (index < this.sendInfo.length) {
const item = this.sendInfo[index];
if (item.status !== this.statuses.INITIAL) {
return getItemPromise(++index);
}
const itemPromise = util.sendImage(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(() => {
// 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.sentItems.length > 0) {
if (this.sentItems[0].randomRotation >= 0) {
signR = -1;
}
if (this.sentItems[0].randomTranslationX >= 0) {
signX = -1;
}
if (this.sentItems[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.status = this.statuses.SENT;
item.statusDate = Date.now;
}).catch(ignorederr => {
if (item.promise.aborted) {
item.status = this.statuses.CANCELED;
} else {
console.error("ERROR", ignorederr);
item.status = this.statuses.FAILED;
}
});
item.promise = itemPromise;
return itemPromise.then(() => getItemPromise(++index));
}
else return Promise.resolve();
};
return promiseChain.then(() => getItemPromise(0));
})
this.sendAttachments((this.messageInput && this.messageInput.length > 0) ? this.messageInput : this.$t('file_mode.files'), this.attachments)
.then(() => {
this.status = this.mainStatuses.SENT;
})
.catch((err) => {
console.error("ERROR", err);
});
},
cancelSendingItem(item) {
if (item.promise && item.status == this.statuses.INITIAL) {
item.promise.abort();
}
item.status = this.statuses.CANCELED;
},
checkDone() {
if (!this.sendInfo.some(a => a.status == this.statuses.INITIAL)) {
this.status = this.mainStatuses.SENT;
}
},
sortSendinfo() {
this.sendInfo.sort((a, b) => b.statusDate - a.statusDate);
},
stackItemTransform(item, index) {
const size = 0.6 * (this.$refs.stackContainer ? Math.min(this.$refs.stackContainer.clientWidth, this.$refs.stackContainer.clientHeight) : 176);
let transform = ""