v0.12.6 FCM updates

This commit is contained in:
2026-03-23 13:11:47 -04:00
parent 10e3df25f9
commit a0183458eb
4 changed files with 47 additions and 58 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "rosterchirp-backend",
"version": "0.12.5",
"version": "0.12.6",
"description": "RosterChirp backend server",
"main": "src/index.js",
"scripts": {

View File

@@ -13,7 +13,7 @@
# ─────────────────────────────────────────────────────────────
set -euo pipefail
VERSION="${1:-0.12.5}"
VERSION="${1:-0.12.6}"
ACTION="${2:-}"
REGISTRY="${REGISTRY:-}"
IMAGE_NAME="rosterchirp"

View File

@@ -1,6 +1,6 @@
{
"name": "rosterchirp-frontend",
"version": "0.12.5",
"version": "0.12.6",
"private": true,
"scripts": {
"dev": "vite",

View File

@@ -1,35 +1,25 @@
// ── Firebase Messaging (background push for Android PWA) ──────────────────────
// Dynamically fetch Firebase config from backend to ensure consistency
// Config must be hardcoded here — the SW is woken by push events before any
// async fetch can resolve, so Firebase must be initialised synchronously.
importScripts('https://www.gstatic.com/firebasejs/10.14.1/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.14.1/firebase-messaging-compat.js');
let FIREBASE_CONFIG = null;
let VAPID_KEY = null;
const FIREBASE_CONFIG = {
apiKey: "AIzaSyDx191unzXFT4WA1OvkdbrIY_c57kgruAU",
authDomain: "rosterchirp-push.firebaseapp.com",
projectId: "rosterchirp-push",
storageBucket: "rosterchirp-push.firebasestorage.app",
messagingSenderId: "126479377334",
appId: "1:126479377334:web:280abdd135cf7e0c50d717"
};
// Fetch Firebase config and initialise messaging
// Initialise Firebase synchronously so the push listener is ready immediately
let messaging = null;
let firebaseConfigPromise = fetch('/api/push/firebase-config')
.then(res => res.json())
.then(config => {
FIREBASE_CONFIG = {
apiKey: config.apiKey,
authDomain: config.authDomain || `${config.projectId}.firebaseapp.com`,
projectId: config.projectId,
storageBucket: config.storageBucket || `${config.projectId}.firebasestorage.app`,
messagingSenderId: config.messagingSenderId,
appId: config.appId
};
VAPID_KEY = config.vapidKey;
if (FIREBASE_CONFIG.apiKey) {
if (FIREBASE_CONFIG.apiKey !== '__FIREBASE_API_KEY__') {
firebase.initializeApp(FIREBASE_CONFIG);
messaging = firebase.messaging();
console.log('[SW] Firebase initialized with dynamic config');
}
})
.catch(err => {
console.warn('[SW] Failed to fetch Firebase config:', err);
});
console.log('[SW] Firebase initialised');
}
// ── Cache ─────────────────────────────────────────────────────────────────────
const CACHE_NAME = 'rosterchirp-v1';
@@ -81,41 +71,40 @@ function showRosterChirpNotification(data) {
}
// ── FCM background messages ───────────────────────────────────────────────────
// Wait for Firebase config to be loaded before setting up message handler
firebaseConfigPromise.then(() => {
if (messaging) {
if (messaging) {
messaging.onBackgroundMessage((payload) => {
console.log('[SW] onBackgroundMessage received, data:', JSON.stringify(payload.data));
return showRosterChirpNotification(payload.data || {});
});
} else {
} else {
console.warn('[SW] Firebase messaging not initialised — push notifications disabled');
}
});
}
// ── Raw push event (fallback for Android) ─────────────────────────────────────
// Android Chrome sometimes doesn't properly trigger Firebase's onBackgroundMessage
// This fallback ensures notifications are displayed even if Firebase SDK fails
// Only runs when Firebase messaging is NOT yet initialised (e.g. push arrives
// before firebaseConfigPromise resolves). If Firebase IS ready it already has
// its own push listener registered and will call onBackgroundMessage — running
// this handler too would show the notification twice.
self.addEventListener('push', (event) => {
console.log('[SW] push event received, hasData:', !!event.data, 'text:', event.data?.text?.()?.slice(0, 120));
console.log('[SW] push event received, hasData:', !!event.data, 'messaging ready:', !!messaging);
// Try to handle the push event directly as a fallback
if (event.data) {
// Firebase compat SDK handles it via onBackgroundMessage — skip to avoid double notification.
if (messaging) return;
if (!event.data) return;
event.waitUntil((async () => {
try {
const data = event.data.json();
console.log('[SW] Push data parsed:', JSON.stringify(data));
// If this is a Firebase message with data payload, show notification
console.log('[SW] Push fallback — data parsed:', JSON.stringify(data));
if (data.data || (data.title && data.body)) {
const notificationData = data.data || data;
return showRosterChirpNotification(notificationData);
await showRosterChirpNotification(data.data || data);
}
} catch (e) {
console.warn('[SW] Failed to parse push data:', e);
// Try to show a basic notification with the raw text
console.warn('[SW] Push fallback — failed to parse push data:', e);
const text = event.data.text();
if (text) {
return self.registration.showNotification('RosterChirp', {
await self.registration.showNotification('RosterChirp', {
body: text.slice(0, 100),
icon: '/icons/icon-192.png',
badge: '/icons/icon-192-maskable.png',
@@ -123,7 +112,7 @@ self.addEventListener('push', (event) => {
});
}
}
}
})());
});
// ── Notification click ────────────────────────────────────────────────────────