@ethora/chat-component 26.2.22 → 26.2.27
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/firebase-messaging-sw.js +121 -82
- package/dist/helpers/getDataFromXml.d.ts +1 -0
- package/dist/helpers/historyPreloadScheduler.d.ts +1 -0
- package/dist/helpers/timestamp.d.ts +2 -0
- package/dist/main.js +10929 -10713
- package/dist/main.js.map +1 -1
- package/dist/networking/api-requests/push.api.d.ts +1 -1
- package/dist/networking/xmppClient.d.ts +20 -1
- package/dist/types/models/config.model.d.ts +3 -0
- package/dist/types/models/message.model.d.ts +1 -0
- package/dist/types/models/xmpp.model.d.ts +5 -1
- package/dist/utils/firebasePushNotifications.d.ts +1 -1
- package/dist/utils/pushStorage.d.ts +3 -0
- package/package.json +1 -1
- package/public/firebase-messaging-sw.js +121 -82
|
@@ -15,4 +15,4 @@ export declare function registerPushToken(registrationToken: string): Promise<an
|
|
|
15
15
|
*
|
|
16
16
|
* @param registrationToken – The token to unregister.
|
|
17
17
|
*/
|
|
18
|
-
export declare function unregisterPushToken(registrationToken: string): Promise<any>;
|
|
18
|
+
export declare function unregisterPushToken(registrationToken: string, authToken?: string): Promise<any>;
|
|
@@ -20,6 +20,8 @@ export declare class XmppClient implements XmppClientInterface {
|
|
|
20
20
|
presencesReady: boolean;
|
|
21
21
|
private connectionSteps;
|
|
22
22
|
private messageQueue;
|
|
23
|
+
private highLaneBurstLimit;
|
|
24
|
+
private highLaneStreak;
|
|
23
25
|
private pendingSendById;
|
|
24
26
|
private inFlightIds;
|
|
25
27
|
private processingQueue;
|
|
@@ -42,12 +44,19 @@ export declare class XmppClient implements XmppClientInterface {
|
|
|
42
44
|
private maxInFlightHistory;
|
|
43
45
|
private softPauseAfterSendMs;
|
|
44
46
|
private activeRoomBoostTtlMs;
|
|
47
|
+
private activeSendBoostMs;
|
|
48
|
+
private backgroundWhileCriticalSend;
|
|
45
49
|
private presenceFailureBackoffMs;
|
|
46
50
|
private startupPrivateStoreTimeoutMs;
|
|
47
51
|
private startupPrivateStoreTtlMs;
|
|
48
52
|
private roomPresenceBlockedUntil;
|
|
49
53
|
private activeHistoryInFlight;
|
|
50
54
|
private chatsPrivateStoreCache;
|
|
55
|
+
private activeRoomJid;
|
|
56
|
+
private sendIsActiveById;
|
|
57
|
+
private sendClickToEchoByScope;
|
|
58
|
+
private sendSlaWarningThresholdMs;
|
|
59
|
+
private backgroundSuppressedStartedAt;
|
|
51
60
|
checkOnline(): boolean;
|
|
52
61
|
pingInterval: any;
|
|
53
62
|
pingTimeout: any;
|
|
@@ -65,10 +74,12 @@ export declare class XmppClient implements XmppClientInterface {
|
|
|
65
74
|
private reconnectBaseDelayMs;
|
|
66
75
|
private pausedDueToOfflineCap;
|
|
67
76
|
private authFailureDetected;
|
|
77
|
+
private intentionalLogout;
|
|
68
78
|
private isTerminalAuthFailure;
|
|
69
79
|
constructor(username: string, password: string, xmppSettings?: xmppSettingsInterface);
|
|
70
80
|
initializeClient(): Promise<void>;
|
|
71
81
|
disconnect(): Promise<void>;
|
|
82
|
+
markIntentionalLogout: () => void;
|
|
72
83
|
attachEventListeners(): void;
|
|
73
84
|
private scheduleAdaptivePing;
|
|
74
85
|
private startAdaptivePing;
|
|
@@ -81,6 +92,14 @@ export declare class XmppClient implements XmppClientInterface {
|
|
|
81
92
|
wrapWithConnectionCheck<T>(operation: () => Promise<T>): Promise<T>;
|
|
82
93
|
private clearMamRegistry;
|
|
83
94
|
private clearHistoryQueue;
|
|
95
|
+
private getSendLane;
|
|
96
|
+
setActiveRoomJid(roomJID: string | null): void;
|
|
97
|
+
private getTotalSendQueueLength;
|
|
98
|
+
private hasPendingSendsForActiveRoom;
|
|
99
|
+
private shouldSuppressBackgroundHistory;
|
|
100
|
+
private updateBackgroundSuppressionMetrics;
|
|
101
|
+
private pickNextSendEntry;
|
|
102
|
+
private recordSendClickToEchoMetric;
|
|
84
103
|
private getRoomEpoch;
|
|
85
104
|
private getHistoryPriority;
|
|
86
105
|
private nextHistoryTaskId;
|
|
@@ -139,7 +158,7 @@ export declare class XmppClient implements XmppClientInterface {
|
|
|
139
158
|
getChatsPrivateStoreRequestStanza: () => Promise<unknown>;
|
|
140
159
|
actionSetTimestampToPrivateStoreStanza(chatId: string, timestamp: number, chats?: string[]): Promise<void>;
|
|
141
160
|
createPrivateRoomStanza(title: string, description: string, to: string): Promise<string>;
|
|
142
|
-
sendMediaMessageStanza(roomJID: string, data: any, id: string):
|
|
161
|
+
sendMediaMessageStanza(roomJID: string, data: any, id: string): Promise<boolean>;
|
|
143
162
|
recoverRoomPresenceOnly(roomJID: string): Promise<boolean>;
|
|
144
163
|
sendPingStanza(): void;
|
|
145
164
|
handlePong(): void;
|
|
@@ -168,6 +168,9 @@ export interface IConfig {
|
|
|
168
168
|
maxInFlightHistory?: number;
|
|
169
169
|
softPauseAfterSendMs?: number;
|
|
170
170
|
activeRoomBoostTtlMs?: number;
|
|
171
|
+
activeSendBoostMs?: number;
|
|
172
|
+
backgroundWhileCriticalSend?: boolean;
|
|
173
|
+
preloadTopKRooms?: number;
|
|
171
174
|
presenceFailureBackoffMs?: number;
|
|
172
175
|
startupPrivateStoreTimeoutMs?: number;
|
|
173
176
|
startupPrivateStoreTtlMs?: number;
|
|
@@ -15,6 +15,9 @@ export interface xmppSettingsInterface {
|
|
|
15
15
|
maxInFlightHistory?: number;
|
|
16
16
|
softPauseAfterSendMs?: number;
|
|
17
17
|
activeRoomBoostTtlMs?: number;
|
|
18
|
+
activeSendBoostMs?: number;
|
|
19
|
+
backgroundWhileCriticalSend?: boolean;
|
|
20
|
+
preloadTopKRooms?: number;
|
|
18
21
|
presenceFailureBackoffMs?: number;
|
|
19
22
|
startupPrivateStoreTimeoutMs?: number;
|
|
20
23
|
startupPrivateStoreTtlMs?: number;
|
|
@@ -61,6 +64,7 @@ export interface XmppClientInterface {
|
|
|
61
64
|
source?: 'active' | 'send_ack' | 'background' | 'default';
|
|
62
65
|
}): Promise<IMessage[] | undefined>;
|
|
63
66
|
promoteRoomHistory(roomJID: string): void;
|
|
67
|
+
setActiveRoomJid(roomJID: string | null): void;
|
|
64
68
|
onCriticalSend(roomJID: string, messageId?: string): void;
|
|
65
69
|
enqueueHistoryTask(params: {
|
|
66
70
|
chatJID: string;
|
|
@@ -80,7 +84,7 @@ export interface XmppClientInterface {
|
|
|
80
84
|
sendTypingRequestStanza(chatId: string, fullName: string, start: boolean): void;
|
|
81
85
|
getChatsPrivateStoreRequestStanza(): Promise<any>;
|
|
82
86
|
actionSetTimestampToPrivateStoreStanza(chatId: string, timestamp: number, chats?: string[]): Promise<void>;
|
|
83
|
-
sendMediaMessageStanza(roomJID: string, data: MediaUploadData, id: string):
|
|
87
|
+
sendMediaMessageStanza(roomJID: string, data: MediaUploadData, id: string): Promise<boolean>;
|
|
84
88
|
createPrivateRoomStanza(title: string, description: string, to: string): Promise<string>;
|
|
85
89
|
sendMessageReactionStanza(messageId: string, roomJid: string, reactionsList: string[], reactionSymbol?: string): void;
|
|
86
90
|
sendTextMessageWithTranslateTagStanza(roomJID: string, firstName: string, lastName: string, photo: string, walletAddress: string, userMessage: string, notDisplayedValue?: string, isReply?: boolean, showInChannel?: boolean, mainMessage?: string, langSource?: Iso639_1Codes): void;
|
|
@@ -36,5 +36,5 @@ export declare function listenForForegroundMessages(handler: (payload: MessagePa
|
|
|
36
36
|
/**
|
|
37
37
|
* disablePushNotifications()
|
|
38
38
|
*/
|
|
39
|
-
export declare function disablePushNotifications(): Promise<void>;
|
|
39
|
+
export declare function disablePushNotifications(_authToken?: string): Promise<void>;
|
|
40
40
|
export {};
|
package/package.json
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
|
-
/* eslint-disable no-empty */
|
|
1
|
+
/* eslint-disable no-empty, no-restricted-globals */
|
|
2
2
|
/* eslint-env worker */
|
|
3
|
-
/* global
|
|
4
|
-
|
|
5
|
-
importScripts(
|
|
6
|
-
'https://www.gstatic.com/firebasejs/10.12.0/firebase-app-compat.js'
|
|
7
|
-
);
|
|
8
|
-
importScripts(
|
|
9
|
-
'https://www.gstatic.com/firebasejs/10.12.0/firebase-messaging-compat.js'
|
|
10
|
-
);
|
|
3
|
+
/* global clients */
|
|
11
4
|
|
|
12
5
|
// ── DEBUG ─────────────────────────────────────────────────────
|
|
13
6
|
const DEBUG = false;
|
|
@@ -16,8 +9,15 @@ const DEDUP_TTL = 60 * 1000;
|
|
|
16
9
|
const params = new URL(self.location.href).searchParams;
|
|
17
10
|
const CUSTOM_ICON = (params.get('iconPath') || '').trim();
|
|
18
11
|
const CUSTOM_BADGE = (params.get('badgePath') || '').trim();
|
|
19
|
-
const DEFAULT_ICON =
|
|
20
|
-
const DEFAULT_BADGE =
|
|
12
|
+
const DEFAULT_ICON = `${self.location.origin}/favicon-192.png`;
|
|
13
|
+
const DEFAULT_BADGE = `${self.location.origin}/favicon-192.png`;
|
|
14
|
+
|
|
15
|
+
log('SW icon config', {
|
|
16
|
+
customIcon: CUSTOM_ICON || null,
|
|
17
|
+
customBadge: CUSTOM_BADGE || null,
|
|
18
|
+
defaultIcon: DEFAULT_ICON,
|
|
19
|
+
defaultBadge: DEFAULT_BADGE,
|
|
20
|
+
});
|
|
21
21
|
|
|
22
22
|
// ── LOGGING ───────────────────────────────────────────────────
|
|
23
23
|
function log(...args) {
|
|
@@ -32,42 +32,8 @@ function error(...args) {
|
|
|
32
32
|
console.error('[SW]', ...args);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
// ── CONFIG ────────────────────────────────────────────────────
|
|
36
|
-
const firebaseConfig = {
|
|
37
|
-
apiKey: params.get('apiKey'),
|
|
38
|
-
authDomain: params.get('authDomain'),
|
|
39
|
-
projectId: params.get('projectId'),
|
|
40
|
-
storageBucket: params.get('storageBucket'),
|
|
41
|
-
messagingSenderId: params.get('messagingSenderId'),
|
|
42
|
-
appId: params.get('appId'),
|
|
43
|
-
};
|
|
44
|
-
|
|
45
35
|
const APP_URL = self.location.origin;
|
|
46
36
|
|
|
47
|
-
// ── INIT FIREBASE ─────────────────────────────────────────────
|
|
48
|
-
try {
|
|
49
|
-
if (
|
|
50
|
-
firebaseConfig.apiKey &&
|
|
51
|
-
firebaseConfig.appId &&
|
|
52
|
-
firebaseConfig.messagingSenderId &&
|
|
53
|
-
firebaseConfig.projectId
|
|
54
|
-
) {
|
|
55
|
-
if (!firebase.apps.length) {
|
|
56
|
-
firebase.initializeApp(firebaseConfig);
|
|
57
|
-
log('Firebase initialized');
|
|
58
|
-
} else {
|
|
59
|
-
log('Firebase already initialized');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
firebase.messaging();
|
|
63
|
-
log('Firebase messaging ready (without onBackgroundMessage)');
|
|
64
|
-
} else {
|
|
65
|
-
warn('Firebase config missing', firebaseConfig);
|
|
66
|
-
}
|
|
67
|
-
} catch (e) {
|
|
68
|
-
error('Firebase init error', e);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
37
|
// ── DEDUP ─────────────────────────────────────────────────────
|
|
72
38
|
const handledPushes = new Map();
|
|
73
39
|
|
|
@@ -110,6 +76,7 @@ function isVisibleClients(clientsList) {
|
|
|
110
76
|
}
|
|
111
77
|
|
|
112
78
|
function dumpClients(clientsList) {
|
|
79
|
+
if (!DEBUG) return [];
|
|
113
80
|
return clientsList.map((c) => ({
|
|
114
81
|
url: c.url,
|
|
115
82
|
visibility: c.visibilityState,
|
|
@@ -164,6 +131,26 @@ function normalizeUrl(url) {
|
|
|
164
131
|
}
|
|
165
132
|
}
|
|
166
133
|
|
|
134
|
+
async function checkAssetAvailability(url) {
|
|
135
|
+
if (!DEBUG) return undefined;
|
|
136
|
+
if (!url) return { ok: false, status: null, error: 'empty_url' };
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
const response = await fetch(url, { method: 'HEAD', cache: 'no-store' });
|
|
140
|
+
return {
|
|
141
|
+
ok: response.ok,
|
|
142
|
+
status: response.status,
|
|
143
|
+
resolvedUrl: response.url || url,
|
|
144
|
+
};
|
|
145
|
+
} catch (e) {
|
|
146
|
+
return {
|
|
147
|
+
ok: false,
|
|
148
|
+
status: null,
|
|
149
|
+
error: String(e?.message || e || 'fetch_failed'),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
167
154
|
function pickTitle(raw = {}, data = {}, notification = {}) {
|
|
168
155
|
return notification.title || raw.title || data.title || 'New Message';
|
|
169
156
|
}
|
|
@@ -185,12 +172,12 @@ function pickUrl(raw = {}, data = {}, notification = {}) {
|
|
|
185
172
|
);
|
|
186
173
|
}
|
|
187
174
|
|
|
188
|
-
function pickIcon(
|
|
189
|
-
return
|
|
175
|
+
function pickIcon() {
|
|
176
|
+
return CUSTOM_ICON || DEFAULT_ICON;
|
|
190
177
|
}
|
|
191
178
|
|
|
192
|
-
function pickBadge(
|
|
193
|
-
return
|
|
179
|
+
function pickBadge() {
|
|
180
|
+
return CUSTOM_BADGE || DEFAULT_BADGE;
|
|
194
181
|
}
|
|
195
182
|
|
|
196
183
|
function pickImage(raw = {}, data = {}, notification = {}) {
|
|
@@ -214,13 +201,6 @@ function extractMessageId(raw = {}, data = {}) {
|
|
|
214
201
|
);
|
|
215
202
|
}
|
|
216
203
|
|
|
217
|
-
function hasNotificationPayload(raw = {}, notification = {}) {
|
|
218
|
-
return Boolean(
|
|
219
|
-
(notification && (notification.title || notification.body)) ||
|
|
220
|
-
(raw.notification && (raw.notification.title || raw.notification.body))
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
204
|
function makeDedupKey(raw = {}, data = {}, notification = {}) {
|
|
225
205
|
const messageId = extractMessageId(raw, data);
|
|
226
206
|
if (messageId) return `id:${messageId}`;
|
|
@@ -276,6 +256,7 @@ function normalizePush(event) {
|
|
|
276
256
|
}
|
|
277
257
|
|
|
278
258
|
async function broadcastDebugMessage(payload) {
|
|
259
|
+
if (!DEBUG) return;
|
|
279
260
|
try {
|
|
280
261
|
const windowClients = await clients.matchAll({
|
|
281
262
|
type: 'window',
|
|
@@ -303,13 +284,33 @@ async function handlePush(raw = {}, source = 'push') {
|
|
|
303
284
|
const title = pickTitle(raw, data, notification);
|
|
304
285
|
const body = pickBody(raw, data, notification);
|
|
305
286
|
const url = pickUrl(raw, data, notification);
|
|
306
|
-
const icon = pickIcon(
|
|
307
|
-
const badge = pickBadge(
|
|
287
|
+
const icon = pickIcon();
|
|
288
|
+
const badge = pickBadge();
|
|
308
289
|
const image = pickImage(raw, data, notification);
|
|
309
290
|
|
|
310
291
|
const messageId = extractMessageId(raw, data);
|
|
311
292
|
const dedupKey = makeDedupKey(raw, data, notification);
|
|
312
|
-
const
|
|
293
|
+
const iconAvailability = DEBUG
|
|
294
|
+
? await checkAssetAvailability(icon)
|
|
295
|
+
: undefined;
|
|
296
|
+
const badgeAvailability = DEBUG
|
|
297
|
+
? await checkAssetAvailability(badge)
|
|
298
|
+
: undefined;
|
|
299
|
+
const iconDebug = DEBUG
|
|
300
|
+
? {
|
|
301
|
+
selectedIcon: icon,
|
|
302
|
+
selectedBadge: badge,
|
|
303
|
+
selectedImage: image || null,
|
|
304
|
+
customIcon: CUSTOM_ICON || null,
|
|
305
|
+
customBadge: CUSTOM_BADGE || null,
|
|
306
|
+
defaultIcon: DEFAULT_ICON,
|
|
307
|
+
defaultBadge: DEFAULT_BADGE,
|
|
308
|
+
payloadIcon: data.icon || notification.icon || raw.icon || null,
|
|
309
|
+
payloadBadge: data.badge || notification.badge || raw.badge || null,
|
|
310
|
+
iconAvailability,
|
|
311
|
+
badgeAvailability,
|
|
312
|
+
}
|
|
313
|
+
: undefined;
|
|
313
314
|
|
|
314
315
|
log('--- PUSH DECISION ---');
|
|
315
316
|
log('source:', source);
|
|
@@ -320,7 +321,7 @@ async function handlePush(raw = {}, source = 'push') {
|
|
|
320
321
|
log('url:', url);
|
|
321
322
|
log('icon:', icon);
|
|
322
323
|
log('badge:', badge);
|
|
323
|
-
log('
|
|
324
|
+
if (iconDebug) log('iconDebug:', iconDebug);
|
|
324
325
|
|
|
325
326
|
if (wasHandled(dedupKey)) {
|
|
326
327
|
log('SKIP DEDUP');
|
|
@@ -336,7 +337,7 @@ async function handlePush(raw = {}, source = 'push') {
|
|
|
336
337
|
|
|
337
338
|
const visible = isVisibleClients(windowClients);
|
|
338
339
|
|
|
339
|
-
log('clients:', dumpClients(windowClients));
|
|
340
|
+
if (DEBUG) log('clients:', dumpClients(windowClients));
|
|
340
341
|
log('visibleClientExists:', visible);
|
|
341
342
|
|
|
342
343
|
await broadcastDebugMessage({
|
|
@@ -350,17 +351,11 @@ async function handlePush(raw = {}, source = 'push') {
|
|
|
350
351
|
icon,
|
|
351
352
|
badge,
|
|
352
353
|
image,
|
|
354
|
+
iconDebug,
|
|
353
355
|
messageId,
|
|
354
356
|
dedupKey,
|
|
355
|
-
browserWillAutoShow,
|
|
356
357
|
});
|
|
357
358
|
|
|
358
|
-
if (browserWillAutoShow) {
|
|
359
|
-
log('SKIP MANUAL SHOW: browser/FCM should auto-display notification');
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// Data-only push: показуємо вручну
|
|
364
359
|
const options = {
|
|
365
360
|
body,
|
|
366
361
|
icon,
|
|
@@ -393,6 +388,7 @@ async function handlePush(raw = {}, source = 'push') {
|
|
|
393
388
|
// ── RAW PUSH ONLY ─────────────────────────────────────────────
|
|
394
389
|
self.addEventListener('push', (event) => {
|
|
395
390
|
log('RAW PUSH EVENT');
|
|
391
|
+
event.stopImmediatePropagation?.();
|
|
396
392
|
|
|
397
393
|
event.waitUntil(
|
|
398
394
|
(async () => {
|
|
@@ -427,26 +423,69 @@ self.addEventListener('notificationclick', (event) => {
|
|
|
427
423
|
type: 'window',
|
|
428
424
|
includeUncontrolled: true,
|
|
429
425
|
});
|
|
426
|
+
const targetUrl = normalizeUrl(url);
|
|
427
|
+
|
|
428
|
+
const payload = {
|
|
429
|
+
data: event.notification?.data || {},
|
|
430
|
+
notification: {
|
|
431
|
+
title: event.notification?.title || '',
|
|
432
|
+
body: event.notification?.body || '',
|
|
433
|
+
},
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
const preferredClient =
|
|
437
|
+
allClients.find((client) => {
|
|
438
|
+
try {
|
|
439
|
+
return client.url.startsWith(self.location.origin);
|
|
440
|
+
} catch {
|
|
441
|
+
return false;
|
|
442
|
+
}
|
|
443
|
+
}) || allClients[0];
|
|
430
444
|
|
|
431
|
-
|
|
445
|
+
if (preferredClient) {
|
|
432
446
|
try {
|
|
433
|
-
if ('
|
|
434
|
-
await
|
|
435
|
-
|
|
436
|
-
try {
|
|
437
|
-
client.postMessage({
|
|
438
|
-
type: 'OPEN_FROM_PUSH',
|
|
439
|
-
url,
|
|
440
|
-
notificationData: event.notification?.data || {},
|
|
441
|
-
});
|
|
442
|
-
} catch {}
|
|
443
|
-
|
|
444
|
-
return;
|
|
447
|
+
if ('navigate' in preferredClient) {
|
|
448
|
+
await preferredClient.navigate(targetUrl);
|
|
445
449
|
}
|
|
450
|
+
|
|
451
|
+
if ('focus' in preferredClient) {
|
|
452
|
+
await preferredClient.focus();
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
try {
|
|
456
|
+
preferredClient.postMessage({
|
|
457
|
+
type: 'PUSH_NOTIFICATION_CLICK',
|
|
458
|
+
...payload,
|
|
459
|
+
});
|
|
460
|
+
} catch {}
|
|
461
|
+
|
|
462
|
+
// Backward compatibility for any legacy listeners in app code
|
|
463
|
+
try {
|
|
464
|
+
preferredClient.postMessage({
|
|
465
|
+
type: 'OPEN_FROM_PUSH',
|
|
466
|
+
url: targetUrl,
|
|
467
|
+
notificationData: event.notification?.data || {},
|
|
468
|
+
});
|
|
469
|
+
} catch {}
|
|
470
|
+
|
|
471
|
+
return;
|
|
472
|
+
} catch (e) {
|
|
473
|
+
warn('notificationclick client handling failed', e);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
const opened = await clients.openWindow(targetUrl);
|
|
478
|
+
|
|
479
|
+
if (opened) {
|
|
480
|
+
try {
|
|
481
|
+
opened.postMessage({
|
|
482
|
+
type: 'PUSH_NOTIFICATION_CLICK',
|
|
483
|
+
...payload,
|
|
484
|
+
});
|
|
446
485
|
} catch {}
|
|
447
486
|
}
|
|
448
487
|
|
|
449
|
-
return
|
|
488
|
+
return opened;
|
|
450
489
|
})()
|
|
451
490
|
);
|
|
452
491
|
});
|