keanu-weblite/src/components/messages/QuickReactions.vue

165 lines
No EOL
4.6 KiB
Vue

<template>
<div class="quick-reaction-container" v-show="reactions">
<div
class="emoji"
v-for="(value, name, index) in reactionMap"
:key="name"
v-show="showAllReaction || index < REACTION_LIMIT"
>
<v-tooltip location="top" v-if="value.includes($matrix.currentUserId)">
<template v-slot:activator="{ props }">
<v-chip
class="pa-2 ma-1 ml-0"
variant="outlined"
size="small"
v-bind="props"
@click="onClickEmoji(name)"
>
{{ name }} {{ value.length }}
</v-chip>
</template>
<span v-if="value.includes($matrix.currentUserId)">{{ $t("global.click_to_remove") }}</span>
</v-tooltip>
<v-chip
v-else
class="pa-2 ma-1 ml-0"
variant="outlined"
size="small"
>
{{ name }} {{ value.length }}
</v-chip>
</div>
<v-chip
v-if="totalReaction > REACTION_LIMIT"
@click="showAllReaction = !showAllReaction"
class="pa-2 ma-1 ml-0"
variant="outlined"
size="small"
>
{{ otherReactionText }}
</v-chip>
<v-tooltip location="top" v-if="!!totalReaction">
<template v-slot:activator="{ props }">
<v-chip
variant="outlined"
size="small"
class="pa-2 ma-1 ml-0"
v-bind="props"
@click="more"
>
<v-icon size="small"> $vuetify.icons.addReaction </v-icon>
</v-chip>
</template>
<span>{{ $t("global.add_reaction") }}</span>
</v-tooltip>
</div>
</template>
<script>
import messageOperationsMixin from "./messageOperationsMixin";
export default {
mixins: [messageOperationsMixin],
props: {
event: {
type: Object,
default: function () {
return {}
}
},
timelineSet: {
type: Object,
default: function () {
return null
}
},
},
data() {
return {
reactionMap: {},
reactions: null,
REACTION_LIMIT: 5,
showAllReaction: false
}
},
mounted() {
this.reactions = this.timelineSet.relations.getChildEventsForEvent(this.event.getId(), 'm.annotation', 'm.reaction');
this.event.on("Event.relationsCreated", this.onRelationsCreated);
},
beforeUnmount() {
this.event.off("Event.relationsCreated", this.onRelationsCreated);
if (this.reactions) {
this.reactions.off('Relations.add', this.onAddRelation);
}
},
computed: {
totalReaction() {
return Object.keys(this.reactionMap).length
},
otherReactionText() {
return this.showAllReaction ? this.$t("global.show_less") : this.$t("message.reaction_count_more", { reactionCount: this.totalReaction - this.REACTION_LIMIT })
}
},
methods: {
onRelationsCreated() {
this.reactions = this.timelineSet.relations.getChildEventsForEvent(this.event.getId(), 'm.annotation', 'm.reaction');
},
onClickEmoji(emoji) {
this.$emit('send-quick-reaction', {reaction:emoji, event:this.event});
},
onAddRelation(ignoredevent) {
this.processReactions();
},
onRemoveRelation(ignoredevent) {
this.processReactions();
},
onRedactRelation(ignoredevent) {
this.processReactions();
},
processReactions() {
var reactionMap = {};
if (this.reactions && this.reactions._eventsCount > 0) {
const relations = this.reactions.getRelations();
for (const r of relations) {
const emoji = r.getRelation().key;
const sender = r.getSender();
if (reactionMap[emoji]) {
const array = reactionMap[emoji];
if (r.isRedacted()) {
delete array[sender];
}
if (!array.includes(sender)) {
array.push(sender)
}
} else if (!r.isRedacted()) {
reactionMap[emoji] = [sender];
}
}
}
this.reactionMap = reactionMap;
}
},
watch: {
reactions: {
handler(newValue, oldValue) {
if (oldValue) {
oldValue.off('Relations.add', this.onAddRelation);
oldValue.off('Relations.remove', this.onRemoveRelation);
oldValue.off('Relations.redaction', this.onRedactRelation);
}
if (newValue) {
newValue.on('Relations.add', this.onAddRelation);
newValue.on('Relations.remove', this.onRemoveRelation);
newValue.on('Relations.redaction', this.onRedactRelation);
}
this.processReactions();
},
immediate: true
}
}
};
</script>
<style lang="scss">
@use "@/assets/css/chat.scss" as *;
</style>