// Renderer bridge for the Messages panel. // All hermes-* IPC returns { ok, ... } | { ok: false, err }. const { contextBridge, ipcRenderer } = require("electron"); contextBridge.exposeInMainWorld("hermes", { // Identity + relay state status: () => ipcRenderer.invoke("hermes-status"), canUseVault: () => ipcRenderer.invoke("hermes-can-use-vault"), init: (mnemonic) => ipcRenderer.invoke("hermes-init", { mnemonic }), initFromVault: () => ipcRenderer.invoke("hermes-init", { useVault: true }), close: () => ipcRenderer.invoke("hermes-close"), // Messages inbox: () => ipcRenderer.invoke("hermes-inbox"), send: (to, text) => ipcRenderer.invoke("hermes-send", { to, text }), markThreadRead: (peerPkHex, upToCreatedAt) => ipcRenderer.invoke("hermes-thread-mark-read", { peerPkHex, upToCreatedAt }), // Contacts (address book) contacts: { list: () => ipcRenderer.invoke("hermes-contacts-list"), add: (name, nickname) => ipcRenderer.invoke("hermes-contacts-add", { name, nickname }), update: (pkHex, patch) => ipcRenderer.invoke("hermes-contacts-update", { pkHex, patch }), remove: (pkHex) => ipcRenderer.invoke("hermes-contacts-remove", { pkHex }), // Opt-in import: opens an OS file-picker for a .vcf. Returns parsed // candidates for the renderer to preview; nothing is added without a // follow-up add() call per contact. Convenience only — the full add // flow (manual +) is never gated behind this. importPick: () => ipcRenderer.invoke("hermes-contacts-import-pick"), }, // Pushes: new decrypted message / relay status change. onMessage: (cb) => { const wrapped = (_e, msg) => cb(msg); ipcRenderer.on("hermes-message", wrapped); return () => ipcRenderer.removeListener("hermes-message", wrapped); }, onStatus: (cb) => { const wrapped = (_e, s) => cb(s); ipcRenderer.on("hermes-status-update", wrapped); return () => ipcRenderer.removeListener("hermes-status-update", wrapped); }, });