aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-14 18:00:19 -0700
committerAdam Soltys <[email protected]>2026-09-14 18:00:19 -0700
commitcb4e155ae6fb72282d5f186389d2ecca6db6a0f0 (patch)
tree4d00f5696f377ba73a4d76244a86f7fb5f56235e /src/features
parent082fc2e4005387697f77e485ae1c783ed3203e91 (diff)
downloadcoinosv3-cb4e155ae6fb72282d5f186389d2ecca6db6a0f0.tar.gz
coinosv3-cb4e155ae6fb72282d5f186389d2ecca6db6a0f0.zip
A remote signer that drops its socket comes back by itself.
"My signer keeps disconnecting": a phone freezing the tab cut the relay socket the bunker session talks through, every request after that hung to its deadline, and the app declared the signer gone — a Reconnect button, tapped over and over. Three changes: the bunker client now talks through a pool that pings and reconnects on its own, so a dropped socket is re-opened and the subscription re-fired without anyone noticing; a request that does fail on a dead connection drops the session and dials again silently, so the notice only appears if that resume fails; and coming back from the background probes the signer with a quick question, replacing a dead session before the next real request runs into it. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
Diffstat (limited to 'src/features')
-rw-r--r--src/features/nostrlogin.js23
1 files changed, 22 insertions, 1 deletions
diff --git a/src/features/nostrlogin.js b/src/features/nostrlogin.js
index 4d3fe50..503384f 100644
--- a/src/features/nostrlogin.js
+++ b/src/features/nostrlogin.js
@@ -67,7 +67,13 @@ export function nostrLoginFeature(ctx) {
if (!signer || signer.kind !== 'bunker') return signer;
const guard = (fn) => async (...args) => {
try { return await fn(...args); } catch (e) {
- if (live === wrapped && SIGNER_DEAD.test(e?.message || '')) live = null;
+ if (live === wrapped && SIGNER_DEAD.test(e?.message || '')) {
+ // drop it AND dial again, silently: the notice (and its Reconnect
+ // button) is for a resume that failed, not for every hiccup
+ live = null;
+ try { signer.close && signer.close(); } catch {}
+ resumeQuietly();
+ }
throw e;
}
};
@@ -701,6 +707,21 @@ export function nostrLoginFeature(ctx) {
// null for signers we cannot silently reattach (pasted keys, bunkers
// without a stored session).
nostrLoginResume() { return resumeLogin(); },
+ // Back from the background: a remote signer's socket may be gone even if
+ // the pool will bring it back — ask it something small now, and if the
+ // answer never comes, resume a fresh session before anyone notices.
+ resumed(awayMs) {
+ const s = liveSigner();
+ if (!s || s.kind !== 'bunker' || !s.ping) return;
+ if (awayMs && awayMs < 5_000) return;
+ s.ping().catch(() => {
+ if (live !== s) return;
+ live = null;
+ try { s.close && s.close(); } catch {}
+ resumeQuietly();
+ });
+ return true;
+ },
unlockExtra() { return unlockExtra(); },
// The welcome screen's sign-in block: Google and passkey act right there;
// the Nostr button steps into the wizard's signer list.