aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/ark.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-02 18:43:56 -0700
committerAdam Soltys <[email protected]>2026-08-02 18:43:56 -0700
commit375bec5f2ee22b1f69bb9f4a963efb12a68aef05 (patch)
tree3b8f3fe0c9c78a82996ad08375760c7281111fcb /src/features/ark.js
parent8da44392be513929802a5f4329b29bfa125aaa04 (diff)
downloadcoinosv3-375bec5f2ee22b1f69bb9f4a963efb12a68aef05.tar.gz
coinosv3-375bec5f2ee22b1f69bb9f4a963efb12a68aef05.zip
Profiles: view pages, editable own kind 0, zap recipients in history
Tapping any avatar or author name (chat rooms, DM threads, the chat home) opens a profile page: avatar, name, nip05, lightning address, about, npub, with Message and Pay actions (Pay runs the npub payment cascade). Your own profile — reachable from your avatar on the chat home — gets an editor for name, about, picture, and lightning address (prefilled with your coinos address); saving merges over the newest published kind 0 so fields we don't understand survive the round trip. Zaps now remember who they went to: the ark feature keys the recipient by what the movement already records (destination address or invoice) and history rows wear a clickable avatar chip that opens the profile. The messages feature exposes showProfile/profileChip seams so any feature can do the same. Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
Diffstat (limited to 'src/features/ark.js')
-rw-r--r--src/features/ark.js21
1 files changed, 20 insertions, 1 deletions
diff --git a/src/features/ark.js b/src/features/ark.js
index 3613b02..c81faa5 100644
--- a/src/features/ark.js
+++ b/src/features/ark.js
@@ -645,6 +645,7 @@ export function arkFeature(ctx) {
const settle = (a) => {
if (a.step === 'done') {
ui.arkLnPaid = { amountSat: a.amountSat, meta: p.meta };
+ if (p.meta && p.meta.pk) noteZap('inv:' + p.invoice, p.meta.pk);
ui.arkLnPay = null;
} else if (ui.arkLnPay) {
ui.arkLnPay.status = 'ready';
@@ -732,6 +733,22 @@ export function arkFeature(ctx) {
}
+ // Who a zap went to, keyed by what the movement records (the ark address
+ // for direct zaps, the invoice for Lightning ones) — enough to put a face
+ // on history rows without touching the manager's movement schema.
+ const zapNotes = () => wallet.loadFeatureState('zapnotes', {});
+ function noteZap(key, pk) {
+ const s = zapNotes();
+ s[key] = pk;
+ const keys = Object.keys(s);
+ if (keys.length > 200) for (const k of keys.slice(0, keys.length - 200)) delete s[k];
+ wallet.saveFeatureState('zapnotes', s);
+ }
+ const zapNoteFor = (m) =>
+ m.type === 'send' && m.to ? zapNotes()['to:' + m.to]
+ : m.type === 'ln-send' && m.invoice ? zapNotes()['inv:' + m.invoice]
+ : null;
+
function arkHistoryItem(m) {
const incoming = !['send', 'offboard', 'exit', 'ln-send'].includes(m.type);
const label = m.type === 'receive' ? t('received') : m.type === 'board' ? t('arkBoarded')
@@ -746,8 +763,9 @@ export function arkFeature(ctx) {
? h('div', { class: `ico ${incoming ? 'in' : 'out'}` }, '⚡')
: h('div', { class: `ico ${incoming ? 'in' : 'out'}`, html: ARK_MARK(15) }),
h('div', { class: 'grow' },
- h('div', { class: 'row gap6' },
+ h('div', { class: 'row gap6', style: 'align-items:center' },
label,
+ (() => { const pk = zapNoteFor(m); return pk ? ctx.hook('profileChip', pk) : null; })(),
m.status !== 'complete' ? h('span', { class: 'tag pending' }, m.status) : null),
h('div', { class: 'small faint' }, timeAgo(m.ts / 1000))),
h('div', { style: 'text-align:right' },
@@ -973,6 +991,7 @@ export function arkFeature(ctx) {
const action = mgr.state.actions.find((a) => a.id === actionId);
if (!action || action.step === 'failed') throw new Error(action?.error || t('claimFailed'));
const vtxoId = decodeVtxo(hex.decode((action.destBytesList || [action.destBytes])[0])).id;
+ noteZap('to:' + z.address, z.pk);
// the receipt is best-effort: the sats are already delivered via mailbox
await wallet.nostrPublish({
kind: ARK_ZAP_KIND,