implement unread messages count for channels

This commit is contained in:
liamcottle
2025-02-15 00:17:39 +13:00
parent 53142063c4
commit b8868c68e1
3 changed files with 104 additions and 3 deletions

View File

@@ -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>

View File

@@ -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);
}
},

View File

@@ -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,
};