Skip to content

feat(pwa): wire offline payment queueing into send flow, fix install/sync bugs - #647

Open
TheWeirdDee wants to merge 1 commit into
FinChippay:mainfrom
TheWeirdDee:feat/pwa-install-prompt-offline-ui
Open

feat(pwa): wire offline payment queueing into send flow, fix install/sync bugs#647
TheWeirdDee wants to merge 1 commit into
FinChippay:mainfrom
TheWeirdDee:feat/pwa-install-prompt-offline-ui

Conversation

@TheWeirdDee

@TheWeirdDee TheWeirdDee commented Aug 16, 2026

Copy link
Copy Markdown

Summary

Closes #388.

This repo's main already carries PWA install-prompt and offline-queue infrastructure merged from earlier issues (#380, #358, #24) — InstallPrompt.tsx, lib/offlineQueue.ts, lib/cacheData.ts, and hooks/useNetworkStatus.ts all predate this PR. What was still missing against #388's acceptance criteria was wiring that infrastructure into the actual payment flow and fixing a few bugs left over from that work:

  • SendPaymentForm now actually calls queueTransaction() when a signed payment is submitted while offline, instead of just letting the submission fail.
  • dashboard.tsx balance fetch now reads/writes through cacheData.ts (IndexedDB) in addition to the existing localStorage snapshot, so the offline banner has a real synced timestamp to show.
  • New QueueSyncNotifier component toasts the result of each queued transaction once connectivity returns and the queue drains (success/failure per payment), listening both to the in-page processQueue() path and the service worker's QUEUE_PROCESSED message.
  • InstallPrompt's install-event tracking previously dispatched a CustomEvent with no listener anywhere, so "installation events are tracked" wasn't actually true — now routed through the app's existing Plausible-based analytics convention (matches lib/onboardingState.ts's trackOnboardingEvent).
  • OfflineBanner now consumes the useNetworkStatus hook (previously created per spec but never imported anywhere) instead of duplicating its own online/offline listeners.
  • Fixed a queue-processing race: _app.tsx was calling attachOnlineListener() on mount, which registers a second online listener that independently calls processQueue(). Since OfflineBanner (mounted app-wide) already reacts to the same event via Background Sync or its own processQueue() fallback, two listeners could race against the same IndexedDB queue on reconnect — in the worst case double-submitting a queued payment, or causing a successful submission to get mislabeled "failed" when the losing racer's resubmission is rejected by Horizon for a stale sequence number. Removed the redundant call; OfflineBanner already owns this correctly.
  • Service worker is now registered unconditionally on app load (_app.tsx) rather than only on-demand via the push-notification opt-in flow, so install eligibility and offline caching are available from first load.

Test plan

  • npx tsc --noEmit — no new errors introduced (diffed against clean main baseline; all remaining errors are pre-existing and unrelated)
  • npx eslint on all touched files — clean
  • __tests__/offlineQueue.test.ts — passes (one attachOnlineListener test is flaky on clean main too, unrelated to this change)
  • Manual verification of install prompt / offline banner / queue sync UI in a browser (not run in this environment)

…bugs

Builds on the PWA install-prompt and offline-queue infrastructure already
merged from earlier issues (FinChippay#380, FinChippay#358, FinChippay#24) by closing the remaining gaps
called out in FinChippay#388:

- SendPaymentForm now actually queues a signed payment via offlineQueue
  when submitted while offline, instead of just failing.
- Dashboard balance fetch now reads/writes through cacheData.ts (IndexedDB)
  so the offline snapshot has a real synced timestamp, in addition to the
  existing localStorage fallback.
- New QueueSyncNotifier component toasts the result of each queued
  transaction once connectivity returns and the queue drains.
- InstallPrompt's install-event tracking now actually reports through the
  app's existing Plausible-based analytics convention (lib/onboardingState.ts)
  instead of dispatching a CustomEvent with no listener.
- OfflineBanner now consumes the (previously unused) useNetworkStatus hook
  instead of duplicating its own online/offline listeners.
- Removed a redundant attachOnlineListener() call in _app.tsx that raced
  OfflineBanner's own online-transition handler against the same IndexedDB
  queue on every reconnect, which could double-submit a queued payment or
  cause a successful submission to be mislabeled "failed".
- Service worker is now registered unconditionally on app load so install
  eligibility and offline caching are available before any user opts into
  push notifications.

Closes FinChippay#388
@TheWeirdDee

Copy link
Copy Markdown
Author

Closing — opened with unwanted AI-attribution text in the description that the author did not approve.

@TheWeirdDee TheWeirdDee reopened this Aug 17, 2026
@github-actions github-actions Bot added the needs-review PR ready for Greptile AI code review label Aug 17, 2026
@github-actions

Copy link
Copy Markdown

🤖 Greptile AI Code Review

Greptile will automatically review this PR (8 file(s) changed).

Review gates:

  • ✅ CodeQL Security Scan
  • ✅ Custom rules (.greptile/config.json)
  • ✅ Architecture guidelines (.greptile/rules.md)

To manually trigger a re-review, comment @greptileai on this PR.
To skip review, add the skip-review label.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review PR ready for Greptile AI code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[New] Progressive Web App Install Prompt and Offline-Ready UI

1 participant