aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/messages.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/features/messages.js')
-rw-r--r--src/features/messages.js40
1 files changed, 36 insertions, 4 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index 06371cf..597cb23 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -2898,11 +2898,28 @@ export function messagesFeature(ctx) {
// "nothing to wait for": counting those passes gave every wrap sealed to
// the login npub up after ~40 s with only the wallet key tried, and the
// wrap log then hid it from every later session (a phone kept 9 of 186
- // messages). An interactive signer (Amber) is live from the moment it
- // resumes and never decrypts here, so it counts as complete.
+ // messages). An interactive signer (Amber by intent) never decrypts here
+ // either, so it is incomplete too: counted as complete, every wrap sealed
+ // to the login npub was given up on the wallet key and logged as opened
+ // — an Amber user's threads held only what that device had sent.
function decryptorsComplete() {
const login = hook('nostrLoginIdentity');
- return !login || !!(login.signer && (login.signer.interactive || login.signer.decryptFrom));
+ return !login || !!(login.signer && !login.signer.interactive && login.signer.decryptFrom);
+ }
+ const interactiveLogin = () => { const l = hook('nostrLoginIdentity'); return !!(l && l.signer && l.signer.interactive); };
+ // Wraps logged while an interactive signer stood in for the login npub
+ // may be messages no key here ever tried. Once a signer that can decrypt
+ // takes over (Amber reconnected over NIP-46), the heal pass re-opens
+ // every wrap the relays still hold.
+ function noteSignerGap() {
+ const s = st();
+ if (interactiveLogin()) { if (!s.dmSignerGap) { s.dmSignerGap = true; save(s); } return; }
+ if (!s.dmSignerGap || !decryptorsComplete()) return;
+ delete s.dmSignerGap;
+ s.dmHeal = 0;
+ save(s);
+ wrapLog = null; healed.clear(); seenWraps.clear();
+ if (dmStarted) resubscribeStreams();
}
// Raw-key unwraps (seed-derived / pasted nsec — the common case) run in
@@ -3055,6 +3072,7 @@ export function messagesFeature(ctx) {
const pks = dmSubKeys();
if (!pks.length) return;
dmStarted = true;
+ if (interactiveLogin()) noteSignerGap();
loadSeenWraps();
// warm threads from the local cache. A self-thread of our own messages is
// the residue of the old sent-copy misthreading (each welcome DM landed
@@ -12140,6 +12158,17 @@ export function messagesFeature(ctx) {
}, ui.msgReconnecting ? h('span', { class: 'spinner sm' }) : t('msgReconnect')));
}
+ // Amber by intent signs, but each decrypt would be a trip through the app,
+ // so nothing sent TO the login npub is opened here — a thread shows only
+ // what this device sent. Amber also speaks NIP-46; connected that way it
+ // decrypts quietly, and the messages held back open.
+ function amberDmNotice() {
+ if (wallet.watchOnly || !interactiveLogin()) return null;
+ return h('div', { class: 'row gap6 chat-signer-off', style: 'align-items:center' },
+ h('span', { class: 'small muted grow' }, t('msgAmberDms')),
+ h('button', { class: 'btn-sm', onClick: () => hook('nostrSignerUpgrade') }, t('msgAmberConnect')));
+ }
+
// Enter sends; Shift+Enter (the textarea's native edit) and Ctrl+J insert
// a newline. Height follows the text as it's typed — imperatively, since
// typing doesn't re-render — with rows as the re-render fallback.
@@ -12402,6 +12431,8 @@ export function messagesFeature(ctx) {
// that quietly won't open are listed.
const lockedRow = signerNotice();
if (lockedRow && wallet.watchOnly) kids.push(lockedRow);
+ const amberRow = amberDmNotice();
+ if (amberRow) kids.push(amberRow);
if (pendingLink && pendingLink.where !== 'communities') kids.push(linkInviteCard());
for (const [rid, inv] of pendingDirect) kids.push(directInviteCard(rid, inv));
@@ -13319,6 +13350,7 @@ export function messagesFeature(ctx) {
h('div', { class: 'chat-time' }, timeLabel(m.rumor.created_at * 1000)))))
: [h('div', { class: 'muted small', style: 'text-align:center;padding:24px 0' }, t('msgNoDmsYet'))])),
dmReplyBar(),
+ amberDmNotice(),
composer(t('msgDmPlaceholder'), () => sendDM(peer), null, 'dm:' + peer, (f) => sendDMFile(peer, f)),
ui.msgSheet ? dmSheet(peer) : null,
choice && ui.msgRoutePick ? routeSheet(peer, choice) : null);
@@ -13796,7 +13828,7 @@ export function messagesFeature(ctx) {
},
// nostr-login just connected or resumed a signer: wraps the backfill
// couldn't open a moment ago can be opened now — drain right away.
- nostrSignerLive() { scheduleDrain(0); },
+ nostrSignerLive() { noteSignerGap(); scheduleDrain(0); },
// Anyone (ark's history, other features) can open a profile or render a
// small clickable identity chip.
showProfile(pk) { openProfile(pk); return true; },