send multiple files at once

This commit is contained in:
10G Meow 2023-05-06 14:03:15 +03:00
parent 6cd47a88c0
commit 31a1eaf3db

View file

@ -186,26 +186,38 @@
</v-container> </v-container>
<input ref="attachment" type="file" name="attachment" @change="handlePickedAttachment($event)" <input ref="attachment" type="file" name="attachment" @change="handlePickedAttachment($event)"
accept="image/*, audio/*, video/*, .pdf" class="d-none" /> accept="image/*, audio/*, video/*, .pdf" class="d-none" multiple/>
<div v-if="currentImageInputPath"> <div v-if="isCurrentImageInputsPathDialog">
<v-dialog v-model="currentImageInputPath" class="ma-0 pa-0" :width="$vuetify.breakpoint.smAndUp ? '50%' : '85%'"> <v-dialog v-model="isCurrentImageInputsPathDialog" class="ma-0 pa-0" :width="$vuetify.breakpoint.smAndUp ? '50%' : '85%'" persistent scrollable>
<v-card class="ma-0 pa-0"> <v-card class="ma-0 pa-0">
<v-card-text class="ma-0 pa-2"> <template v-if="Array.isArray(currentImageInputs)">
<v-card-text :class="{'ma-0 pa-2' : true, 'd-flex flex-wrap justify-center': currentImageInputs.length > 1}">
<div :class="{'col-4': currentImageInputs.length > 1}" v-for="(currentImageInput, id) in currentImageInputs" :key="id">
<v-img v-if="currentImageInput && currentImageInput.image" :aspect-ratio="1" :src="currentImageInput.image" <v-img v-if="currentImageInput && currentImageInput.image" :aspect-ratio="1" :src="currentImageInput.image"
contain class="current-image-input-path" /> contain class="current-image-input-path" />
<div> <div>
file: {{ currentImageInputPath.name }}
<span v-if="currentImageInput && currentImageInput.scaled && currentImageInput.useScaled"> <span v-if="currentImageInput && currentImageInput.scaled && currentImageInput.useScaled">
{{ currentImageInput.scaledDimensions.width }} x {{ currentImageInput.scaledDimensions.height }}</span> {{ currentImageInput.scaledDimensions.width }} x {{ currentImageInput.scaledDimensions.height }}</span>
<span v-else-if="currentImageInput && currentImageInput.dimensions"> <span v-else-if="currentImageInput && currentImageInput.dimensions">
{{ currentImageInput.dimensions.width }} x {{ currentImageInput.dimensions.height }}</span> {{ currentImageInput.dimensions.width }} x {{ currentImageInput.dimensions.height }}</span>
<span v-if="currentImageInput && currentImageInput.scaled && currentImageInput.useScaled"> <span v-if="currentImageInput && currentImageInput.scaled && currentImageInput.useScaled">
({{ formatBytes(currentImageInput.scaledSize) }})</span> ({{ formatBytes(currentImageInput.scaledSize) }})</span>
<span v-else> ({{ formatBytes(currentImageInputPath.size) }})</span>
<v-switch v-if="currentImageInput && currentImageInput.scaled" :label="$t('message.scale_image')" <v-switch v-if="currentImageInput && currentImageInput.scaled" :label="$t('message.scale_image')"
v-model="currentImageInput.useScaled" /> v-model="currentImageInput.useScaled" />
</div> </div>
</div>
</v-card-text>
</template>
<template v-else>
<v-card-text>
<div v-for="(currentImageInputPath, id) in currentImageInputsPath" :key="id">
<span>file: {{ currentImageInputPath.name }}</span>
<span> ({{ formatBytes(currentImageInputPath.size) }})</span>
</div>
</v-card-text>
</template>
<v-card-text>
<div v-if="currentSendError">{{ currentSendError }}</div> <div v-if="currentSendError">{{ currentSendError }}</div>
<div v-else>{{ currentSendProgress }}</div> <div v-else>{{ currentSendProgress }}</div>
</v-card-text> </v-card-text>
@ -338,8 +350,8 @@ export default {
timelineWindowPaginating: false, timelineWindowPaginating: false,
scrollPosition: null, scrollPosition: null,
currentImageInput: null, currentImageInputs: null,
currentImageInputPath: null, currentImageInputsPath: null,
currentSendOperation: null, currentSendOperation: null,
currentSendProgress: null, currentSendProgress: null,
currentSendShowSendButton: true, currentSendShowSendButton: true,
@ -423,6 +435,17 @@ export default {
}, },
computed: { computed: {
isCurrentImageInputsPath() {
return Array.isArray(this.currentImageInputsPath)
},
isCurrentImageInputsPathDialog: {
get() {
return this.isCurrentImageInputsPath
},
set() {
this.currentImageInputsPath = null
}
},
chatContainer() { chatContainer() {
const container = this.$refs.chatContainer; const container = this.$refs.chatContainer;
if (this.useVoiceMode) { if (this.useVoiceMode) {
@ -896,26 +919,17 @@ export default {
this.$refs.attachment.click(); this.$refs.attachment.click();
}, },
/** optimizeImage(e,event,file) {
* Handle picked attachment let currentImageInput = {
*/
handlePickedAttachment(event) {
if (event.target.files && event.target.files[0]) {
var reader = new FileReader();
reader.onload = (e) => {
const file = event.target.files[0];
this.currentSendShowSendButton = true;
if (file.type.startsWith("image/")) {
this.currentImageInput = {
image: e.target.result, image: e.target.result,
dimensions: null, dimensions: null,
}; };
try { try {
this.currentImageInput.dimensions = sizeOf(dataUriToBuffer(e.target.result)); currentImageInput.dimensions = sizeOf(dataUriToBuffer(e.target.result));
// Need to resize? // Need to resize?
const w = this.currentImageInput.dimensions.width; const w = currentImageInput.dimensions.width;
const h = this.currentImageInput.dimensions.height; const h = currentImageInput.dimensions.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());
@ -930,16 +944,16 @@ export default {
.play(event.target) .play(event.target)
.then((img) => { .then((img) => {
Vue.set( Vue.set(
this.currentImageInput, currentImageInput,
"scaled", "scaled",
new File([img], file.name, { new File([img], file.name, {
type: img.type, type: img.type,
lastModified: Date.now(), lastModified: Date.now(),
}) })
); );
Vue.set(this.currentImageInput, "useScaled", true); Vue.set(currentImageInput, "useScaled", true);
Vue.set(this.currentImageInput, "scaledSize", img.size); Vue.set(currentImageInput, "scaledSize", img.size);
Vue.set(this.currentImageInput, "scaledDimensions", { Vue.set(currentImageInput, "scaledDimensions", {
width: newWidth, width: newWidth,
height: newHeight, height: newHeight,
}); });
@ -951,13 +965,28 @@ export default {
} catch (error) { } catch (error) {
console.error("Failed to get image dimensions: " + error); console.error("Failed to get image dimensions: " + error);
} }
return currentImageInput
},
handleFileReader(event, file) {
if (file) {
var reader = new FileReader();
reader.onload = (e) => {
this.currentSendShowSendButton = true;
if (file.type.startsWith("image/")) {
const currentImageInput = this.optimizeImage(e, event, file)
this.currentImageInputs = Array.isArray(this.currentImageInputs) ? [...this.currentImageInputs, currentImageInput] : [currentImageInput]
} }
console.log(this.currentImageInput); this.currentImageInputsPath = Array.isArray(this.currentImageInputsPath) ? [...this.currentImageInputsPath, file] : [file];
this.currentImageInputPath = file;
}; };
reader.readAsDataURL(event.target.files[0]); reader.readAsDataURL(file);
} }
}, },
/**
* Handle picked attachment
*/
handlePickedAttachment(event) {
Object.values(event.target.files).forEach(file => this.handleFileReader(event, file));
},
showStickerPicker() { showStickerPicker() {
this.$refs.stickerPickerSheet.open(); this.$refs.stickerPickerSheet.open();
@ -975,15 +1004,7 @@ export default {
}); });
} }
}, },
sendImage(withText, inputFile) {
sendAttachment(withText) {
this.$refs.attachment.value = null;
if (this.currentImageInputPath) {
var inputFile = this.currentImageInputPath;
if (this.currentImageInput && this.currentImageInput.scaled && this.currentImageInput.useScaled) {
// Send scaled version of image instead!
inputFile = this.currentImageInput.scaled;
}
this.currentSendProgress = null; this.currentSendProgress = null;
this.currentSendOperation = util.sendImage( this.currentSendOperation = util.sendImage(
this.$matrix.matrixClient, this.$matrix.matrixClient,
@ -994,8 +1015,8 @@ export default {
this.currentSendOperation this.currentSendOperation
.then(() => { .then(() => {
this.currentSendOperation = null; this.currentSendOperation = null;
this.currentImageInput = null; this.currentImageInputs = null;
this.currentImageInputPath = null; this.currentImageInputsPath = null;
this.currentSendProgress = null; this.currentSendProgress = null;
if (withText) { if (withText) {
this.sendMessage(withText); this.sendMessage(withText);
@ -1010,6 +1031,16 @@ export default {
this.currentSendOperation = null; this.currentSendOperation = null;
this.currentSendProgress = null; this.currentSendProgress = null;
}); });
},
sendAttachment(withText) {
this.$refs.attachment.value = null;
if (this.isCurrentImageInputsPath) {
let inputFiles = this.currentImageInputsPath;
if (Array.isArray(this.currentImageInputs) && this.currentImageInputs.scaled && this.currentImageInputs.useScaled) {
// Send scaled version of image instead!
inputFiles = this.currentImageInputs.map(({scaled}) => scaled)
}
inputFiles.forEach((inputFile) => this.sendImage(withText, inputFile))
} }
}, },
@ -1019,8 +1050,8 @@ export default {
this.currentSendOperation.abort(); this.currentSendOperation.abort();
} }
this.currentSendOperation = null; this.currentSendOperation = null;
this.currentImageInput = null; this.currentImageInputs = null;
this.currentImageInputPath = null; this.currentImageInputsPath = null;
this.currentSendProgress = null; this.currentSendProgress = null;
this.currentSendError = null; this.currentSendError = null;
}, },
@ -1399,8 +1430,12 @@ export default {
}, },
onVoiceRecording(event) { onVoiceRecording(event) {
console.log('voice..')
console.log(event)
console.log(event.file)
this.currentSendShowSendButton = false; this.currentSendShowSendButton = false;
this.currentImageInputPath = event.file; //this.currentImageInputsPath = event.file;
this.currentImageInputsPath = Array.isArray(this.currentImageInputsPath) ? [...this.currentImageInputsPath, event.file] : [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;