Offers were one-way (buyer proposes, seller accepts/declines) and fixed-slot
addressable events, so the buyer could never counter back and the haggling left
no trace. Now it's a thread.
- useMarketplaceOffers: every message gets a UNIQUE d (append-only) with a
'role' tag (offer = buyer / response = seller), 'e' = the message it answers,
and status. New counterOffer() plus respondToOffer(previous, status). Parsing
still accepts the legacy fixed-slot d form when the role tag is absent.
- useListingOffers returns OfferThread[] (oldest first) with = whose
turn it is; useIncomingOffers returns the threads awaiting me (across listings).
- ListingOffersPanel: shows the volley, and accept/decline/counter (inline amount)
for whichever side's turn it is, with withdraw on your own open offer. Counter
notifications are nudged over DM too.
- New useTradeNotifications: incoming offers, counters and 'confirm our trade'
requests, derived from events already addressed to the user.
- Bell: trade items render first in All and count toward the badge (vs seenAt).
- OS notifications: new 'trades' category in notificationPrefs + a trades source
in OsNotificationBridge.
- NIP.md updated for the thread model (legacy form documented).
An OS alarm an hour before each upcoming event the user RSVP'd going or
interested to. Because the OS holds the alarm it fires with the app fully
closed — the only closed-app notification achievable without a server.
- src/lib/reminders.ts: schedule/cancel via @capacitor/local-notifications,
tracking handed-out ids in localStorage so withdrawn RSVPs and passed events
are cancelled without disturbing one-off notifications. Web is a no-op.
- src/hooks/useLocalReminders.ts: reuses the existing upcoming-events and
my-RSVPs queries; no new relay destination, no signing.
- Bridge mounts the hook only on native and only when the new 'reminders'
pref is on; unmount cancels everything (opt-out/logout).
- Skipped the Pro-expiry reminder on purpose: it would drag the heavy
useSasquatchPro query into a nudge.
Bumps to v1.5.7 (versionCode 10507); APK rebuilt.
Mirrors the activity the app already computes (bell, crews, DMs, newsletter)
to the OS notification shade, with no new relay traffic and no new network
destination.
- src/lib/osNotify.ts: one delivery API. Web uses the Notification API; native
uses @capacitor/local-notifications (lazily imported, so the web bundle never
pays for it). Tap-through navigates in-app.
- src/components/OsNotificationBridge.tsx: mounted once in Layout, inert until
opted in. Per-source silent priming + a seen-id set means history is never
replayed as a flood, and it stays quiet while the app is visible (the bell
already covers that).
- DMs notify from the gift-wrap ENVELOPE only (src/hooks/useDmEnvelopes.ts,
no decryption) — so Amber is never prompted just to be told you have a
message. Preview is honestly generic.
- src/lib/notificationPrefs.ts + useNotificationPrefs: device-local, opt-in,
default off, per-category toggles. Settings -> Notifications UI.
Deliberately local-only: a fully closed app needs a server push, which is not
built (Phase 2 = on-device background runner; Phase 3 = content-free FCM).