[0.9.1] FORK_IA_UX: Fase 2 (invite) — invite a contact to a Karvan room by feed id over SSB

Reuses Oasis's own private-message invite pattern (like the industry module:
pmModel.sendMessage([feed], 'KARVAN_INVITE', '... -> /karvan/<id>')), so the invite
lands in the contact's inbox with a link — no new SSB code, no touching the SSB
startup. Joining a room by link adopts a local mirror (karvanModel.adoptRoom, the
id is the capability). Real-time cross-device signaling (media/text sync between
the two mirrors) is the remaining Fase 2 piece (muxrpc ephemeral), deferred.
Verified single-node: invite publishes to the inbox, validation, adopt, form; 13/13
model tests (added adoptRoom).
This commit is contained in:
s1to 2026-08-07 20:27:45 +02:00
parent 813bf16958
commit af160dbd26
5 changed files with 81 additions and 4 deletions

View file

@ -101,7 +101,19 @@ exports.karvanRoomView = (room, messages, params = {}) =>
input({ type: "hidden", name: "from", value: params.selfId || "" }),
input({ type: "text", name: "text", id: "karvan-text", placeholder: i18n.karvanSay || "Temporary message…", maxlength: "2000", autocomplete: "off" }),
button({ type: "submit" }, i18n.karvanSend || "Send")
)
),
// Fase 2: invitar a un contacto por su feed id → le llega al inbox un enlace a esta sala
form({ class: "karvan-invite", method: "POST", action: "/karvan/" + room.id + "/invite" },
input({ type: "text", name: "to", placeholder: i18n.karvanInvitePlaceholder || "Invite a contact by @feed-id…", autocomplete: "off", spellcheck: "false" }),
button({ type: "submit" }, i18n.karvanInvite || "Invite")
),
params.invite === "ok"
? p({ class: "karvan-invite-msg ok" }, i18n.karvanInviteSent || "✓ Invitation sent to their inbox.")
: params.invite === "bad"
? p({ class: "karvan-invite-msg err" }, i18n.karvanInviteBad || "✗ That is not a valid @feed-id.")
: params.invite === "fail"
? p({ class: "karvan-invite-msg err" }, i18n.karvanInviteFail || "✗ Could not send the invitation.")
: ""
),
script({ src: "/js/karvan.js", defer: "defer" })
);