aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-16 00:12:02 -0700
committerAdam Soltys <[email protected]>2026-08-16 00:12:02 -0700
commitb3e3468579c7ea996cd8da6fa3cc4ff9004cfa32 (patch)
treeacbeb6c0e69a7cd6a9e59611e81769e387a7c077 /src/features
parent0f060c19156f7fec90ac5a5b3c6ef3fb8640e36c (diff)
downloadcoinosv3-b3e3468579c7ea996cd8da6fa3cc4ff9004cfa32.tar.gz
coinosv3-b3e3468579c7ea996cd8da6fa3cc4ff9004cfa32.zip
Chat stops blaming the signer for a locked door: a padlocked wallet says so plainly, with the unlock one tap away
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_014tE4U5nEjGTQy8PwYqamfv
Diffstat (limited to 'src/features')
-rw-r--r--src/features/messages.js25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index 9bc61eb..070c54e 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -153,6 +153,9 @@ export function messagesFeature(ctx) {
return pks;
};
const isMe = (pk) => myPubkeys().includes(pk);
+ // "No identity" while soft-locked means the keys left with the lock — say
+ // that, not "signer disconnected" (which reads as a nostr-login problem).
+ const noIdToast = () => toast(t(wallet.watchOnly ? 'msgLockedChat' : 'msgNoIdentity'));
// ---- shared runtime -----------------------------------------------------
@@ -372,7 +375,7 @@ export function messagesFeature(ctx) {
const text = (ui.msgDraft || '').trim();
if (!text || ui.msgSending) return;
const id = await identity();
- if (!id) { toast(t('msgNoIdentity')); return; }
+ if (!id) { noIdToast(); return; }
ui.msgSending = true;
render();
try {
@@ -422,7 +425,7 @@ export function messagesFeature(ctx) {
async function createCommunity(name) {
const id = await identity();
- if (!id) { toast(t('msgNoIdentity')); return; }
+ if (!id) { noIdToast(); return; }
name = name.trim().slice(0, 64);
if (!name) return;
const ownerSalt = bytesToHex(crypto.getRandomValues(new Uint8Array(32)));
@@ -498,7 +501,7 @@ export function messagesFeature(ctx) {
async function mintInviteLink(room) {
const id = await identity();
- if (!id) { toast(t('msgNoIdentity')); return null; }
+ if (!id) { noIdToast(); return null; }
const s = st();
const existing = s.invites[room.jm.community_id];
if (existing) return existing.url;
@@ -518,7 +521,7 @@ export function messagesFeature(ctx) {
const peer = parseNostrPubkey(input);
if (!peer) { toast(t('msgBadNpub')); return; }
const id = await identity();
- if (!id) { toast(t('msgNoIdentity')); return; }
+ if (!id) { noIdToast(); return; }
if (!(id.signer instanceof Uint8Array) && !id.signer.encryptTo) { toast(t('msgSignerNoDm')); return; }
const rumor = {
kind: 3313, pubkey: id.pubkey,
@@ -988,7 +991,7 @@ export function messagesFeature(ctx) {
const text = (ui.msgDraft || '').trim();
if (!text || ui.msgSending) return;
const id = await identity();
- if (!id) { toast(t('msgNoIdentity')); return; }
+ if (!id) { noIdToast(); return; }
if (!(id.signer instanceof Uint8Array) && !id.signer.encryptTo) { toast(t('msgSignerNoDm')); return; }
ui.msgSending = true;
render();
@@ -1426,7 +1429,7 @@ export function messagesFeature(ctx) {
async function saveProfile() {
const id = await identity();
- if (!id) { toast(t('msgNoIdentity')); return; }
+ if (!id) { noIdToast(); return; }
const e = ui.profEdit;
ui.profSaving = true;
render();
@@ -1764,6 +1767,11 @@ export function messagesFeature(ctx) {
// identity itself is still known — it's the ability to sign as it that's
// missing — so this offers to fetch it back rather than to log in again.
function signerNotice() {
+ if (wallet.watchOnly) {
+ return h('div', { class: 'row gap6 chat-signer-off', style: 'align-items:center' },
+ h('span', { class: 'small muted grow' }, '\u{1F512} ' + t('msgLockedChat')),
+ h('button', { class: 'btn-sm', onClick: () => { ui.justLocked = false; ui.screen = 'vault'; render(); } }, t('unlock')));
+ }
const id = hook('nostrLoginIdentity');
if (!id || id.signer) return null;
return h('div', { class: 'row gap6 chat-signer-off', style: 'align-items:center' },
@@ -1835,6 +1843,11 @@ export function messagesFeature(ctx) {
backBtn(() => { ui.chatOpen = false; render(); }),
h('h3', { style: 'margin:0' }, t('tabMessages'))));
+ // A locked wallet can't decrypt or sign — say so up top, where the rooms
+ // that quietly won't open are listed.
+ const lockedRow = signerNotice();
+ if (lockedRow && wallet.watchOnly) kids.push(lockedRow);
+
if (pendingLink) kids.push(linkInviteCard());
for (const [rid, inv] of pendingDirect) kids.push(directInviteCard(rid, inv));