More send media optimization

This commit is contained in:
N-Pex 2025-07-17 11:22:26 +02:00
parent 7b4b35762a
commit 9b0a6ae225
5 changed files with 54 additions and 55 deletions

View file

@ -83,6 +83,7 @@ $hiliteColor: #4642f1;
flex: 1 1 100%; flex: 1 1 100%;
background-color: $backgroundSection; background-color: $backgroundSection;
display: flex; display: flex;
position: relative;
&.drop-target { &.drop-target {
background-color: $backgroundHilite; background-color: $backgroundHilite;
@ -97,13 +98,14 @@ $hiliteColor: #4642f1;
object-fit: cover; object-fit: cover;
} }
.filename { .send-attachments__selecting__current-item__preparing {
width: 100%; position: absolute;
height: 100%; right: 8px;
bottom: 4px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: end;
justify-content: center; justify-content: end;
} }
} }

View file

@ -1392,15 +1392,6 @@ export default {
this.$refs.attachment.click(); this.$refs.attachment.click();
}, },
addAttachment(file) {
if (file) {
if (!this.uploadBatch) {
this.uploadBatch = this.$matrix.attachmentManager.createUpload(this.room);
}
this.uploadBatch?.addAttachment(this.$matrix.attachmentManager.createAttachment(file));
}
},
/** /**
* Handle picked attachment * Handle picked attachment
*/ */
@ -1411,7 +1402,10 @@ export default {
}, },
addAttachments(files) { addAttachments(files) {
files.forEach(file => this.addAttachment(file)); if (!this.uploadBatch) {
this.uploadBatch = this.$matrix.attachmentManager.createUpload(this.room);
}
this.uploadBatch?.addAttachments(files.map((f) => this.$matrix.attachmentManager.createAttachment(f)));
}, },
showStickerPicker() { showStickerPicker() {
@ -1862,7 +1856,7 @@ export default {
onVoiceRecording(event) { onVoiceRecording(event) {
const batch = this.$matrix.attachmentManager.createUpload(this.room); const batch = this.$matrix.attachmentManager.createUpload(this.room);
batch.addAttachment(this.$matrix.attachmentManager.createAttachment(event.file)); batch.addAttachments([this.$matrix.attachmentManager.createAttachment(event.file)]);
var text = undefined; var text = undefined;
if (this.currentInput && this.currentInput.length > 0) { if (this.currentInput && this.currentInput.length > 0) {
text = this.currentInput; text = this.currentInput;

View file

@ -22,14 +22,12 @@
@dragleave.prevent="dropTarget = false" @dragleave.prevent="dropTarget = false"
@dragenter.prevent="dropTarget = true" @dragenter.prevent="dropTarget = true"
> >
<div v-if="currentAttachment && currentAttachment.status === 'loading'" class="filename"> <ThumbnailView :file="currentAttachment" />
<div>{{ currentAttachment.file.name }}</div> <div v-if="currentAttachment && currentAttachment.status === 'loading'" class="send-attachments__selecting__current-item__preparing">
<div style="font-size: 0.7em; opacity: 0.7"> <div style="font-size: 0.7em; opacity: 0.7">
{{ $t("message.preparing_to_upload") }} <v-progress-circular indeterminate class="mb-0"></v-progress-circular>
<v-progress-linear indeterminate class="mb-0"></v-progress-linear>
</div> </div>
</div> </div>
<ThumbnailView v-else :file="currentAttachment" />
</div> </div>
<div class="file-drop-thumbnail-container"> <div class="file-drop-thumbnail-container">
<v-tooltip location="top" v-for="(attachment, index) in batch.attachments" :key="index"> <v-tooltip location="top" v-for="(attachment, index) in batch.attachments" :key="index">
@ -94,6 +92,7 @@
elevation="0" elevation="0"
color="black" color="black"
@click.stop="showInformation" @click.stop="showInformation"
:disabled="currentAttachment?.status !== 'loaded'"
></v-btn> ></v-btn>
</div> </div>
</template> </template>
@ -253,7 +252,7 @@ export default defineComponent({
}, },
data() { data() {
return { return {
currentItemIndex: 0, currentItemIndex: -1,
messageInput: "", messageInput: "",
mainStatuses: Object.freeze({ mainStatuses: Object.freeze({
SELECTING: 0, SELECTING: 0,
@ -276,6 +275,9 @@ export default defineComponent({
return !this.batch.canSend; return !this.batch.canSend;
}, },
currentAttachment(): Attachment | undefined { currentAttachment(): Attachment | undefined {
if (this.currentItemIndex < 0 && this.batch.attachments.length > 0) {
this.currentItemIndex = this.batch.attachments.length - 1;
}
if (this.currentItemIndex >= 0 && this.currentItemIndex < this.batch.attachments.length) { if (this.currentItemIndex >= 0 && this.currentItemIndex < this.batch.attachments.length) {
return this.batch.attachments[this.currentItemIndex]; return this.batch.attachments[this.currentItemIndex];
} }
@ -305,16 +307,18 @@ export default defineComponent({
this.dropTarget = false; this.dropTarget = false;
let droppedFiles: FileList | undefined = e.dataTransfer?.files; let droppedFiles: FileList | undefined = e.dataTransfer?.files;
if (!droppedFiles) return; if (!droppedFiles) return;
let files: File[] = [];
for (let i = 0; i < droppedFiles.length; i++) { for (let i = 0; i < droppedFiles.length; i++) {
const file = droppedFiles.item(i); const file = droppedFiles.item(i);
this.batch.addAttachment(this.$matrix.attachmentManager.createAttachment(file)); if (file) files.push(file);
} }
this.batch.addAttachments(files.map((f) => this.$matrix.attachmentManager.createAttachment(f)));
}, },
close() { close() {
this.batch.cancel(); this.batch.cancel();
this.status = this.mainStatuses.SELECTING; this.status = this.mainStatuses.SELECTING;
this.messageInput = ""; this.messageInput = "";
this.currentItemIndex = 0; this.currentItemIndex = -1;
this.$emit("close"); this.$emit("close");
}, },
sendAll() { sendAll() {

View file

@ -70,7 +70,7 @@ export type AttachmentBatch = {
attachmentsSentCount: ComputedRef<number>; attachmentsSentCount: ComputedRef<number>;
attachmentsSending: ComputedRef<Attachment[]>; attachmentsSending: ComputedRef<Attachment[]>;
attachmentsSent: ComputedRef<Attachment[]>; attachmentsSent: ComputedRef<Attachment[]>;
addAttachment: (attachment: Attachment) => void; addAttachments: (attachments: Attachment[]) => void;
removeAttachment: (attachment: Attachment) => void; removeAttachment: (attachment: Attachment) => void;
isTooLarge: (attachment: Attachment) => boolean; isTooLarge: (attachment: Attachment) => boolean;
canSend: ComputedRef<boolean>; canSend: ComputedRef<boolean>;

View file

@ -57,7 +57,6 @@ export class AttachmentManager {
private async prepareUpload(attachment: Attachment): Promise<Attachment> { private async prepareUpload(attachment: Attachment): Promise<Attachment> {
const file = attachment.file; const file = attachment.file;
if (file.type.startsWith("image/")) { if (file.type.startsWith("image/")) {
attachment.proof = await proofmode.proofCheckFile(file);
let url = URL.createObjectURL(file); let url = URL.createObjectURL(file);
attachment.src = url; attachment.src = url;
if (attachment.src) { if (attachment.src) {
@ -66,8 +65,6 @@ export class AttachmentManager {
img.src = url; img.src = url;
attachment.dimensions = await new Promise((response) => { attachment.dimensions = await new Promise((response) => {
img.onload = (event) => { img.onload = (event) => {
console.log("height: " + img.height);
console.log("width: " + img.width);
response({ width: img.width, height: img.height }); response({ width: img.width, height: img.height });
}; };
img.onerror = (event) => { img.onerror = (event) => {
@ -82,38 +79,38 @@ export class AttachmentManager {
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((w > h ? 640 / aspect : 640).toFixed()); var newHeight = parseInt((w > h ? 640 / aspect : 640).toFixed());
imageResize(file, { const img = await imageResize(file, {
format: "webp", format: "webp",
width: newWidth, width: newWidth,
height: newHeight, height: newHeight,
outputType: "blob", outputType: "blob",
}) });
.then((img) => { attachment.scaledFile = new File([img as BlobPart], file.name, {
attachment.scaledFile = new File([img as BlobPart], file.name, { type: "image/webp",
type: "image/webp", lastModified: Date.now(),
lastModified: Date.now(), });
}); attachment.scaledDimensions = {
attachment.scaledDimensions = { width: newWidth,
width: newWidth, height: newHeight,
height: newHeight, };
};
// Default to scaled version if the image does not contain Content Credentials
//
attachment.useScaled =
attachment.scaledFile !== undefined &&
(attachment.proof === undefined ||
attachment.proof.integrity === undefined ||
attachment.proof.integrity.c2pa === undefined);
})
.catch((err) => {
console.error("Resize failed:", err);
});
} }
} catch (error) { } catch (error) {
console.error("Failed to get image dimensions: " + error); console.error("Failed to get image dimensions: " + error);
} }
} }
try {
attachment.proof = await proofmode.proofCheckFile(file);
// Default to scaled version if the image does not contain Content Credentials
//
attachment.useScaled =
attachment.scaledFile !== undefined &&
(attachment.proof === undefined ||
attachment.proof.integrity === undefined ||
attachment.proof.integrity.c2pa === undefined);
} catch (error) {
console.error("Failed to get content credentials: " + error);
}
} else if (file.type.startsWith("video/")) { } else if (file.type.startsWith("video/")) {
let url = URL.createObjectURL(file); let url = URL.createObjectURL(file);
const thumb: AttachmentThumbnail | undefined = await new Promise((resolve) => { const thumb: AttachmentThumbnail | undefined = await new Promise((resolve) => {
@ -421,9 +418,9 @@ export const createUploadBatch = (
attachments.value.sort((a, b) => (b.sendInfo?.statusDate ?? 0) - (a.sendInfo?.statusDate ?? 0)); attachments.value.sort((a, b) => (b.sendInfo?.statusDate ?? 0) - (a.sendInfo?.statusDate ?? 0));
}; };
const addAttachment = (attachment: Attachment) => { const addAttachments = (attachmentsToAdd: Attachment[]) => {
if (sendingStatus.value == "initial") { if (sendingStatus.value == "initial") {
attachments.value.push(attachment); attachments.value.push(...attachmentsToAdd);
} }
}; };
@ -439,7 +436,9 @@ export const createUploadBatch = (
}; };
const canSend = computed(() => { const canSend = computed(() => {
return attachments.value.length > 0 && !attachments.value.some((a: Attachment) => isTooLarge(a)); return (
attachments.value.length > 0 && !attachments.value.some((a: Attachment) => isTooLarge(a) || a.status !== "loaded")
);
}); });
const cancel = () => { const cancel = () => {
@ -603,7 +602,7 @@ export const createUploadBatch = (
attachmentsSentCount, attachmentsSentCount,
attachmentsSending, attachmentsSending,
attachmentsSent, attachmentsSent,
addAttachment, addAttachments,
removeAttachment, removeAttachment,
isTooLarge, isTooLarge,
canSend, canSend,