mirror of
https://github.com/aljazceru/meshcore-web.git
synced 2025-12-17 08:14:19 +01:00
implement unread messages count for channels
This commit is contained in:
@@ -7,6 +7,14 @@
|
||||
<div class="text-sm text-gray-500">{{ channel.description }}</div>
|
||||
</div>
|
||||
|
||||
<!-- unread messages count -->
|
||||
<div v-if="unreadMessagesCount > 0" class="my-auto">
|
||||
<div class="inline-flex items-center justify-center w-6 h-6 text-xs font-bold text-white bg-red-500 rounded-full shadow">
|
||||
<span v-if="unreadMessagesCount >= 100">99</span>
|
||||
<span>{{ unreadMessagesCount }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- channel dropdown menu -->
|
||||
<div class="my-auto">
|
||||
<ChannelDropDownMenu :channel="channel"/>
|
||||
@@ -16,14 +24,51 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContactDropDownMenu from "../contacts/ContactDropDownMenu.vue";
|
||||
import ChannelDropDownMenu from "./ChannelDropDownMenu.vue";
|
||||
import Database from "../../js/Database.js";
|
||||
|
||||
export default {
|
||||
name: 'ChannelListItem',
|
||||
components: {ChannelDropDownMenu, ContactDropDownMenu},
|
||||
components: {ChannelDropDownMenu},
|
||||
props: {
|
||||
channel: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
unreadMessagesCount: 0,
|
||||
channelMessagesSubscription: null,
|
||||
channelMessagesReadStateSubscription: null,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
|
||||
// listen for new messages so we can update read state
|
||||
this.channelMessagesSubscription = Database.ChannelMessage.getChannelMessages(this.channel.idx).$.subscribe(async () => {
|
||||
await this.onMessagesUpdated();
|
||||
});
|
||||
|
||||
// listen for read state changes
|
||||
this.channelMessagesReadStateSubscription = Database.ChannelMessagesReadState.get(this.channel.idx).$.subscribe(async (channelMessagesReadState) => {
|
||||
await this.onChannelMessagesReadStateChange(channelMessagesReadState);
|
||||
});
|
||||
|
||||
},
|
||||
unmounted() {
|
||||
this.channelMessagesSubscription?.unsubscribe();
|
||||
this.channelMessagesReadStateSubscription?.unsubscribe();
|
||||
},
|
||||
methods: {
|
||||
async onMessagesUpdated() {
|
||||
const channelMessagesReadState = await Database.ChannelMessagesReadState.get(this.channel.idx).exec();
|
||||
await this.onChannelMessagesReadStateChange(channelMessagesReadState);
|
||||
},
|
||||
async updateUnreadMessagesCount(lastReadTimestamp) {
|
||||
this.unreadMessagesCount = await Database.ChannelMessage.getChannelMessagesUnreadCount(this.channel.idx, lastReadTimestamp).exec();
|
||||
},
|
||||
async onChannelMessagesReadStateChange(channelMessagesReadState) {
|
||||
const messagesLastReadTimestamp = channelMessagesReadState?.timestamp ?? 0;
|
||||
await this.updateUnreadMessagesCount(messagesLastReadTimestamp);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -283,9 +283,11 @@ export default {
|
||||
},
|
||||
updateMessagesLastReadAt() {
|
||||
|
||||
// update last read at for contact messages
|
||||
// update last read state for messages
|
||||
if(this.type === "contact"){
|
||||
Database.ContactMessagesReadState.touch(this.contact.publicKey);
|
||||
} else if(this.type === "channel"){
|
||||
Database.ChannelMessagesReadState.touch(this.channel.idx);
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
@@ -131,6 +131,22 @@ async function initDatabase(publicKeyHex) {
|
||||
},
|
||||
}
|
||||
},
|
||||
channel_messages_read_state: {
|
||||
schema: {
|
||||
version: 0,
|
||||
primaryKey: 'id',
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
maxLength: 36,
|
||||
},
|
||||
timestamp: {
|
||||
type: 'integer',
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
// database is now ready
|
||||
@@ -348,6 +364,20 @@ class ChannelMessage {
|
||||
});
|
||||
}
|
||||
|
||||
// get unread channel messages count for the provided channel idx
|
||||
static getChannelMessagesUnreadCount(channelIdx, messagesLastReadTimestamp) {
|
||||
return database.channel_messages.count({
|
||||
selector: {
|
||||
timestamp: {
|
||||
$gt: messagesLastReadTimestamp,
|
||||
},
|
||||
channel_idx: {
|
||||
$eq: channelIdx,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// delete channel messages for the provided channel idx
|
||||
static async deleteChannelMessages(channelIdx) {
|
||||
await this.getChannelMessages(channelIdx).remove();
|
||||
@@ -355,9 +385,33 @@ class ChannelMessage {
|
||||
|
||||
}
|
||||
|
||||
class ChannelMessagesReadState {
|
||||
|
||||
// update the read state of messages for the provided channel idx
|
||||
static async touch(channelIdx) {
|
||||
return await database.channel_messages_read_state.upsert({
|
||||
id: channelIdx.toString(),
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
}
|
||||
|
||||
// get the read state of messages for the provided channel idx
|
||||
static get(channelIdx) {
|
||||
return database.channel_messages_read_state.findOne({
|
||||
selector: {
|
||||
id: {
|
||||
$eq: channelIdx.toString(),
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
initDatabase,
|
||||
Message,
|
||||
ContactMessagesReadState,
|
||||
ChannelMessage,
|
||||
ChannelMessagesReadState,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user