aboutsummaryrefslogtreecommitdiffstats
path: root/src/features/messages.js
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-09-12 17:06:14 -0700
committerAdam Soltys <[email protected]>2026-09-12 17:06:14 -0700
commitce61a0f20a2c535e0c69f59836a17f31a3d88468 (patch)
treebc80738e4181af5bb8b3ca0844a16d52766c415a /src/features/messages.js
parent8fe3d0d28d5f15643c1737809c5f1773cb8f9f94 (diff)
downloadcoinosv3-ce61a0f20a2c535e0c69f59836a17f31a3d88468.tar.gz
coinosv3-ce61a0f20a2c535e0c69f59836a17f31a3d88468.zip
End to end over the real network, and the advice now fits the app it's in.
A push sent to ntfy.sh reached a killed app on a real phone: 17:02:21.259 ntfy.sh → the phone's ntfy → broadcast to io.coinos.webview 17:02:21.308 app process started (it had been killed) 17:02:21.458 wake: job started 17:02:22.926 wake: finishing (page said so) — 1.7s, and "You were paid" One thing that took two goes: `adb shell am force-stop` marks a package STOPPED, and Android delivers no broadcasts to a stopped package unless the sender sets FLAG_INCLUDE_STOPPED_PACKAGES — which `am broadcast` does and a real distributor rightly doesn't. The first attempt looked like a failure and was a test artefact; `am kill`, which is what Android itself does to a backgrounded app, delivers fine. And the WebView build can now say something useful about push. It was inheriting the browser's line — "your browser has no push service, try Firefox" — which is nonsense inside a WebView that IS the app. It asks the host what's actually there and says: install a push app like ntfy (nothing installed), or wait a moment and reopen (a distributor that hasn't answered yet). Payments and messages still arrive whenever coinos is open, which is the part that matters most to someone reading an apology. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
Diffstat (limited to 'src/features/messages.js')
-rw-r--r--src/features/messages.js26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/features/messages.js b/src/features/messages.js
index 9fbd19b..b153dba 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -1284,6 +1284,25 @@ export function messagesFeature(ctx) {
} catch {}
})();
+ // What to tell someone whose phone can't be woken. In a browser that's
+ // "your browser has no push service"; inside the UnifiedPush build of the
+ // Android app it's about the distributor, because that build IS the push —
+ // telling a WebView to go and use Firefox would be nonsense.
+ function pushAdvice() {
+ const env = hostEnv();
+ if (!env || env.app !== 'graphene') return t('nwcNoPushService');
+ if (!env.distributors) return t('upNoDistributor');
+ if (!env.endpoint) return t('upWaiting', { app: (env.distributor || '').split('.').pop() });
+ return t('nwcNoPushService');
+ }
+ function hostEnv() {
+ try {
+ const h2 = typeof window !== 'undefined' && window.CoinosHost;
+ if (!h2 || typeof h2.env !== 'function') return null;
+ return JSON.parse(h2.env());
+ } catch { return null; }
+ }
+
async function registerPush({ interactive = false } = {}) {
try {
// A UnifiedPush endpoint needs no permission and no push service: it's
@@ -4038,9 +4057,10 @@ export function messagesFeature(ctx) {
}, t('msgDismiss')))));
// A browser with no push service at all: the offer above is beside the
// point (permission may even be granted), so say what's actually wrong
- // wherever the user got to.
+ // wherever the user got to. Inside the Android build that carries its own
+ // push, the answer is a different one — see pushAdvice.
if (st().noPushService && !st().push)
- kids.push(h('div', { class: 'notice info small' }, t('nwcNoPushService')));
+ kids.push(h('div', { class: 'notice info small' }, pushAdvice()));
// ---- the feed, above the conversations: it's the thing you read, they're
// the things you answer
@@ -4548,6 +4568,8 @@ export function messagesFeature(ctx) {
// Also the way a zap sent from a form reaches the tally right away,
// without waiting on its receipt.
zapSettled(eventId, ok, sats) { settleZap(eventId, ok, sats); return true; },
+ // the right thing to say about push on THIS device, wherever it's asked
+ pushAdvice() { return pushAdvice(); },
// Chat lives behind a header button and takes over the whole screen —
// no balance card, no tabs; each view carries its own way back.
// The bare avatar node for the app header's identity menu.