web-manager 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -133,9 +133,9 @@ class Manager {
133
133
  // Set up auth event listeners (uses event delegation, no need to wait for DOM)
134
134
  this._auth.setupEventListeners();
135
135
 
136
- // Set up push notification auto-request if enabled
137
- if (this.config.pushNotifications?.enabled && this.config.pushNotifications?.config?.autoRequest > 0) {
138
- this._setupNotificationAutoRequest();
136
+ // Set up push notifications
137
+ if (this.config.pushNotifications?.enabled) {
138
+ this._notifications.initialize(this.config.pushNotifications.config);
139
139
  }
140
140
 
141
141
  // Initialize Chatsy chat widget if enabled
@@ -568,29 +568,6 @@ class Manager {
568
568
  }, this.config.refreshNewVersion.config.interval);
569
569
  }
570
570
 
571
- _setupNotificationAutoRequest() {
572
- // Quit if document is not available
573
- if (typeof document === 'undefined') {
574
- return;
575
- }
576
-
577
- // Set up click listener to request notification permissions
578
- const handleClick = () => {
579
- // Remove listener after first click
580
- document.removeEventListener('click', handleClick);
581
-
582
- // Set timeout to request notifications
583
- setTimeout(() => {
584
- console.log('Auto-requesting notification permissions...');
585
- this._notifications.subscribe().catch(err => {
586
- console.error('Notification subscription failed:', err.message);
587
- });
588
- }, this.config.pushNotifications.config.autoRequest);
589
- };
590
-
591
- // Wait for user click
592
- document.addEventListener('click', handleClick);
593
- }
594
571
 
595
572
  // async _loadPolyfillsIfNeeded() {
596
573
  // // Check if polyfills are needed by testing for ES6 features
@@ -4,6 +4,56 @@ class Notifications {
4
4
  this._requestInProgress = false;
5
5
  }
6
6
 
7
+ initialize(config) {
8
+ const storage = this.manager.storage();
9
+ const stored = storage.get('notifications');
10
+ const permission = typeof Notification !== 'undefined' ? Notification.permission : 'default';
11
+
12
+ console.log('[WM:push] Page load check:', { storedSubscribed: stored?.subscribed, storedToken: stored?.token?.slice(-8), permission });
13
+
14
+ // If localStorage says subscribed but browser permission disagrees, clear it
15
+ if (stored?.subscribed && permission !== 'granted') {
16
+ console.log('[WM:push] Clearing stale subscription — permission is', permission);
17
+ storage.set('notifications', { subscribed: false, token: null });
18
+ }
19
+
20
+ // Arm auto-request if not currently subscribed (including just-cleared)
21
+ const autoRequest = config?.autoRequest;
22
+ if ((!stored?.subscribed || permission !== 'granted') && autoRequest > 0) {
23
+ console.log('[WM:push] Arming auto-request (delay:', autoRequest + 'ms)');
24
+ this._setupAutoRequest(autoRequest);
25
+ }
26
+
27
+ // Listen for foreground messages (tab is focused)
28
+ if (permission === 'granted') {
29
+ console.log('[WM:push] Setting up foreground listener...', { supported: this.isSupported(), hasMessaging: !!this.manager.firebaseMessaging });
30
+ this.onMessage((payload) => {
31
+ console.log('[WM:push] Foreground message received:', payload);
32
+ }).then(unsub => {
33
+ console.log('[WM:push] Foreground listener registered:', typeof unsub === 'function' ? 'OK' : 'FAILED (got empty fn)');
34
+ });
35
+ }
36
+ }
37
+
38
+ _setupAutoRequest(delay) {
39
+ if (typeof document === 'undefined') {
40
+ return;
41
+ }
42
+
43
+ const handleClick = () => {
44
+ document.removeEventListener('click', handleClick);
45
+
46
+ setTimeout(() => {
47
+ console.log('[WM:push] Auto-requesting notification permissions...');
48
+ this.subscribe().catch(err => {
49
+ console.error('[WM:push] Auto-subscription failed:', err.message);
50
+ });
51
+ }, delay);
52
+ };
53
+
54
+ document.addEventListener('click', handleClick);
55
+ }
56
+
7
57
  // Check if notifications are supported
