Allow preview of thread images

This commit is contained in:
N Pex 2023-08-07 15:47:52 +00:00
parent e43b08dc64
commit 0ff2884429
5 changed files with 95 additions and 38 deletions

View file

@ -1532,3 +1532,17 @@ body {
bottom: 20px; bottom: 20px;
position: absolute; position: absolute;
} }
.download-all-button {
font-family: "Inter", sans-serif;
font-weight: 700;
font-size: 11.54 * $chat-text-size;
line-height: 140%;
color: white !important;
background-color: #4642f1 !important;
border-radius: $small-button-height / 2;
min-height: 0;
height: $small-button-height !important;
margin-top: $chat-standard-padding-xs;
margin-bottom: $chat-standard-padding-xs;
}

View file

@ -104,7 +104,8 @@
"file": "File", "file": "File",
"files": "Files", "files": "Files",
"images": "Images", "images": "Images",
"send_attachements_dialog_title": "Do you want to send following attachments ?" "send_attachements_dialog_title": "Do you want to send following attachments ?",
"download_all": "Download all"
}, },
"room": { "room": {
"invitations": "You have no invitations | You have 1 invitation | You have {count} invitations", "invitations": "You have no invitations | You have 1 invitation | You have {count} invitations",

View file

@ -1419,24 +1419,7 @@ export default {
}, },
download(event) { download(event) {
util util.download(this.$matrix.matrixClient, event);
.getAttachment(this.$matrix.matrixClient, event)
.then((url) => {
const link = document.createElement("a");
link.href = url;
link.target = "_blank";
link.download = event.getContent().body || this.$t("fallbacks.download_name");
document.body.appendChild(link);
link.click();
setTimeout(function () {
document.body.removeChild(link);
URL.revokeObjectURL(url);
}, 200);
})
.catch((err) => {
console.log("Failed to fetch attachment: ", err);
});
}, },
cancelEditReply() { cancelEditReply() {

View file

@ -5,10 +5,14 @@
<v-container fluid class="imageCollection"> <v-container fluid class="imageCollection">
<v-row wrap> <v-row wrap>
<v-col v-for="({ size, item }) in layoutedItems()" :key="item.event.getId()" :cols="size"> <v-col v-for="({ size, item }) in layoutedItems()" :key="item.event.getId()" :cols="size">
<v-img :aspect-ratio="16 / 9" :src="item.src" cover /> <v-img :aspect-ratio="16 / 9" :src="item.src" cover @click.stop="dialogSrc = item.src; dialog = true" />
</v-col> </v-col>
</v-row> </v-row>
</v-container> </v-container>
<div style="text-align: end">
<v-btn class="download-all-button" @click.stop="downloadAll">{{ $t("message.download_all") }}&nbsp;<v-icon
color="white">arrow_downward</v-icon></v-btn>
</div>
<i v-if="event.isRedacted()" class="deleted-text"> <i v-if="event.isRedacted()" class="deleted-text">
<v-icon :color="this.senderIsAdminOrModerator(this.event) ? 'white' : ''" size="small">block</v-icon> <v-icon :color="this.senderIsAdminOrModerator(this.event) ? 'white' : ''" size="small">block</v-icon>
{{ $t('message.incoming_message_deleted_text') }} {{ $t('message.incoming_message_deleted_text') }}
@ -19,6 +23,9 @@
</span> </span>
</div> </div>
</div> </div>
<v-dialog v-model="dialog" :width="$vuetify.breakpoint.smAndUp ? '940px' : '90%'">
<v-img style="background:white" :src="dialogSrc" />
</v-dialog>
</message-incoming> </message-incoming>
</template> </template>
@ -33,28 +40,55 @@ export default {
mixins: [messageMixin], mixins: [messageMixin],
data() { data() {
return { return {
items: [] items: [],
dialog: false,
dialogSrc: null,
thread: null,
} }
}, },
mounted() { mounted() {
this.items = this.timelineSet.relations.getAllChildEventsForEvent(this.event.getId()).map(e => { this.thread = this.timelineSet.relations.getChildEventsForEvent(this.event.getId(), "m.thread", "m.room.message");
let ret = { this.processThread();
event: e, },
src: null, beforeDestroy() {
}; this.thread = null;
ret.promise = },
util watch: {
.getThumbnail(this.$matrix.matrixClient, e, 100, 100) thread: {
.then((url) => { handler(newValue, oldValue) {
ret.src = url; if (oldValue) {
}) oldValue.off('Relations.add', this.onAddRelation);
.catch((err) => { }
console.log("Failed to fetch thumbnail: ", err); if (newValue) {
}); newValue.on('Relations.add', this.onAddRelation);
return ret; }
}) this.processThread();
},
immediate: true
}
}, },
methods: { methods: {
onAddRelation() {
this.processThread();
},
processThread() {
this.items = this.timelineSet.relations.getAllChildEventsForEvent(this.event.getId()).map(e => {
let ret = {
event: e,
src: null,
};
ret.promise =
util
.getThumbnail(this.$matrix.matrixClient, e, 100, 100)
.then((url) => {
ret.src = url;
})
.catch((err) => {
console.log("Failed to fetch thumbnail: ", err);
});
return ret;
});
},
layoutedItems() { layoutedItems() {
if (!this.items || this.items.length == 0) { return [] } if (!this.items || this.items.length == 0) { return [] }
let array = this.items.slice(0); let array = this.items.slice(0);
@ -84,6 +118,9 @@ export default {
} }
} }
return rows return rows
},
downloadAll() {
this.items.forEach(item => util.download(this.$matrix.matrixClient, item.event));
} }
} }
}; };
@ -94,7 +131,6 @@ export default {
</style> </style>
<style lang="scss" scoped> <style lang="scss" scoped>
.bubble { .bubble {
width: 100%; width: 100%;
} }
@ -103,10 +139,12 @@ export default {
border-radius: 15px; border-radius: 15px;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden;
.row { .row {
margin: -4px; // Compensate for column padding, so the border-radius above looks round! margin: -4px; // Compensate for column padding, so the border-radius above looks round!
padding: 0; padding: 0;
} }
.col { .col {
padding: 2px; padding: 2px;
} }

View file

@ -889,6 +889,27 @@ class Util {
}) })
}); });
} }
download(matrixClient, event) {
this
.getAttachment(matrixClient, event)
.then((url) => {
const link = document.createElement("a");
link.href = url;
link.target = "_blank";
link.download = event.getContent().body || this.$t("fallbacks.download_name");
document.body.appendChild(link);
link.click();
setTimeout(function () {
document.body.removeChild(link);
URL.revokeObjectURL(url);
}, 200);
})
.catch((err) => {
console.log("Failed to fetch attachment: ", err);
});
}
} }
export default new Util(); export default new Util();