Skip to content

Commit

Permalink
implement unread message indicators
Browse files Browse the repository at this point in the history
  • Loading branch information
liamcottle committed Nov 18, 2024
1 parent 8a65174 commit 83d8f5c
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 3 deletions.
23 changes: 20 additions & 3 deletions src/components/messages/MessageViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export default {
data() {
return {
isActive: false,
messages: [],
messagesSubscription: null,
Expand All @@ -148,10 +149,15 @@ export default {
},
activated() {
this.isActive = true;
// update read state when coming back to message viewer
Database.NodeMessagesReadState.touch(this.nodeId);
this.updateMessagesLastReadAt();
},
deactivated() {
this.isActive = false;
},
methods: {
async sendMessage() {
Expand Down Expand Up @@ -229,7 +235,7 @@ export default {
this.scrollMessagesToBottom();
// update read state since we auto scrolled to bottom of new messages
Database.NodeMessagesReadState.touch(this.nodeId);
this.updateMessagesLastReadAt();
}
Expand All @@ -255,7 +261,7 @@ export default {
// update read state since we scrolled to bottom
if(isAtBottom){
Database.NodeMessagesReadState.touch(this.nodeId);
this.updateMessagesLastReadAt();
}
},
Expand All @@ -265,6 +271,17 @@ export default {
container.scrollTop = container.scrollHeight;
});
},
updateMessagesLastReadAt() {
// do nothing if route is not active
if(!this.isActive){
return;
}
// update last read at
Database.NodeMessagesReadState.touch(this.nodeId);
},
},
computed: {
Protobuf() {
Expand Down
37 changes: 37 additions & 0 deletions src/components/nodes/NodeListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@
</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>

<!-- our node battery level -->
<div v-if="node.num === GlobalState.myNodeId && node.deviceMetrics && node.deviceMetrics.batteryLevel != null" class="ml-1 my-auto flex text-gray-500">
<div class="my-auto text-sm">
Expand Down Expand Up @@ -110,6 +118,8 @@ import NodeDropDownMenu from "./NodeDropDownMenu.vue";
import GlobalState from "../../js/GlobalState.js";
import TimeUtils from "../../js/TimeUtils.js";
import moment from "moment";
import Database from "../../js/Database.js";
import Connection from "../../js/Connection.js";
export default {
name: 'NodeListItem',
Expand All @@ -120,6 +130,22 @@ export default {
props: {
node: Object,
},
data() {
return {
unreadMessagesCount: 0,
nodeMessagesReadStateSubscription: null,
};
},
mounted() {
Connection.addMessageListener(this.onMessage);
this.nodeMessagesReadStateSubscription = Database.NodeMessagesReadState.get(this.node.num).$.subscribe(async (nodeMessagesReadState) => {
await this.onNodeMessagesReadStateChange(nodeMessagesReadState);
});
},
unmounted() {
Connection.removeMessageListener(this.onMessage);
this.nodeMessagesReadStateSubscription?.unsubscribe();
},
methods: {
getNodeLongName: (nodeId) => NodeUtils.getNodeLongName(nodeId),
formatUnixSecondsAgo(unixSeconds) {
Expand All @@ -132,6 +158,17 @@ export default {
return "Unknown";
},
async onMessage() {
const nodeMessagesReadState = await Database.NodeMessagesReadState.get(this.node.num).exec();
await this.onNodeMessagesReadStateChange(nodeMessagesReadState);
},
async updateUnreadMessagesCount(lastReadTimestamp) {
this.unreadMessagesCount = await Database.Message.getNodeMessagesUnreadCount(this.node.num, lastReadTimestamp).exec();
},
async onNodeMessagesReadStateChange(nodeMessagesReadState) {
const messagesLastReadTimestamp = nodeMessagesReadState?.timestamp ?? 0;
await this.updateUnreadMessagesCount(messagesLastReadTimestamp);
},
},
computed: {
GlobalState() {
Expand Down
16 changes: 16 additions & 0 deletions src/js/Connection.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Database from "./Database.js";
class Connection {

static clientNotificationListeners = [];
static messageListeners = [];
static traceRouteListeners = [];

static addClientNotificationListener(listener) {
Expand All @@ -17,6 +18,16 @@ class Connection {
});
}

static addMessageListener(listener) {
this.messageListeners.push(listener);
}

static removeMessageListener(listenerToRemove) {
this.messageListeners = this.messageListeners.filter((listener) => {
return listener !== listenerToRemove;
});
}

static addTraceRouteListener(listener) {
this.traceRouteListeners.push(listener);
}
Expand Down Expand Up @@ -231,6 +242,11 @@ class Connection {
connection.events.onMessagePacket.subscribe(async (data) => {
console.log("onMessagePacket", data);
await Database.Message.insert(data);
for(const messageListener of this.messageListeners){
try {
messageListener(data);
} catch(e){}
}
});

// listen for device status changes
Expand Down
29 changes: 29 additions & 0 deletions src/js/Database.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ async function initDatabase(nodeId) {
database = await createRxDatabase({
name: `meshtxt_db_node_${nodeId}`,
storage: getRxStorageDexie(),
allowSlowCount: true, // fixme: figure out why rxdb complains about indexes when they existed during testing...
});

// add database schemas
Expand Down Expand Up @@ -265,6 +266,23 @@ class Message {
});
}

// get unread direct messages count for the provided node id
static getNodeMessagesUnreadCount(nodeId, messagesLastReadTimestamp) {
return database.messages.count({
selector: {
timestamp: {
$gt: messagesLastReadTimestamp,
},
from: {
$eq: nodeId,
},
to: {
$eq: GlobalState.myNodeId,
},
},
});
}

}

class TraceRoute {
Expand Down Expand Up @@ -340,6 +358,17 @@ class NodeMessagesReadState {
});
}

// get the read state of messages for the provided node id
static get(nodeId) {
return database.node_messages_read_state.findOne({
selector: {
id: {
$eq: nodeId.toString(),
},
},
});
}

}

export default {
Expand Down

0 comments on commit 83d8f5c

Please sign in to comment.