diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.js | 34 | ||||
| -rw-r--r-- | src/features/nwc.js | 15 |
2 files changed, 41 insertions, 8 deletions
@@ -5045,6 +5045,12 @@ const ctx = { parseAmount: (v, u) => parseAmount(v, u, rateNow()), worthLine, openImage: (src) => { ui.lightbox = src; render(); }, + // What woke this run, if anything did, and how to say we're finished. + // Both read through a closure: ctx is built before these are defined, and + // a bare `wakeDone` shorthand captured the binding while it was still + // undefined — the job then ran its full half minute every time. + wakePayload: () => WAKE_PAYLOAD, + wakeDone: () => wakeDone(), // "The next balance isn't a change, it's the first real value" — state // arriving late (the ark store opening past boot's patience) must not read // as money landing: without this the balance counts up from 0 in green, @@ -5124,6 +5130,23 @@ const ctx = { // BEFORE features construct: a nostr npub/nprofile rewrites itself onto the // existing /npub… profile deep link (which the messages feature reads at // construction); payment URIs stash for dispatch once a wallet is open. +// Woken by the Android wrapper (see android/, WakeJob): the wallet is being +// loaded off-screen to deal with something. The payload is read once, here, +// because whether anything CAN be done depends on whether a wallet opens at +// all — and if none does, the job should end straight away rather than hold +// a WebView open for half a minute over a locked wallet. +const WAKE_PAYLOAD = (() => { + try { + const w = new URLSearchParams(location.search).get('wake'); + if (w == null) return null; + history.replaceState(null, '', location.pathname || '/'); + return w; + } catch { return null; } +})(); +const wakeDone = () => { + try { if (WAKE_PAYLOAD != null && window.CoinosHost && window.CoinosHost.done) window.CoinosHost.done(); } catch {} +}; + const INTENT_URI = (() => { try { const u = new URLSearchParams(location.search).get('u'); @@ -5311,5 +5334,14 @@ loadLocale(getLang()).finally(async () => { const storeReady = featureHook('arkStoreReady'); if (storeReady) await storeReady; _bootDeciding = false; // from here on the screen is a decision, not a guess - if (!restoreAccountsState()) render(); + const opened = restoreAccountsState(); + if (!opened) render(); + if (WAKE_PAYLOAD != null) { + // Nothing opened — a locked vault, or no wallet on this device. There is + // nothing to answer with, so say so now. + if (!opened) wakeDone(); + // And a backstop: a wallet that opened but has no feature interested in + // this payload must still end the job. + else setTimeout(wakeDone, 40_000); + } }); diff --git a/src/features/nwc.js b/src/features/nwc.js index cefeb31..2cb9d81 100644 --- a/src/features/nwc.js +++ b/src/features/nwc.js @@ -803,16 +803,17 @@ export function nwcFeature(ctx) { // service can stop rather than sit there costing battery. A cap, because // "finished" is not always reachable: the relay may have nothing for us. function serveWake() { - let payload = null; - try { payload = new URLSearchParams(location.search).get('wake'); } catch {} + const payload = ctx.wakePayload ? ctx.wakePayload() : null; if (payload == null) return; - try { history.replaceState(null, '', location.pathname || '/'); } catch {} - const host = typeof window !== 'undefined' && window.CoinosHost; + if (!ctx.wakeDone) return; + let settled = false; + const finish = () => { if (settled) return; settled = true; ctx.wakeDone(); }; + // No connections means nothing here could have been asked of us: end the + // job now rather than hold a WebView open for half a minute on the + // strength of a payload we can't act on. + if (!conns().length) { finish(); return; } listen(); // the request is on a relay; this is what hears it reconcileBg(); // and make sure the pouch behind it is current - if (!host || typeof host.done !== 'function') return; - let settled = false; - const finish = () => { if (settled) return; settled = true; try { host.done(); } catch {} }; // an answer published is the signal we were woken for const stop = onAnswered(() => setTimeout(finish, 1500)); setTimeout(() => { try { stop(); } catch {} finish(); }, 25_000); |
