web-manager 4.2.0 → 4.3.1
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 +3 -26
- package/dist/modules/notifications.js +90 -16
- package/package.json +3 -3
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
|
|
137
|
-
if (this.config.pushNotifications?.enabled
|
|
138
|
-
this.
|
|
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,58 @@ class Notifications {
|
|
|
4
4
|
this._requestInProgress = false;
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
+
initialize(config) {
|
|
8
|
+
this._vapidKey = this.manager.config?.firebase?.messaging?.config?.vapidKey || null;
|
|
9
|
+
|
|
10
|
+
const storage = this.manager.storage();
|
|
11
|
+
const stored = storage.get('notifications');
|
|
12
|
+
const permission = typeof Notification !== 'undefined' ? Notification.permission : 'default';
|
|
13
|
+
|
|
14
|
+
console.log('[WM:push] Page load check:', { storedSubscribed: stored?.subscribed, storedToken: stored?.token?.slice(-8), permission });
|
|
15
|
+
|
|
16
|
+
// If localStorage says subscribed but browser permission disagrees, clear it
|
|
17
|
+
if (stored?.subscribed && permission !== 'granted') {
|
|
18
|
+
console.log('[WM:push] Clearing stale subscription — permission is', permission);
|
|
19
|
+
storage.set('notifications', { subscribed: false, token: null });
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Arm auto-request if not currently subscribed (including just-cleared)
|
|
23
|
+
const autoRequest = config?.autoRequest;
|
|
24
|
+
if ((!stored?.subscribed || permission !== 'granted') && autoRequest > 0) {
|
|
25
|
+
console.log('[WM:push] Arming auto-request (delay:', autoRequest + 'ms)');
|
|
26
|
+
this._setupAutoRequest(autoRequest);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Listen for foreground messages (tab is focused)
|
|
30
|
+
if (permission === 'granted') {
|
|
31
|
+
console.log('[WM:push] Setting up foreground listener...', { supported: this.isSupported(), hasMessaging: !!this.manager.firebaseMessaging });
|
|
32
|
+
this.onMessage((payload) => {
|
|
33
|
+
console.log('[WM:push] Foreground message received:', payload);
|
|
34
|
+
}).then(unsub => {
|
|
35
|
+
console.log('[WM:push] Foreground listener registered:', typeof unsub === 'function' ? 'OK' : 'FAILED (got empty fn)');
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_setupAutoRequest(delay) {
|
|
41
|
+
if (typeof document === 'undefined') {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const handleClick = () => {
|
|
46
|
+
document.removeEventListener('click', handleClick);
|
|
47
|
+
|
|
48
|
+
setTimeout(() => {
|
|
49
|
+
console.log('[WM:push] Auto-requesting notification permissions...');
|
|
50
|
+
this.subscribe().catch(err => {
|
|
51
|
+
console.error('[WM:push] Auto-subscription failed:', err.message);
|
|
52
|
+
});
|
|
53
|
+
}, delay);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
document.addEventListener('click', handleClick);
|
|
57
|
+
}
|
|
58
|
+
|
|
7
59
|
// Check if notifications are supported
|
|
8
60
|
isSupported() {
|
|
9
61
|
return 'Notification' in window &&
|
|
@@ -62,10 +114,9 @@ class Notifications {
|
|
|
62
114
|
|
|
63
115
|
// Get FCM token
|
|
64
116
|
const { getToken } = await import('firebase/messaging');
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
});
|
|
117
|
+
const tokenOptions = { serviceWorkerRegistration: swRegistration };
|
|
118
|
+
if (this._vapidKey) { tokenOptions.vapidKey = this._vapidKey; }
|
|
119
|
+
const token = await getToken(messaging, tokenOptions);
|
|
69
120
|
|
|
70
121
|
if (!token) {
|
|
71
122
|
throw new Error('Failed to get FCM token');
|
|
@@ -148,9 +199,9 @@ class Notifications {
|
|
|
148
199
|
const { getToken } = await import('firebase/messaging');
|
|
149
200
|
const swRegistration = this.manager.state.serviceWorker;
|
|
150
201
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
202
|
+
const tokenOptions = { serviceWorkerRegistration: swRegistration };
|
|
203
|
+
if (this._vapidKey) { tokenOptions.vapidKey = this._vapidKey; }
|
|
204
|
+
return await getToken(messaging, tokenOptions);
|
|
154
205
|
} catch (error) {
|
|
155
206
|
console.error('Get token error:', error);
|
|
156
207
|
return null;
|
|
@@ -222,31 +273,54 @@ class Notifications {
|
|
|
222
273
|
}
|
|
223
274
|
}
|
|
224
275
|
|
|
225
|
-
// Sync subscription when auth state changes
|
|
276
|
+
// Sync subscription when auth state changes or on page load.
|
|
277
|
+
// Re-fetches the current FCM token — if it changed (browser rotated it,
|
|
278
|
+
// service worker was re-registered, etc.), saves the new token to Firestore
|
|
279
|
+
// and updates localStorage. Clears the subscribed state if the token is gone.
|
|
226
280
|
async syncSubscription() {
|
|
227
281
|
try {
|
|
228
|
-
// Check if we have a stored notification token
|
|
229
282
|
const storage = this.manager.storage();
|
|
230
283
|
const storedNotification = storage.get('notifications');
|
|
231
284
|
|
|
232
|
-
|
|
285
|
+
const permission = typeof Notification !== 'undefined' ? Notification.permission : 'default';
|
|
286
|
+
|
|
287
|
+
console.log('[WM:push:sync] Starting sync:', { storedSubscribed: storedNotification?.subscribed, storedToken: storedNotification?.token?.slice(-8), permission });
|
|
288
|
+
|
|
289
|
+
if (permission !== 'granted') {
|
|
290
|
+
if (storedNotification?.subscribed) {
|
|
291
|
+
console.log('[WM:push:sync] Permission not granted — clearing localStorage');
|
|
292
|
+
storage.set('notifications', { subscribed: false, token: null });
|
|
293
|
+
} else {
|
|
294
|
+
console.log('[WM:push:sync] Permission not granted and not subscribed — nothing to do');
|
|
295
|
+
}
|
|
233
296
|
return false;
|
|
234
297
|
}
|
|
235
298
|
|
|
236
|
-
//
|
|
237
|
-
await this.
|
|
299
|
+
// Permission is granted — check if there's a live token (covers localStorage cleared, new browser, etc.)
|
|
300
|
+
const currentToken = await this.getToken();
|
|
301
|
+
|
|
302
|
+
if (!currentToken) {
|
|
303
|
+
console.log('[WM:push:sync] Token fetch returned null — clearing localStorage');
|
|
304
|
+
storage.set('notifications', { subscribed: false, token: null });
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
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)');
|
|
309
|
+
|
|
310
|
+
await this._saveSubscription(currentToken);
|
|
238
311
|
|
|
239
|
-
// Update local storage with current user ID
|
|
240
312
|
const user = this.manager.auth().getUser();
|
|
241
313
|
storage.set('notifications', {
|
|
242
|
-
|
|
314
|
+
subscribed: true,
|
|
315
|
+
token: currentToken,
|
|
243
316
|
uid: user?.uid || null,
|
|
244
|
-
timestamp: new Date().toISOString()
|
|
317
|
+
timestamp: new Date().toISOString(),
|
|
245
318
|
});
|
|
246
319
|
|
|
320
|
+
console.log('[WM:push:sync] Sync complete — subscribed');
|
|
247
321
|
return true;
|
|
248
322
|
} catch (error) {
|
|
249
|
-
console.error('Sync
|
|
323
|
+
console.error('[WM:push:sync] Sync error:', error);
|
|
250
324
|
return false;
|
|
251
325
|
}
|
|
252
326
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "web-manager",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.1",
|
|
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.
|
|
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.
|
|
53
|
+
"mocha": "^11.7.6",
|
|
54
54
|
"prepare-package": "^2.1.0"
|
|
55
55
|
}
|
|
56
56
|
}
|