8
58
  isSupported() {
9
59
  return 'Notification' in window &&
@@ -222,31 +272,54 @@ class Notifications {
222
272
  }
223
273
  }
224
274
 
225
- // Sync subscription when auth state changes
275
+ // Sync subscription when auth state changes or on page load.
276
+ // Re-fetches the current FCM token — if it changed (browser rotated it,
277
+ // service worker was re-registered, etc.), saves the new token to Firestore
278
+ // and updates localStorage. Clears the subscribed state if the token is gone.
226
279
  async syncSubscription() {
227
280
  try {
228
- // Check if we have a stored notification token
229
281
  const storage = this.manager.storage();
230
282
  const storedNotification = storage.get('notifications');
231
283
 
232
- if (!storedNotification?.token) {
284
+ const permission = typeof Notification !== 'undefined' ? Notification.permission : 'default';
285
+
286
+ console.log('[WM:push:sync] Starting sync:', { storedSubscribed: storedNotification?.subscribed, storedToken: storedNotification?.token?.slice(-8), permission });
287
+
288
+ if (permission !== 'granted') {
289
+ if (storedNotification?.subscribed) {
290
+ console.log('[WM:push:sync] Permission not granted — clearing localStorage');
291
+ storage.set('notifications', { subscribed: false, token: null });
292
+ } else {
293
+ console.log('[WM:push:sync] Permission not granted and not subscribed — nothing to do');
294
+ }
233
295
  return false;
234
296
  }
235
297
 
236
- // Update the subscription in Firestore with current auth state
237
- await this._saveSubscription(storedNotification.token);
298
+ // Permission is granted check if there's a live token (covers localStorage cleared, new browser, etc.)
299
+ const currentToken = await this.getToken();
300
+
301
+ if (!currentToken) {
302
+ console.log('[WM:push:sync] Token fetch returned null — clearing localStorage');
303
+ storage.set('notifications', { subscribed: false, token: null });
304
+ return false;
305
+ }
306
+
307
+ console.log('[WM:push:sync] Token valid:', currentToken.slice(-8), storedNotification?.token ? (storedNotification.token.slice(-8) === currentToken.slice(-8) ? '(unchanged)' : '(CHANGED from ' + storedNotification.token.slice(-8) + ')') : '(recovered — localStorage was empty)');
308
+
309
+ await this._saveSubscription(currentToken);
238
310
 
239
- // Update local storage with current user ID
240
311
  const user = this.manager.auth().getUser();
241
312
  storage.set('notifications', {
242
- ...storedNotification,
313
+ subscribed: true,
314
+ token: currentToken,
243
315
  uid: user?.uid || null,
244
- timestamp: new Date().toISOString()
316
+ timestamp: new Date().toISOString(),
245
317
  });
246
318
 
319
+ console.log('[WM:push:sync] Sync complete — subscribed');
247
320
  return true;
248
321
  } catch (error) {
249
- console.error('Sync subscription error:', error);
322
+ console.error('[WM:push:sync] Sync error:', error);
250
323
  return false;
251
324
  }
252
325
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-manager",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "description": "Easily access important variables such as the query string, current domain, and current page in a single object.",
5
5
  "main": "dist/index.js",
6
6
  "module": "src/index.js",
@@ -43,14 +43,14 @@
43
43
  "@sentry/browser": "Resolved by using OVERRIDES in web-manager (lighthouse is the issue"
44
44
  },
45
45
  "dependencies": {
46
- "@sentry/browser": "^10.52.0",
46
+ "@sentry/browser": "^10.54.0",
47
47
  "chatsy": "^2.0.14",
48
48
  "firebase": "^12.13.0",
49
49
  "itwcw-package-analytics": "^1.0.8",
50
50
  "lodash": "^4.18.1"
51
51
  },
52
52
  "devDependencies": {
53
- "mocha": "^11.7.5",
53
+ "mocha": "^11.7.6",
54
54
  "prepare-package": "^2.1.0"
55
55
  }
56
56
  }