Send authors: ['$contacts'] in the nostr-push subscription filter
when onlyFollowing is enabled. The nostr-push server resolves this
macro to the user's kind 3 follow list. Toggling the setting off
removes the authors filter so all notifications are delivered again.
Disabled notification types (e.g. reactions) still triggered push
notifications and showed the unread dot indicator, even though the
notification tab correctly filtered them out.
Three root causes fixed:
- useHasUnreadNotifications now uses getEnabledNotificationKinds to
only query for enabled types, preventing phantom unread dots
- NotificationSettings now syncs type preference changes to the
nostr-push server via updateSubscription (is_active toggle)
- Native Android poller now receives enabled kinds from the JS layer
and uses them in the relay filter instead of hardcoded kinds
Browsers (especially Safari/Firefox) require pushManager.subscribe() to be
synchronously reachable from a user gesture. The previous code awaited a
getVapidKey() network call inside enable(), which broke the activation chain
and threw 'DOMException: The operation is insecure'.
Fix: fetch and cache the VAPID key during SW registration on mount so it is
ready in vapidKeyRef before the user ever clicks Enable, making
pushManager.subscribe() the first async call after the user gesture.
- Remove redundant Notification.requestPermission() from enable() since
the caller (NotificationSettings) already handles it from the user gesture.
On iOS this second call could behave unexpectedly.
- Add console.debug logging throughout the enable flow and RPC send for
diagnosing push registration issues in production.
- NotificationSettings: on web, drive the push toggle from the hook's
enabled state (actual browser subscription) instead of the NIP-78
notificationsEnabled setting which can be stale across devices.
NIP-78 is still used for the Capacitor/Android path.
- useNativeNotifications: remove the web push auto-disable effect that
raced against encrypted settings loading, causing disablePush() on
every page load before settings resolved.
- usePushNotifications: remove REGISTERED_KEY localStorage check from
the mount restore logic; derive enabled purely from
pushManager.getSubscription() like the working Ghastly reference.
Remove dead REGISTERED_KEY code entirely.
Replace the browser Notification constructor (tab-must-be-open) with nostr-push
Web Push notifications that work even when the browser is closed.
- Add service worker (public/sw.js) for receiving and displaying push events
- Add nostr-push RPC client (src/lib/nostrPush.ts) using an ephemeral device
keypair for signing — the user's Nostr signer is never prompted
- Add usePushNotifications hook managing the full lifecycle: SW registration,
VAPID key fetch, pushManager.subscribe, and nostr-push registration
- Replace the web path in useNativeNotifications with push registration that
auto-enables/disables based on the notificationsEnabled encrypted setting
- Android native Capacitor path is unchanged
- Requires VITE_NOSTR_PUSH_PUBKEY env var (hex pubkey of the nostr-push server)