161 lines
No EOL
4.7 KiB
Vue
161 lines
No EOL
4.7 KiB
Vue
<template>
|
|
<message-incoming v-bind="{ ...$props, ...$attrs }" v-on="$listeners">
|
|
<div class="bubble">
|
|
<div class="original-message" v-if="inReplyToText">
|
|
<div class="original-message-sender">
|
|
{{ $t('message.user_said', {user: inReplyToSender || "Someone"}) }}
|
|
</div>
|
|
<div
|
|
class="original-message-text"
|
|
v-html="linkify($sanitize(inReplyToText))"
|
|
/>
|
|
</div>
|
|
<div class="message">
|
|
<v-container fluid class="imageCollection">
|
|
<v-row wrap>
|
|
<v-col v-for="({ size, item }) in layoutedItems()" :key="item.event.getId()" :cols="size">
|
|
<v-img :aspect-ratio="16 / 9" :src="item.src" cover @click.stop="dialogSrc = item.src; dialog = true" />
|
|
</v-col>
|
|
</v-row>
|
|
</v-container>
|
|
<div style="text-align: end">
|
|
<v-btn class="download-all-button" @click.stop="downloadAll">{{ $t("message.download_all") }} <v-icon
|
|
color="white">arrow_downward</v-icon></v-btn>
|
|
</div>
|
|
<i v-if="event.isRedacted()" class="deleted-text">
|
|
<v-icon :color="this.senderIsAdminOrModerator(this.event) ? 'white' : ''" size="small">block</v-icon>
|
|
{{ $t('message.incoming_message_deleted_text') }}
|
|
</i>
|
|
<span v-html="linkify($sanitize(messageText))" v-else />
|
|
<span class="edit-marker" v-if="event.replacingEventId() && !event.isRedacted()">
|
|
{{ $t('message.edited') }}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<v-dialog v-model="dialog" :width="$vuetify.breakpoint.smAndUp ? '940px' : '90%'">
|
|
<v-img style="background:white" :src="dialogSrc" />
|
|
</v-dialog>
|
|
</message-incoming>
|
|
</template>
|
|
|
|
<script>
|
|
import MessageIncoming from "./MessageIncoming.vue";
|
|
import messageMixin from "./messageMixin";
|
|
import util from "../../plugins/utils";
|
|
|
|
export default {
|
|
extends: MessageIncoming,
|
|
components: { MessageIncoming },
|
|
mixins: [messageMixin],
|
|
data() {
|
|
return {
|
|
items: [],
|
|
dialog: false,
|
|
dialogSrc: null,
|
|
thread: null,
|
|
}
|
|
},
|
|
mounted() {
|
|
this.thread = this.timelineSet.relations.getChildEventsForEvent(this.event.getId(), "m.thread", "m.room.message");
|
|
this.processThread();
|
|
},
|
|
beforeDestroy() {
|
|
this.thread = null;
|
|
},
|
|
watch: {
|
|
thread: {
|
|
handler(newValue, oldValue) {
|
|
if (oldValue) {
|
|
oldValue.off('Relations.add', this.onAddRelation);
|
|
}
|
|
if (newValue) {
|
|
newValue.on('Relations.add', this.onAddRelation);
|
|
}
|
|
this.processThread();
|
|
},
|
|
immediate: true
|
|
}
|
|
},
|
|
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() {
|
|
if (!this.items || this.items.length == 0) { return [] }
|
|
let array = this.items.slice(0);
|
|
let rows = []
|
|
while (array.length > 0) {
|
|
if (array.length >= 7) {
|
|
rows.push({ size: 6, item: array[0] });
|
|
rows.push({ size: 6, item: array[1] });
|
|
rows.push({ size: 12, item: array[2] });
|
|
rows.push({ size: 3, item: array[3] });
|
|
rows.push({ size: 3, item: array[4] });
|
|
rows.push({ size: 3, item: array[5] });
|
|
rows.push({ size: 3, item: array[6] });
|
|
array = array.slice(7);
|
|
} else if (array.length >= 3) {
|
|
rows.push({ size: 6, item: array[0] });
|
|
rows.push({ size: 6, item: array[1] });
|
|
rows.push({ size: 12, item: array[2] });
|
|
array = array.slice(3);
|
|
} else if (array.length >= 2) {
|
|
rows.push({ size: 6, item: array[0] });
|
|
rows.push({ size: 6, item: array[1] });
|
|
array = array.slice(2);
|
|
} else {
|
|
rows.push({ size: 12, item: array[0] });
|
|
array = array.slice(1);
|
|
}
|
|
}
|
|
return rows
|
|
},
|
|
downloadAll() {
|
|
this.items.forEach(item => util.download(this.$matrix.matrixClient, item.event));
|
|
}
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
@import "@/assets/css/chat.scss";
|
|
</style>
|
|
|
|
<style lang="scss" scoped>
|
|
.bubble {
|
|
width: 100%;
|
|
}
|
|
|
|
.imageCollection {
|
|
border-radius: 15px;
|
|
padding: 0;
|
|
overflow: hidden;
|
|
|
|
.row {
|
|
margin: -4px; // Compensate for column padding, so the border-radius above looks round!
|
|
padding: 0;
|
|
}
|
|
|
|
.col {
|
|
padding: 2px;
|
|
}
|
|
}
|
|
</style> |