v0.12.7 FCM bug fixes

This commit is contained in:
2026-03-23 19:10:21 -04:00
parent ad67330d20
commit eca93aae28
8 changed files with 1352 additions and 11 deletions

View File

@@ -42,6 +42,7 @@ export function AuthProvider({ children }) {
try { await api.logout(); } catch {}
localStorage.removeItem('tc_token');
sessionStorage.removeItem('tc_token');
localStorage.removeItem('rc_fcm_token');
setUser(null);
setMustChangePassword(false);
};

View File

@@ -112,7 +112,7 @@ export default function Chat() {
// Dynamically import the Firebase SDK (tree-shaken, only loaded when needed)
const { initializeApp, getApps } = await import('firebase/app');
const { getMessaging, getToken, deleteToken } = await import('firebase/messaging');
const { getMessaging, getToken } = await import('firebase/messaging');
const firebaseApp = getApps().length
? getApps()[0]
@@ -126,13 +126,12 @@ export default function Chat() {
if (granted !== 'granted') return;
}
// Always delete any cached token first so we get a fresh Web Push subscription.
// Stale tokens (e.g. from a previous install or a Chrome push-subscription reset)
// still look valid to Firebase but silently fail to deliver — deleteToken forces
// Chrome to create a brand-new subscription and register it with FCM.
console.log('[Push] Clearing any cached FCM token...');
await deleteToken(firebaseMessaging).catch(() => {});
// Do NOT call deleteToken() here. Deleting the token on every page load (or
// every visibility-change) forces Chrome to create a new Web Push subscription
// each time. During the brief window between delete and re-register the server
// still holds the old (now invalid) token, so any in-flight message fails to
// deliver. Passing serviceWorkerRegistration directly to getToken() is enough
// for Firebase to return the existing valid token without needing a refresh.
console.log('[Push] Requesting FCM token...');
const fcmToken = await getToken(firebaseMessaging, {
vapidKey,
@@ -144,6 +143,14 @@ export default function Chat() {
}
console.log('[Push] FCM token obtained:', fcmToken.slice(0, 30) + '...');
// Skip the server round-trip if this token is already registered.
// Avoids a redundant DB write on every tab-focus / visibility change.
const cachedToken = localStorage.getItem('rc_fcm_token');
if (cachedToken === fcmToken) {
console.log('[Push] Token unchanged — skipping subscribe');
return;
}
const token = localStorage.getItem('tc_token') || sessionStorage.getItem('tc_token');
const subRes = await fetch('/api/push/subscribe', {
method: 'POST',
@@ -154,6 +161,7 @@ export default function Chat() {
const err = await subRes.json().catch(() => ({}));
console.warn('[Push] Subscribe failed:', err.error || subRes.status);
} else {
localStorage.setItem('rc_fcm_token', fcmToken);
console.log('[Push] FCM subscription registered successfully');
}
} catch (e) {