v0.12.27 schedule list view update

This commit is contained in:
2026-03-25 07:56:35 -04:00
parent 8c4650d1bc
commit 163d71d505
5 changed files with 113 additions and 9 deletions

View File

@@ -300,10 +300,105 @@ Single-user add/remove via `groups.js` (GroupInfoModal) always uses the named me
---
## FCM Push Notifications
**Status:** Working on Android (v0.12.26+). iOS in progress.
### Overview
Push notifications use Firebase Cloud Messaging (FCM) — not the older web-push/VAPID approach. VAPID env vars are still present (auto-generated on first start) but are no longer used for push delivery.
### Firebase Project Setup
1. Create a Firebase project at console.firebase.google.com
2. Add a **Web app** to the project → copy the web app config values into `.env`
3. In Project Settings → Cloud Messaging → **Web Push certificates** → generate a key pair → copy the public key as `FIREBASE_VAPID_KEY`
4. In Project Settings → Service accounts → Generate new private key → download JSON → stringify it (remove all newlines) → set as `FIREBASE_SERVICE_ACCOUNT` in `.env`
Required `.env` vars:
```
FIREBASE_API_KEY=
FIREBASE_PROJECT_ID=
FIREBASE_APP_ID=
FIREBASE_MESSAGING_SENDER_ID=
FIREBASE_VAPID_KEY= # Web Push certificate public key (from Cloud Messaging tab)
FIREBASE_SERVICE_ACCOUNT= # Full service account JSON, stringified (backend only)
```
### Architecture
```
Frontend (browser/PWA)
└─ usePushNotifications hook (Chat.jsx or dedicated hook)
├─ GET /api/push/firebase-config → fetches SDK config from backend
├─ Initialises Firebase JS SDK + getMessaging()
├─ getToken(messaging, { vapidKey }) → obtains FCM token
└─ POST /api/push/subscribe → registers token in push_subscriptions table
Backend (push.js)
├─ sendPushToUser(schema, userId, payload) — shared helper, called from:
│ ├─ messages.js (REST POST route — PRIMARY message path)
│ └─ index.js (socket message:send handler — secondary/fallback)
└─ Firebase Admin SDK sends the FCM message to Google's servers → device
```
### Database
Table `push_subscriptions` (migration 007):
```sql
id, user_id, device ('mobile'|'desktop'), fcm_token, created_at
```
PK is `(user_id, device)` — one token per device type per user. `/api/push/subscribe` deletes the old row then inserts, so tokens stay fresh.
### Message Payload Structure
All real messages use `notification + data`:
```js
{
token: sub.fcm_token,
notification: { title, body }, // FCM shows this even if SW fails
data: { url: '/', groupId: '42' }, // SW uses for click routing
android: { priority: 'high', notification: { sound: 'default' } },
webpush: { headers: { Urgency: 'high' }, fcm_options: { link: url } },
}
```
### Service Worker (sw.js)
`onBackgroundMessage` fires when the PWA is backgrounded/closed. Shows the notification and stores `groupId` for click routing. When the user taps the notification, the SW's `notificationclick` handler navigates to the app.
### Push Trigger Logic (messages.js)
**Critical:** The frontend sends messages via `POST /api/messages/group/:groupId` (REST), not via the socket `message:send` event. Push notifications **must** be fired from `messages.js`, not just from the socket handler in `index.js`.
- **Private group:** query `group_members`, skip sender, call `sendPushToUser` for each member
- **Public group:** query `DISTINCT user_id FROM push_subscriptions WHERE user_id != sender`, call `sendPushToUser` for each
- Image messages use body `'📷 Image'`
- The socket handler in `index.js` has identical logic for any future socket-path senders
### Debug & Test Endpoints
```
GET /api/push/debug # admin only — lists all FCM tokens for this schema + firebase status
POST /api/push/test # sends test push to own device
POST /api/push/test?mode=browser # webpush-only test (Chrome handles directly, no SW involved)
```
Use `/debug` to confirm tokens are registered. Use `/test` to verify end-to-end delivery independently of real message flow.
### Stale Token Cleanup
`sendPushToUser` catches FCM errors and deletes the `push_subscriptions` row for codes:
- `messaging/registration-token-not-registered`
- `messaging/invalid-registration-token`
- `messaging/invalid-argument`
---
## Outstanding / Deferred Work
### Android Background Push (KNOWN_LIMITATIONS.md)
**Status:** Implemented (v0.11.26+). Replaced web-push/VAPID with Firebase Cloud Messaging (FCM). Requires Firebase project setup — see .env.example for required env vars and sw.js for the SW config block.
### iOS Push Notifications
**Status:** In progress. Android working (v0.12.26+). iOS PWA push requires additional handling — investigation ongoing.
### WebSocket Reconnect on Focus
**Status:** Deferred. Socket drops when Android PWA is backgrounded.