Builds on the previous Hermes sessions (NIP-17 crypto + chipnet hermes.bch
+ Theseus Messages window) to turn the flat inbox into something usable.
main.js (hermes block):
- Persistent inbox per identity at
<userData>/hermes/<pkHex>/inbox.jsonl (append-only JSONL, replayed on
init). Read-state at <userData>/hermes/<pkHex>/read.json so unread
badges survive restarts.
- Address book at <userData>/hermes/contacts.json: list / add / update /
remove. hermes-contacts-add resolves .bch name OR npub OR hex pk,
canonicalises, writes.
- Reverse-resolve consults contacts first, chain second: a user-curated
nickname wins over the on-chain np lookup.
- hermes-send also records the outgoing message to the inbox so thread
view shows both sides (only when at least one relay accepted).
- Inbox messages carry direction + peerPkHex + peerName so the renderer
can group by thread without re-doing the pairing logic.
- --messages CLI flag opens the panel at launch (first instance via
whenReady, second-instance via handleLaunch) so the dev harness and
power users don't need Ctrl+Shift+M.
- Dev-only auto-init: THESEUS_HERMES_DEV_MNEMONIC env, gated on
THESEUS_USER_DATA so it refuses to touch a production profile.
- HERMES_INBOX_LIMIT raised 200 -> 2000 now that history actually sticks.
messages-preload.js:
- Adds hermes.contacts.{list, add, update, remove} and
hermes.markThreadRead; status + onMessage/onStatus unchanged.
messages.html:
- Replaces the flat inbox with a two-column layout: contact list (search
+ unread badges + last-message preview) on the left, selected thread
on the right with sender bubbles, timestamps, inline Enter-to-send
compose, remove-contact affordance.
- .bch suffix stripped from displayed names (TLD is noise in chat UI;
other TLDs stay as disambiguation).
- Mark-thread-read fires on open; vault-bind path kept intact.
38 lines
1.7 KiB
JavaScript
38 lines
1.7 KiB
JavaScript
// 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 }),
|
|
},
|
|
|
|
// 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);
|
|
},
|
|
});
|