diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py index 7be3946..a6b9107 100644 --- a/meshchatx/meshchat.py +++ b/meshchatx/meshchat.py @@ -3040,6 +3040,7 @@ class ReticulumMeshChat: "is_speaker_muted": self.telephone_manager.telephone.receive_muted, "is_voicemail": self.voicemail_manager.is_recording, "call_start_time": self.telephone_manager.call_start_time, + "is_contact": bool(self.database.contacts.get_contact_by_identity_hash(remote_identity_hash)) if remote_identity_hash else False, } return web.json_response( @@ -3150,6 +3151,7 @@ class ReticulumMeshChat: icon = self.database.misc.get_user_icon(lxmf_hash) if icon: d["remote_icon"] = dict(icon) + d["is_contact"] = bool(self.database.contacts.get_contact_by_identity_hash(remote_identity_hash)) call_history.append(d) return web.json_response( @@ -3631,6 +3633,12 @@ class ReticulumMeshChat: self.database.contacts.delete_contact(contact_id) return web.json_response({"message": "Contact deleted"}) + @routes.get("/api/v1/telephone/contacts/check/{identity_hash}") + async def telephone_contacts_check(request): + identity_hash = request.match_info["identity_hash"] + contact = self.database.contacts.get_contact_by_identity_hash(identity_hash) + return web.json_response({"is_contact": contact is not None, "contact": dict(contact) if contact else None}) + # announce @routes.get("/api/v1/announce") async def announce_trigger(request): diff --git a/meshchatx/src/backend/database/contacts.py b/meshchatx/src/backend/database/contacts.py index 5c216af..8b145ac 100644 --- a/meshchatx/src/backend/database/contacts.py +++ b/meshchatx/src/backend/database/contacts.py @@ -58,3 +58,9 @@ class ContactsDAO: def delete_contact(self, contact_id): self.provider.execute("DELETE FROM contacts WHERE id = ?", (contact_id,)) + def get_contact_by_identity_hash(self, remote_identity_hash): + return self.provider.fetchone( + "SELECT * FROM contacts WHERE remote_identity_hash = ?", + (remote_identity_hash,), + ) + diff --git a/meshchatx/src/frontend/components/call/CallOverlay.vue b/meshchatx/src/frontend/components/call/CallOverlay.vue index e62bc34..47ebc98 100644 --- a/meshchatx/src/frontend/components/call/CallOverlay.vue +++ b/meshchatx/src/frontend/components/call/CallOverlay.vue @@ -69,6 +69,12 @@
{{ activeCall.remote_identity_name || $t("call.unknown") }}
+
+ In contacts +
{{ activeCall.remote_identity_hash diff --git a/meshchatx/src/frontend/components/call/CallPage.vue b/meshchatx/src/frontend/components/call/CallPage.vue index 96e1177..b282b71 100644 --- a/meshchatx/src/frontend/components/call/CallPage.vue +++ b/meshchatx/src/frontend/components/call/CallPage.vue @@ -100,6 +100,12 @@ }} {{ $t("call.unknown") }}
+
+ In contacts +
- +
+ + +
@@ -1212,6 +1229,21 @@ export default { console.log(e); } }, + async addContactFromHistory(entry) { + const name = prompt("Enter contact name:", entry.remote_identity_name || ""); + if (!name) return; + try { + await window.axios.post("/api/v1/telephone/contacts", { + name: name, + remote_identity_hash: entry.remote_identity_hash, + }); + ToastUtils.success("Contact added"); + this.getHistory(); + this.getContacts(); + } catch (e) { + ToastUtils.error(e.response?.data?.message || "Failed to add contact"); + } + }, async getHistory() { try { const response = await window.axios.get("/api/v1/telephone/history?limit=10");