diff --git a/meshchat.py b/meshchat.py index 99714c4..3ed2e6a 100644 --- a/meshchat.py +++ b/meshchat.py @@ -1007,6 +1007,7 @@ class ReticulumMeshChat: # get query params aspect = request.query.get("aspect", None) identity_hash = request.query.get("identity_hash", None) + destination_hash = request.query.get("destination_hash", None) limit = request.query.get("limit", None) # build announces database query @@ -1020,6 +1021,10 @@ class ReticulumMeshChat: if identity_hash is not None: query = query.where(database.Announce.identity_hash == identity_hash) + # filter by provided destination hash + if destination_hash is not None: + query = query.where(database.Announce.destination_hash == destination_hash) + # limit results if limit is not None: query = query.limit(limit) diff --git a/src/frontend/components/messages/MessagesPage.vue b/src/frontend/components/messages/MessagesPage.vue index 0310fa4..4cba9f0 100644 --- a/src/frontend/components/messages/MessagesPage.vue +++ b/src/frontend/components/messages/MessagesPage.vue @@ -38,6 +38,9 @@ export default { ConversationViewer, MessagesSidebar, }, + props: { + destinationHash: String, + }, data() { return { @@ -76,6 +79,11 @@ export default { this.getConversations(); }, 5000); + // compose message if a destination hash was provided on page load + if(this.destinationHash){ + this.onComposeNewMessage(this.destinationHash); + } + }, methods: { async onComposeNewMessage(destinationHash) { @@ -93,6 +101,9 @@ export default { destinationHash = destinationHash.replace("lxmf@", ""); } + // fetch updated announce as we might be composing new message before we loaded the announces list + await this.getLxmfDeliveryAnnounce(destinationHash); + // attempt to find existing peer so we can show their name const existingPeer = this.peers[destinationHash]; if(existingPeer){ @@ -165,6 +176,28 @@ export default { console.log(e); } }, + async getLxmfDeliveryAnnounce(destinationHash) { + try { + + // fetch announce for destination hash + const response = await window.axios.get(`/api/v1/announces`, { + params: { + destination_hash: destinationHash, + limit: 1, + }, + }); + + // update ui + const lxmfDeliveryAnnounces = response.data.announces; + for(const lxmfDeliveryAnnounce of lxmfDeliveryAnnounces){ + this.updatePeerFromAnnounce(lxmfDeliveryAnnounce); + } + + } catch(e) { + // do nothing if failed to load announce + console.log(e); + } + }, async getConversations() { try { const response = await window.axios.get(`/api/v1/lxmf/conversations`); diff --git a/src/frontend/components/network-visualiser/NetworkVisualiser.vue b/src/frontend/components/network-visualiser/NetworkVisualiser.vue index 9f3f971..9836536 100644 --- a/src/frontend/components/network-visualiser/NetworkVisualiser.vue +++ b/src/frontend/components/network-visualiser/NetworkVisualiser.vue @@ -165,6 +165,47 @@ export default { }, }); + // handle double click on a node + this.network.on("doubleClick", (params) => { + + // get clicked node id + const clickedNodeId = params.nodes[0]; + if(!clickedNodeId){ + return; + } + + // find node by id + const node = this.network.body.nodes[clickedNodeId]; + if(!node){ + return; + } + + // handle double click on an announce node + if(node.options.group === "announce"){ + + // get announce + const announce = node.options._announce; + if(!announce) { + return; + } + + // handle double click on lxmf.delivery node + if(announce.aspect === "lxmf.delivery"){ + + // go to messages page for this destination hash + this.$router.push({ + name: "messages", + params: { + destinationHash: announce.destination_hash, + }, + }); + + } + + } + + }); + // update network await this.update(); @@ -358,6 +399,9 @@ export default { } + // attach announce to this node + node._announce = announce; + // add node nodes.push(node); diff --git a/src/frontend/main.js b/src/frontend/main.js index 3fdece6..664cf68 100644 --- a/src/frontend/main.js +++ b/src/frontend/main.js @@ -46,7 +46,8 @@ const router = createRouter({ }, { name: "messages", - path: '/messages', + path: '/messages/:destinationHash?', + props: true, component: defineAsyncComponent(() => import("./components/messages/MessagesPage.vue")), }, {