@realtimexsco/live-chat 1.5.5 → 1.5.6
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 +37 -32
- package/dist/index.cjs +434 -270
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +435 -271
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/PERMISSIONS.md +0 -445
|
@@ -17,12 +17,28 @@ importScripts(
|
|
|
17
17
|
|
|
18
18
|
var PUSH_BROADCAST_CHANNEL = "realtimex-push";
|
|
19
19
|
var NOTIFICATION_CLICK_SW_TYPE = "realtimex:notification-click";
|
|
20
|
+
var CHAT_HEARTBEAT_SW_TYPE = "realtimex:chat-heartbeat";
|
|
20
21
|
var PUSH_DATA_CACHE = "realtimex-push-data-v1";
|
|
21
22
|
var TAG_PREFIX = "realtimex-";
|
|
22
23
|
|
|
23
24
|
/** In-memory fallback when Cache API or FCM click data is empty. */
|
|
24
25
|
var pendingPushDataStore = {};
|
|
25
26
|
|
|
27
|
+
// Last time any tab told us its ForegroundPushBridge is mounted and can
|
|
28
|
+
// show its own in-app toast (see CHAT_HEARTBEAT_SW_TYPE above). A visible
|
|
29
|
+
// tab is not the same thing as a tab with the chat UI actually mounted —
|
|
30
|
+
// the host app can be open and focused on a completely unrelated route —
|
|
31
|
+
// so "tab visible" alone isn't safe grounds to suppress the OS
|
|
32
|
+
// notification for a background push.
|
|
33
|
+
var lastChatHeartbeatAt = 0;
|
|
34
|
+
var CHAT_HEARTBEAT_STALE_MS = 30000;
|
|
35
|
+
|
|
36
|
+
self.addEventListener("message", function (event) {
|
|
37
|
+
if (event.data && event.data.type === CHAT_HEARTBEAT_SW_TYPE) {
|
|
38
|
+
lastChatHeartbeatAt = Date.now();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
26
42
|
var params = new URL(self.location.href).searchParams;
|
|
27
43
|
var rawConfig = params.get("config");
|
|
28
44
|
|
|
@@ -93,15 +109,6 @@ function cachePendingOpen(data) {
|
|
|
93
109
|
});
|
|
94
110
|
}
|
|
95
111
|
|
|
96
|
-
function isChatClient(client) {
|
|
97
|
-
try {
|
|
98
|
-
var pathname = new URL(client.url).pathname || "";
|
|
99
|
-
return pathname === "/chat" || pathname.indexOf("/chat/") === 0;
|
|
100
|
-
} catch (e) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
112
|
function notifyPage(message) {
|
|
106
113
|
try {
|
|
107
114
|
var bc = new BroadcastChannel(PUSH_BROADCAST_CHANNEL);
|
|
@@ -309,14 +316,21 @@ if (rawConfig) {
|
|
|
309
316
|
var hasVisibleClient = windowClients.some(function (client) {
|
|
310
317
|
return client.visibilityState === "visible";
|
|
311
318
|
});
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
|
|
319
|
+
var chatBridgeActive =
|
|
320
|
+
Date.now() - lastChatHeartbeatAt < CHAT_HEARTBEAT_STALE_MS;
|
|
321
|
+
// Regular messages: only skip the OS notification when a tab is
|
|
322
|
+
// both visible AND actually has the chat UI mounted (recent
|
|
323
|
+
// heartbeat) — that's what makes the in-app toast path real. A
|
|
324
|
+
// visible tab elsewhere in the host app (chat widget not mounted,
|
|
325
|
+
// e.g. a different route) can't render that toast, so it still
|
|
326
|
+
// needs the OS notification for DMs and group messages alike, same
|
|
327
|
+
// as a backgrounded/closed tab. Calls skip this assumption
|
|
328
|
+
// entirely — the in-app ringing dialog only exists while the user
|
|
329
|
+
// is actually on the chat screen, so a visible-but-elsewhere tab
|
|
330
|
+
// still needs the OS notification or the call goes unnoticed.
|
|
331
|
+
if (hasVisibleClient && chatBridgeActive && !isCall) {
|
|
318
332
|
console.log(
|
|
319
|
-
"[realtimex-push]
|
|
333
|
+
"[realtimex-push] chat UI active in a visible tab — skip OS notification (use in-app toast)",
|
|
320
334
|
);
|
|
321
335
|
return;
|
|
322
336
|
}
|
|
@@ -373,27 +387,18 @@ function deliverNotificationClick(data) {
|
|
|
373
387
|
return clients
|
|
374
388
|
.matchAll({ type: "window", includeUncontrolled: true })
|
|
375
389
|
.then(function (windowClients) {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
var target = chatClient || anyClient;
|
|
390
|
+
// Any open tab of this app already gets `message` via
|
|
391
|
+
// notifyPage()'s BroadcastChannel below, regardless of which route
|
|
392
|
+
// it's on — the chat widget can be mounted anywhere in a host app,
|
|
393
|
+
// there's no fixed "/chat" page to require a match against. Focus
|
|
394
|
+
// whichever tab is already open instead of guessing its route; only
|
|
395
|
+
// open a brand new window when there's genuinely no tab open at all.
|
|
396
|
+
var target = windowClients[0];
|
|
386
397
|
|
|
387
398
|
if (target && "focus" in target) {
|
|
388
399
|
return target.focus().then(function () {
|
|
389
400
|
notifyPage(message);
|
|
390
401
|
if (target.postMessage) target.postMessage(message);
|
|
391
|
-
|
|
392
|
-
if (conversationId && !isChatClient(target) && clients.openWindow) {
|
|
393
|
-
return cachePendingOpen(data).then(function () {
|
|
394
|
-
return clients.openWindow(targetUrl);
|
|
395
|
-
});
|
|
396
|
-
}
|
|
397
402
|
return undefined;
|
|
398
403
|
});
|
|
399
404
|
}
|