Merge branch '158-message-show-message-receipts-seen-by' into 'dev'
Resolve "Message: Show message receipts (seen by)" See merge request keanuapp/keanuapp-weblite!181
This commit is contained in:
commit
235a235782
5 changed files with 139 additions and 2 deletions
|
|
@ -356,6 +356,40 @@ body {
|
||||||
.quick-reaction-container .emoji {
|
.quick-reaction-container .emoji {
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.seen-by-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
height: 16px;
|
||||||
|
.clickable {
|
||||||
|
display: flex;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
|
margin-top: 3px;
|
||||||
|
.more {
|
||||||
|
margin-right: 10px;
|
||||||
|
color: #444444;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.seen-by-user {
|
||||||
|
width: 16px !important;
|
||||||
|
height: 16px !important;
|
||||||
|
margin-left: -5px !important;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.list-enter-active,
|
||||||
|
.list-leave-active {
|
||||||
|
transition: all 1s;
|
||||||
|
}
|
||||||
|
.list-enter, .list-leave-to /* .list-leave-active below version 2.1.8 */ {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateX(24px);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.messageIn {
|
.messageIn {
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,8 @@
|
||||||
"outgoing_message_deleted_text": "You deleted this message.",
|
"outgoing_message_deleted_text": "You deleted this message.",
|
||||||
"incoming_message_deleted_text": "This message was deleted.",
|
"incoming_message_deleted_text": "This message was deleted.",
|
||||||
"not_allowed_to_send": "Only admins and moderators are allowed to send to the room",
|
"not_allowed_to_send": "Only admins and moderators are allowed to send to the room",
|
||||||
"reaction_count_more": "{reactionCount} more"
|
"reaction_count_more": "{reactionCount} more",
|
||||||
|
"seen_by": "Seen by no members | Seen by 1 member | Seen by {count} members"
|
||||||
},
|
},
|
||||||
"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",
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,17 @@
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</div>
|
</div>
|
||||||
<QuickReactions :event="event" :timelineSet="timelineSet" v-on="$listeners"/>
|
<QuickReactions :event="event" :timelineSet="timelineSet" v-on="$listeners"/>
|
||||||
|
<SeenBy :room="room" :event="event"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import SeenBy from "./SeenBy.vue";
|
||||||
import messageMixin from "./messageMixin";
|
import messageMixin from "./messageMixin";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [messageMixin],
|
mixins: [messageMixin],
|
||||||
|
components: { SeenBy }
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,14 +25,17 @@
|
||||||
<span v-else class="white--text headline">{{ userAvatarLetter }}</span>
|
<span v-else class="white--text headline">{{ userAvatarLetter }}</span>
|
||||||
</v-avatar>
|
</v-avatar>
|
||||||
<QuickReactions :event="event" :timelineSet="timelineSet" v-on="$listeners"/>
|
<QuickReactions :event="event" :timelineSet="timelineSet" v-on="$listeners"/>
|
||||||
|
<SeenBy :room="room" :event="event"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import SeenBy from "./SeenBy.vue";
|
||||||
import messageMixin from "./messageMixin";
|
import messageMixin from "./messageMixin";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [messageMixin],
|
mixins: [messageMixin],
|
||||||
|
components: { SeenBy }
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
|
||||||
96
src/components/messages/SeenBy.vue
Normal file
96
src/components/messages/SeenBy.vue
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
<template>
|
||||||
|
<div class="seen-by-container">
|
||||||
|
<v-tooltip top open-delay="500">
|
||||||
|
<template v-slot:activator="{ on, attrs }">
|
||||||
|
<div v-bind="attrs" v-on="on" class="clickable">
|
||||||
|
<div class="more" v-if="seenBy.length > 0">{{ moreItems }}</div>
|
||||||
|
<transition-group name="list" tag="div" v-if="seenBy.length > 0">
|
||||||
|
<v-avatar v-for="(member, index) in seenBy" :key="member.userId" class="seen-by-user" size="16" color="grey"
|
||||||
|
v-show="index < SHOW_LIMIT">
|
||||||
|
<img v-if="memberAvatar(member)" :src="memberAvatar(member)" />
|
||||||
|
<span v-else class="white--text headline">{{
|
||||||
|
member.name.substring(0, 1).toUpperCase()
|
||||||
|
}}</span>
|
||||||
|
</v-avatar>
|
||||||
|
</transition-group>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<span>{{ $tc("message.seen_by", seenBy.length) }}</span>
|
||||||
|
</v-tooltip>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
room: {
|
||||||
|
type: Object,
|
||||||
|
default: function () {
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
event: {
|
||||||
|
type: Object,
|
||||||
|
default: function () {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
seenBy: [],
|
||||||
|
SHOW_LIMIT: 5,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.update();
|
||||||
|
if (this.room) {
|
||||||
|
this.room.on("Room.receipt", this.onReceipt);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
if (this.room) {
|
||||||
|
this.room.off("Room.receipt", this.onReceipt);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
moreItems() {
|
||||||
|
if (this.seenBy.length > this.SHOW_LIMIT) {
|
||||||
|
return `+${this.seenBy.length - this.SHOW_LIMIT}`;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onReceipt(ignoredevent) {
|
||||||
|
this.update();
|
||||||
|
},
|
||||||
|
memberAvatar(member) {
|
||||||
|
if (member) {
|
||||||
|
return member.getAvatarUrl(
|
||||||
|
this.$matrix.matrixClient.getHomeserverUrl(),
|
||||||
|
16,
|
||||||
|
16,
|
||||||
|
"scale",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
update() {
|
||||||
|
this.seenBy = ((this.room && this.event) ? this.room.getReceiptsForEvent(this.event) : [])
|
||||||
|
.filter(receipt => receipt.type == 'm.read' && receipt.userId !== this.$matrix.currentUserId)
|
||||||
|
.map(receipt => this.room.getMember(receipt.userId));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
event() {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "@/assets/css/chat.scss";
|
||||||
|
</style>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue