theseus/messages-preload.js
Local Dev 8eae448dde Hermes: Ermis shortcut (Ctrl+Shift+E), sidebar add-on, vCard import, brand kit
Shortcut: Ctrl+Shift+M -> Ctrl+Shift+E. Chrome owns Ctrl+Shift+M as
'switch profile' and E matches the Greek spelling (Ermis).

Sidebar discoverability: new bundled add-on at bundled-addons/hermes/
registers a left-strip icon + launcher panel. The panel is a thin chrome
(mark + 'Open Messages' + shortcut hint) that forwards clicks through
api.onMessage -> ipcMain.emit('hermes-open-request') -> openHermesWindow.
All real messaging code stays in main.js — add-on is purely for discovery.

Address book: opt-in vCard (.vcf) import. Dialog in the Add Contact modal
lets the user pick a file; main.js parses BEGIN:VCARD blocks for X-BNS-NAME
/ X-NOSTR-NPUB / X-NOSTR-PUBKEY plus .bch names and npubs mentioned in
NOTE fields. Candidates are previewed per-contact with checkboxes; nothing
is added until the user confirms. Non-matching vCards are returned too (so
the user can still add manually) rather than silently dropped. Nothing is
uploaded; parsing is local.

site/hermes: status badge flipped from 'designed - not yet built' to
'MVP - desktop'. New 'What ships today' grid covers threaded chat, send by
name, address book, local history (all live) and mobile + Tor (next /
planned). Hero carries the new Ctrl+Shift+E shortcut and a link to
/hermes/branding.

site/hermes/branding: new page. Mark SVG (winged envelope, two variants
for 16-20px and 24-160px display sizes), palette (reuses Silent Mode
tokens + an amber accent that's distinctly warm-yellow, not Hermes-orange
— so it never collides with Hermès the fashion house), name explanation
(English Hermes / Greek Ermis), voice notes, do/don't table, MPL-2.0
attribution.

Hermes/MOBILE-RECOMMENDATION.md: analysis of three mobile paths (inside
Ariadne / standalone / hybrid). Recommendation is Option 1: ship as a
screen inside Ariadne. Reuses the wallet seed, aligns with the design
doc's 'one seed many purposes' architecture, lowest total cost.
2026-10-21 00:45:25 +03:00

43 lines
2 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 }),
// 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);
},
});