diff --git a/src/assets/translations/en.json b/src/assets/translations/en.json
index d6d5f39..3e86316 100644
--- a/src/assets/translations/en.json
+++ b/src/assets/translations/en.json
@@ -90,7 +90,11 @@
"incoming_message_deleted_text": "This message was deleted.",
"not_allowed_to_send": "Only admins and moderators are allowed to send to the room",
"reaction_count_more": "{reactionCount} more",
- "seen_by": "Seen by no members | Seen by 1 member | Seen by {count} members"
+ "seen_by": "Seen by no members | Seen by 1 member | Seen by {count} members",
+ "file": "File",
+ "files": "Files",
+ "images": "Images",
+ "send_attachements_dialog_title": "Do you want to send following attachments ?"
},
"room": {
"invitations": "You have no invitations | You have 1 invitation | You have {count} invitations",
diff --git a/src/components/Chat.vue b/src/components/Chat.vue
index a068ebd..c2b3ffb 100644
--- a/src/components/Chat.vue
+++ b/src/components/Chat.vue
@@ -188,35 +188,52 @@
+ accept="image/*, audio/*, video/*, .pdf" class="d-none" multiple/>
-
-
+
+
-
-
-
- file: {{ currentImageInputPath.name }}
-
- {{ currentImageInput.scaledDimensions.width }} x {{ currentImageInput.scaledDimensions.height }}
-
- {{ currentImageInput.dimensions.width }} x {{ currentImageInput.dimensions.height }}
-
- ({{ formatBytes(currentImageInput.scaledSize) }})
- ({{ formatBytes(currentImageInputPath.size) }})
-
-
- {{ currentSendError }}
- {{ currentSendProgress }}
-
+ {{ $t('message.send_attachements_dialog_title') }}
+
+
+ {{ $t('message.images') }}
+
+
+
+
+
+ {{ currentImageInput.scaledDimensions.width }} x {{ currentImageInput.scaledDimensions.height }}
+
+ {{ currentImageInput.dimensions.width }} x {{ currentImageInput.dimensions.height }}
+
+ ({{ formatBytes(currentImageInput.scaledSize) }})
+
+
+
+
+
+
+ {{ $t('message.files') }}
+
+
+
+ {{ $t('message.file') }}: {{ currentImageInputPath.name }}
+ ({{ formatBytes(currentImageInputPath.size) }})
+
+
+
+
-
- {{
- $t("menu.cancel")
- }}
+
+ {{ currentSendError }}
+ {{ currentSendProgress }}
+
+
+ {{ $t("menu.cancel") }}
+
{{ $t("menu.send") }}
@@ -342,8 +359,8 @@ export default {
timelineWindowPaginating: false,
scrollPosition: null,
- currentImageInput: null,
- currentImageInputPath: null,
+ currentImageInputs: null,
+ currentFileInputs: null,
currentSendOperation: null,
currentSendProgress: null,
currentSendShowSendButton: true,
@@ -444,6 +461,20 @@ export default {
},
computed: {
+ nonImageFiles() {
+ return this.isCurrentFileInputsAnArray && this.currentFileInputs.filter(file => !file.type.includes("image/"))
+ },
+ isCurrentFileInputsAnArray() {
+ return Array.isArray(this.currentFileInputs)
+ },
+ currentFileInputsDialog: {
+ get() {
+ return this.isCurrentFileInputsAnArray
+ },
+ set() {
+ this.currentFileInputs = null
+ }
+ },
chatContainer() {
const container = this.$refs.chatContainer;
if (this.useVoiceMode) {
@@ -950,64 +981,64 @@ export default {
this.$refs.attachment.click();
},
- /**
- * Handle picked attachment
- */
- handlePickedAttachment(event) {
- if (event.target.files && event.target.files[0]) {
+ optimizeImage(e,event,file) {
+ let currentImageInput = {
+ image: e.target.result,
+ dimensions: null,
+ };
+ try {
+ currentImageInput.dimensions = sizeOf(dataUriToBuffer(e.target.result));
+
+ // Need to resize?
+ const w = currentImageInput.dimensions.width;
+ const h = currentImageInput.dimensions.height;
+ if (w > 640 || h > 640) {
+ var aspect = w / h;
+ var newWidth = parseInt((w > h ? 640 : 640 * aspect).toFixed());
+ var newHeight = parseInt((w > h ? 640 / aspect : 640).toFixed());
+ var imageResize = new ImageResize({
+ format: "png",
+ width: newWidth,
+ height: newHeight,
+ outputType: "blob",
+ });
+ imageResize
+ .play(event.target)
+ .then((img) => {
+ Vue.set(
+ currentImageInput,
+ "scaled",
+ new File([img], file.name, {
+ type: img.type,
+ lastModified: Date.now(),
+ })
+ );
+ Vue.set(currentImageInput, "useScaled", true);
+ Vue.set(currentImageInput, "scaledSize", img.size);
+ Vue.set(currentImageInput, "scaledDimensions", {
+ width: newWidth,
+ height: newHeight,
+ });
+ })
+ .catch((err) => {
+ console.error("Resize failed:", err);
+ });
+ }
+ } catch (error) {
+ console.error("Failed to get image dimensions: " + error);
+ }
+ return currentImageInput
+ },
+ handleFileReader(event, file) {
+ if (file) {
var reader = new FileReader();
reader.onload = (e) => {
- const file = event.target.files[0];
if (file.type.startsWith("image/")) {
- this.currentImageInput = {
- image: e.target.result,
- dimensions: null,
- };
- try {
- this.currentImageInput.dimensions = sizeOf(dataUriToBuffer(e.target.result));
-
- // Need to resize?
- const w = this.currentImageInput.dimensions.width;
- const h = this.currentImageInput.dimensions.height;
- if (w > 640 || h > 640) {
- var aspect = w / h;
- var newWidth = parseInt((w > h ? 640 : 640 * aspect).toFixed());
- var newHeight = parseInt((w > h ? 640 / aspect : 640).toFixed());
- var imageResize = new ImageResize({
- format: "png",
- width: newWidth,
- height: newHeight,
- outputType: "blob",
- });
- imageResize
- .play(event.target)
- .then((img) => {
- Vue.set(
- this.currentImageInput,
- "scaled",
- new File([img], file.name, {
- type: img.type,
- lastModified: Date.now(),
- })
- );
- Vue.set(this.currentImageInput, "useScaled", true);
- Vue.set(this.currentImageInput, "scaledSize", img.size);
- Vue.set(this.currentImageInput, "scaledDimensions", {
- width: newWidth,
- height: newHeight,
- });
- })
- .catch((err) => {
- console.error("Resize failed:", err);
- });
- }
- } catch (error) {
- console.error("Failed to get image dimensions: " + error);
- }
+ const currentImageInput = this.optimizeImage(e, event, file)
+ this.currentImageInputs = Array.isArray(this.currentImageInputs) ? [...this.currentImageInputs, currentImageInput] : [currentImageInput]
}
- console.log(this.currentImageInput);
this.$matrix.matrixClient.getMediaConfig().then((config) => {
- this.currentImageInputPath = file;
+ this.currentFileInputs = Array.isArray(this.currentFileInputs) ? [...this.currentFileInputs, file] : [file];
if (config["m.upload.size"] && file.size > config["m.upload.size"]) {
this.currentSendError = this.$t("message.upload_file_too_large");
this.currentSendShowSendButton = false;
@@ -1016,9 +1047,15 @@ export default {
}
});
};
- 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() {
this.$refs.stickerPickerSheet.open();
@@ -1036,41 +1073,35 @@ export default {
});
}
},
-
sendAttachment(withText) {
this.$refs.attachment.value = null;
- if (this.currentImageInputPath) {
- var inputFile = this.currentImageInputPath;
- if (this.currentImageInput && this.currentImageInput.scaled && this.currentImageInput.useScaled) {
+ if (this.isCurrentFileInputsAnArray) {
+ let inputFiles = this.currentFileInputs;
+ if (Array.isArray(this.currentImageInputs) && this.currentImageInputs.scaled && this.currentImageInputs.useScaled) {
// Send scaled version of image instead!
- inputFile = this.currentImageInput.scaled;
+ inputFiles = this.currentImageInputs.map(({scaled}) => scaled)
}
+
+ const promises = inputFiles.map(inputFile => util.sendImage(this.$matrix.matrixClient, this.roomId, inputFile, this.onUploadProgress));
+
+ Promise.all(promises).then(() => {
+ this.currentSendOperation = null;
+ this.currentImageInputs = null;
+ this.currentFileInputs = null;
this.currentSendProgress = null;
- this.currentSendOperation = util.sendImage(
- this.$matrix.matrixClient,
- this.roomId,
- inputFile,
- this.onUploadProgress
- );
- this.currentSendOperation
- .then(() => {
- this.currentSendOperation = null;
- this.currentImageInput = null;
- this.currentImageInputPath = null;
- this.currentSendProgress = null;
- if (withText) {
- this.sendMessage(withText);
- }
- })
- .catch((err) => {
- if (err.name === "AbortError" || err === "Abort") {
- this.currentSendError = null;
- } else {
- this.currentSendError = err.LocaleString();
- }
- this.currentSendOperation = null;
- this.currentSendProgress = null;
- });
+ if (withText) {
+ this.sendMessage(withText);
+ }
+ })
+ .catch((err) => {
+ if (err.name === "AbortError" || err === "Abort") {
+ this.currentSendError = null;
+ } else {
+ this.currentSendError = err.LocaleString();
+ }
+ this.currentSendOperation = null;
+ this.currentSendProgress = null;
+ });
}
},
@@ -1080,8 +1111,8 @@ export default {
this.currentSendOperation.abort();
}
this.currentSendOperation = null;
- this.currentImageInput = null;
- this.currentImageInputPath = null;
+ this.currentImageInputs = null;
+ this.currentFileInputs = null;
this.currentSendProgress = null;
this.currentSendError = null;
},
@@ -1461,7 +1492,7 @@ export default {
onVoiceRecording(event) {
this.currentSendShowSendButton = false;
- this.currentImageInputPath = event.file;
+ this.currentFileInputs = Array.isArray(this.currentFileInputs) ? [...this.currentFileInputs, event.file] : [event.file];
var text = undefined;
if (this.currentInput && this.currentInput.length > 0) {
text = this.currentInput;