@tencentcloud/web-push 1.0.2 → 1.0.3
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/README.md +102 -175
- package/dist/index.d.ts +259 -0
- package/{index.esm.js → dist/index.esm.js} +1118 -158
- package/dist/index.umd.js +1 -0
- package/dist/src/components/message-popup.d.ts +63 -0
- package/{src → dist/src}/core/web-push-sdk.d.ts +23 -1
- package/{src → dist/src}/index.d.ts +1 -0
- package/{src → dist/src}/types/inner.d.ts +2 -10
- package/dist/src/types/outer.d.ts +120 -0
- package/{src → dist/src}/utils/logger.d.ts +6 -0
- package/{src → dist/src}/utils/validator.d.ts +0 -13
- package/dist/sw.js +1 -0
- package/package.json +47 -9
- package/src/__tests__/index.test.ts +120 -0
- package/src/__tests__/integration.test.ts +285 -0
- package/src/__tests__/setup.ts +210 -0
- package/src/__tests__/types.test.ts +303 -0
- package/src/__tests__/web-push-sdk.test.ts +257 -0
- package/src/components/message-popup.ts +1007 -0
- package/src/core/event-emitter.ts +61 -0
- package/src/core/service-worker-manager.ts +614 -0
- package/src/core/web-push-sdk.ts +690 -0
- package/src/debug/GenerateTestUserSig.js +37 -0
- package/src/debug/index.d.ts +6 -0
- package/src/debug/index.js +1 -0
- package/src/debug/lib-generate-test-usersig-es.min.js +2 -0
- package/src/index.ts +9 -0
- package/src/service-worker/sw.ts +494 -0
- package/src/types/index.ts +2 -0
- package/src/types/inner.ts +44 -0
- package/src/types/outer.ts +142 -0
- package/src/utils/browser-support.ts +412 -0
- package/src/utils/logger.ts +66 -0
- package/src/utils/storage.ts +51 -0
- package/src/utils/validator.ts +267 -0
- package/CHANGELOG.md +0 -55
- package/index.d.ts +0 -110
- package/index.umd.js +0 -1
- package/src/types/outer.d.ts +0 -66
- package/sw.js +0 -1
- /package/{src → dist/src}/core/event-emitter.d.ts +0 -0
- /package/{src → dist/src}/core/service-worker-manager.d.ts +0 -0
- /package/{src → dist/src}/service-worker/sw.d.ts +0 -0
- /package/{src → dist/src}/types/index.d.ts +0 -0
- /package/{src → dist/src}/utils/browser-support.d.ts +0 -0
- /package/{src → dist/src}/utils/storage.d.ts +0 -0
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
import ChatSDK from "@tencentcloud/lite-chat/professional";
|
|
2
|
-
const version = "1.0.
|
|
2
|
+
const version = "1.0.3";
|
|
3
|
+
var Placement = /* @__PURE__ */ ((Placement2) => {
|
|
4
|
+
Placement2[Placement2["CENTER"] = 0] = "CENTER";
|
|
5
|
+
Placement2[Placement2["TOP_LEFT"] = 1] = "TOP_LEFT";
|
|
6
|
+
Placement2[Placement2["TOP_CENTER"] = 2] = "TOP_CENTER";
|
|
7
|
+
Placement2[Placement2["TOP_RIGHT"] = 3] = "TOP_RIGHT";
|
|
8
|
+
Placement2[Placement2["MIDDLE_RIGHT"] = 4] = "MIDDLE_RIGHT";
|
|
9
|
+
Placement2[Placement2["BOTTOM_RIGHT"] = 5] = "BOTTOM_RIGHT";
|
|
10
|
+
Placement2[Placement2["BOTTOM_CENTER"] = 6] = "BOTTOM_CENTER";
|
|
11
|
+
Placement2[Placement2["BOTTOM_LEFT"] = 7] = "BOTTOM_LEFT";
|
|
12
|
+
Placement2[Placement2["MIDDLE_LEFT"] = 8] = "MIDDLE_LEFT";
|
|
13
|
+
return Placement2;
|
|
14
|
+
})(Placement || {});
|
|
3
15
|
var EVENT = /* @__PURE__ */ ((EVENT2) => {
|
|
4
16
|
EVENT2["MESSAGE_RECEIVED"] = "message_received";
|
|
5
17
|
EVENT2["MESSAGE_REVOKED"] = "message_revoked";
|
|
6
18
|
EVENT2["NOTIFICATION_CLICKED"] = "notification_clicked";
|
|
19
|
+
EVENT2["CUSTOM_MESSAGE_RECEIVED"] = "custom_message_received";
|
|
7
20
|
return EVENT2;
|
|
8
21
|
})(EVENT || {});
|
|
9
22
|
const logPrefix = "[WebPush]";
|
|
10
23
|
class Logger {
|
|
24
|
+
// 默认为 release 级别
|
|
11
25
|
constructor() {
|
|
26
|
+
this.logLevel = 1;
|
|
12
27
|
}
|
|
13
28
|
static getInstance() {
|
|
14
29
|
if (!Logger.instance) {
|
|
@@ -16,17 +31,41 @@ class Logger {
|
|
|
16
31
|
}
|
|
17
32
|
return Logger.instance;
|
|
18
33
|
}
|
|
34
|
+
setLogLevel(level) {
|
|
35
|
+
this.logLevel = level;
|
|
36
|
+
}
|
|
37
|
+
getLogLevel() {
|
|
38
|
+
return this.logLevel;
|
|
39
|
+
}
|
|
40
|
+
shouldLog(messageLevel) {
|
|
41
|
+
if (this.logLevel === 4)
|
|
42
|
+
return false;
|
|
43
|
+
return messageLevel >= this.logLevel;
|
|
44
|
+
}
|
|
19
45
|
log(message, ...args) {
|
|
20
|
-
|
|
46
|
+
if (this.shouldLog(1)) {
|
|
47
|
+
console.log(`${logPrefix} ${message}`, ...args);
|
|
48
|
+
}
|
|
21
49
|
}
|
|
22
50
|
warn(message, ...args) {
|
|
23
|
-
|
|
51
|
+
if (this.shouldLog(2)) {
|
|
52
|
+
console.warn(`${logPrefix} ${message}`, ...args);
|
|
53
|
+
}
|
|
24
54
|
}
|
|
25
55
|
error(message, ...args) {
|
|
26
|
-
|
|
56
|
+
if (this.shouldLog(3)) {
|
|
57
|
+
console.error(`${logPrefix} ${message}`, ...args);
|
|
58
|
+
}
|
|
27
59
|
}
|
|
28
60
|
info(message, ...args) {
|
|
29
|
-
|
|
61
|
+
if (this.shouldLog(1)) {
|
|
62
|
+
console.info(`${logPrefix} ${message}`, ...args);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
debug(message, ...args) {
|
|
66
|
+
if (this.shouldLog(0)) {
|
|
67
|
+
console.debug(`${logPrefix} ${message}`, ...args);
|
|
68
|
+
}
|
|
30
69
|
}
|
|
31
70
|
}
|
|
32
71
|
const logger = Logger.getInstance();
|
|
@@ -276,50 +315,6 @@ class Validator {
|
|
|
276
315
|
};
|
|
277
316
|
this.validateObject(options, schema);
|
|
278
317
|
}
|
|
279
|
-
static validatePushMessage(message) {
|
|
280
|
-
if (!message) {
|
|
281
|
-
throw new ValidationError("message", "Push message cannot be empty");
|
|
282
|
-
}
|
|
283
|
-
const schema = {
|
|
284
|
-
messageID: {
|
|
285
|
-
required: true,
|
|
286
|
-
type: "string"
|
|
287
|
-
},
|
|
288
|
-
title: {
|
|
289
|
-
required: true,
|
|
290
|
-
type: "string"
|
|
291
|
-
},
|
|
292
|
-
body: {
|
|
293
|
-
required: true,
|
|
294
|
-
type: "string"
|
|
295
|
-
},
|
|
296
|
-
icon: {
|
|
297
|
-
required: false,
|
|
298
|
-
type: "string",
|
|
299
|
-
pattern: /^https?:\/\/.+/
|
|
300
|
-
},
|
|
301
|
-
tag: {
|
|
302
|
-
required: false,
|
|
303
|
-
type: "string"
|
|
304
|
-
},
|
|
305
|
-
timestamp: {
|
|
306
|
-
required: true,
|
|
307
|
-
type: "number"
|
|
308
|
-
}
|
|
309
|
-
};
|
|
310
|
-
this.validateObject(message, schema);
|
|
311
|
-
}
|
|
312
|
-
/**
|
|
313
|
-
* Validate URL format
|
|
314
|
-
*/
|
|
315
|
-
static validateURL(url, fieldName = "url") {
|
|
316
|
-
this.validateValue(fieldName, url, {
|
|
317
|
-
required: true,
|
|
318
|
-
type: "string",
|
|
319
|
-
pattern: /^https?:\/\/.+/,
|
|
320
|
-
message: `${fieldName} must be a valid HTTP/HTTPS URL`
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
318
|
/**
|
|
324
319
|
* Validate Service Worker path
|
|
325
320
|
*/
|
|
@@ -1172,6 +1167,838 @@ class ServiceWorkerManager {
|
|
|
1172
1167
|
}
|
|
1173
1168
|
}
|
|
1174
1169
|
}
|
|
1170
|
+
class MessagePopup {
|
|
1171
|
+
constructor(config = {}) {
|
|
1172
|
+
this.container = null;
|
|
1173
|
+
this.popups = /* @__PURE__ */ new Map();
|
|
1174
|
+
this.timers = /* @__PURE__ */ new Map();
|
|
1175
|
+
this.messageHandlers = /* @__PURE__ */ new Map();
|
|
1176
|
+
this.animationTimers = /* @__PURE__ */ new Map();
|
|
1177
|
+
this.adjustHeightTimers = /* @__PURE__ */ new Map();
|
|
1178
|
+
this.defaultConfig = {
|
|
1179
|
+
enabled: true,
|
|
1180
|
+
duration: 0,
|
|
1181
|
+
// 默认不自动关闭
|
|
1182
|
+
position: "top-right",
|
|
1183
|
+
maxCount: 5,
|
|
1184
|
+
showCloseButton: true,
|
|
1185
|
+
clickable: true,
|
|
1186
|
+
customRender: void 0,
|
|
1187
|
+
onClick: void 0,
|
|
1188
|
+
onClose: void 0
|
|
1189
|
+
};
|
|
1190
|
+
this.config = { ...this.defaultConfig, ...config };
|
|
1191
|
+
this.init();
|
|
1192
|
+
}
|
|
1193
|
+
init() {
|
|
1194
|
+
if (!this.config.enabled)
|
|
1195
|
+
return;
|
|
1196
|
+
this.createContainer();
|
|
1197
|
+
this.injectStyles();
|
|
1198
|
+
}
|
|
1199
|
+
createContainer() {
|
|
1200
|
+
const existingContainer = document.getElementById(
|
|
1201
|
+
"web-push-popup-container"
|
|
1202
|
+
);
|
|
1203
|
+
if (existingContainer) {
|
|
1204
|
+
this.container = existingContainer;
|
|
1205
|
+
return;
|
|
1206
|
+
}
|
|
1207
|
+
this.container = document.createElement("div");
|
|
1208
|
+
this.container.id = "web-push-popup-container";
|
|
1209
|
+
this.container.className = `web-push-popup-container web-push-popup-${this.config.position}`;
|
|
1210
|
+
document.body.appendChild(this.container);
|
|
1211
|
+
}
|
|
1212
|
+
injectStyles() {
|
|
1213
|
+
if (document.getElementById("web-push-popup-styles"))
|
|
1214
|
+
return;
|
|
1215
|
+
const style = document.createElement("style");
|
|
1216
|
+
style.id = "web-push-popup-styles";
|
|
1217
|
+
style.textContent = `
|
|
1218
|
+
.web-push-popup-container {
|
|
1219
|
+
position: fixed;
|
|
1220
|
+
z-index: 10000;
|
|
1221
|
+
pointer-events: none;
|
|
1222
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
.web-push-popup-top-left {
|
|
1226
|
+
top: 20px;
|
|
1227
|
+
left: 20px;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
.web-push-popup-top-center {
|
|
1231
|
+
top: 20px;
|
|
1232
|
+
left: 50%;
|
|
1233
|
+
transform: translateX(-50%);
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
.web-push-popup-top-right {
|
|
1237
|
+
top: 20px;
|
|
1238
|
+
right: 20px;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
.web-push-popup-right-center {
|
|
1242
|
+
top: 50%;
|
|
1243
|
+
right: 20px;
|
|
1244
|
+
transform: translateY(-50%);
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
.web-push-popup-bottom-right {
|
|
1248
|
+
bottom: 20px;
|
|
1249
|
+
right: 20px;
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
.web-push-popup-bottom-center {
|
|
1253
|
+
bottom: 20px;
|
|
1254
|
+
left: 50%;
|
|
1255
|
+
transform: translateX(-50%);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
.web-push-popup-bottom-left {
|
|
1259
|
+
bottom: 20px;
|
|
1260
|
+
left: 20px;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
.web-push-popup-left-center {
|
|
1264
|
+
top: 50%;
|
|
1265
|
+
left: 20px;
|
|
1266
|
+
transform: translateY(-50%);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
.web-push-popup-center {
|
|
1270
|
+
top: 50%;
|
|
1271
|
+
left: 50%;
|
|
1272
|
+
transform: translate(-50%, -50%);
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
.web-push-popup {
|
|
1276
|
+
background: #ffffff;
|
|
1277
|
+
border-radius: 16px;
|
|
1278
|
+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
|
|
1279
|
+
margin-bottom: 10px;
|
|
1280
|
+
padding: 24px;
|
|
1281
|
+
min-width: 300px;
|
|
1282
|
+
max-width: 480px;
|
|
1283
|
+
pointer-events: auto;
|
|
1284
|
+
cursor: pointer;
|
|
1285
|
+
transition: all 0.3s ease;
|
|
1286
|
+
border: 1px solid #e1e5e9;
|
|
1287
|
+
position: relative;
|
|
1288
|
+
animation: web-push-popup-slide-in 0.3s ease-out;
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
.web-push-popup:hover {
|
|
1292
|
+
box-shadow: 0 6px 25px rgba(0, 0, 0, 0.2);
|
|
1293
|
+
transform: translateY(-2px);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
.web-push-popup.web-push-popup-closing {
|
|
1297
|
+
animation: web-push-popup-slide-out 0.3s ease-in forwards;
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
@keyframes web-push-popup-slide-in {
|
|
1301
|
+
from {
|
|
1302
|
+
opacity: 0;
|
|
1303
|
+
transform: translateX(100%);
|
|
1304
|
+
}
|
|
1305
|
+
to {
|
|
1306
|
+
opacity: 1;
|
|
1307
|
+
transform: translateX(0);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
@keyframes web-push-popup-slide-out {
|
|
1312
|
+
from {
|
|
1313
|
+
opacity: 1;
|
|
1314
|
+
transform: translateX(0);
|
|
1315
|
+
}
|
|
1316
|
+
to {
|
|
1317
|
+
opacity: 0;
|
|
1318
|
+
transform: translateX(100%);
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
.web-push-popup-header {
|
|
1323
|
+
display: flex;
|
|
1324
|
+
align-items: center;
|
|
1325
|
+
margin-bottom: 8px;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
.web-push-popup-info {
|
|
1329
|
+
flex: 1;
|
|
1330
|
+
min-width: 0;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
.web-push-popup-title {
|
|
1334
|
+
font-size: 14px;
|
|
1335
|
+
font-weight: 600;
|
|
1336
|
+
color: #1a1a1a;
|
|
1337
|
+
margin: 0 0 2px 0;
|
|
1338
|
+
white-space: nowrap;
|
|
1339
|
+
overflow: hidden;
|
|
1340
|
+
text-overflow: ellipsis;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
.web-push-popup-subtitle {
|
|
1344
|
+
font-size: 12px;
|
|
1345
|
+
color: #666;
|
|
1346
|
+
margin: 0;
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
.web-push-popup-close {
|
|
1350
|
+
position: absolute;
|
|
1351
|
+
top: 8px;
|
|
1352
|
+
right: 8px;
|
|
1353
|
+
background: none;
|
|
1354
|
+
border: none;
|
|
1355
|
+
font-size: 18px;
|
|
1356
|
+
color: #999;
|
|
1357
|
+
cursor: pointer;
|
|
1358
|
+
padding: 4px;
|
|
1359
|
+
line-height: 1;
|
|
1360
|
+
border-radius: 4px;
|
|
1361
|
+
transition: all 0.2s ease;
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
.web-push-popup-close:hover {
|
|
1365
|
+
background: #f5f5f5;
|
|
1366
|
+
color: #333;
|
|
1367
|
+
}
|
|
1368
|
+
|
|
1369
|
+
.web-push-popup-content {
|
|
1370
|
+
font-size: 14px;
|
|
1371
|
+
color: #333;
|
|
1372
|
+
line-height: 1.4;
|
|
1373
|
+
word-wrap: break-word;
|
|
1374
|
+
margin: 0;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
.web-push-popup-html-container {
|
|
1378
|
+
margin-bottom: 10px;
|
|
1379
|
+
pointer-events: auto;
|
|
1380
|
+
position: relative;
|
|
1381
|
+
animation: web-push-popup-slide-in 0.3s ease-out;
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
.web-push-popup-html-container.web-push-popup-closing {
|
|
1385
|
+
animation: web-push-popup-slide-out 0.3s ease-in forwards;
|
|
1386
|
+
}
|
|
1387
|
+
`;
|
|
1388
|
+
document.head.appendChild(style);
|
|
1389
|
+
}
|
|
1390
|
+
show(message) {
|
|
1391
|
+
if (!this.config.enabled || !this.container)
|
|
1392
|
+
return;
|
|
1393
|
+
try {
|
|
1394
|
+
if (this.popups.size >= this.config.maxCount) {
|
|
1395
|
+
this.removeOldestPopup();
|
|
1396
|
+
}
|
|
1397
|
+
if (this.config.customRender) {
|
|
1398
|
+
const popup2 = this.config.customRender(message, this.container);
|
|
1399
|
+
this.addPopup(message.id, popup2, message.MsgContent.Duration);
|
|
1400
|
+
return;
|
|
1401
|
+
}
|
|
1402
|
+
let popup;
|
|
1403
|
+
if (message.MsgType === "standard") {
|
|
1404
|
+
popup = this.createStandardPopup(message, message.id);
|
|
1405
|
+
} else {
|
|
1406
|
+
popup = this.createHtmlPopup(message, message.id);
|
|
1407
|
+
}
|
|
1408
|
+
this.applyPlacement(message.MsgContent.Placement ?? 0);
|
|
1409
|
+
this.addPopup(message.id, popup, message.MsgContent.Duration);
|
|
1410
|
+
} catch (error) {
|
|
1411
|
+
logger.error("Failed to show message popup", error);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
createStandardPopup(message, messageId) {
|
|
1415
|
+
const popup = document.createElement("div");
|
|
1416
|
+
popup.className = "web-push-popup web-push-popup-standard";
|
|
1417
|
+
popup.dataset.messageId = messageId;
|
|
1418
|
+
if (message.MsgContent.Image) {
|
|
1419
|
+
const imageContainer = document.createElement("div");
|
|
1420
|
+
imageContainer.className = "web-push-popup-image";
|
|
1421
|
+
imageContainer.style.cssText = `
|
|
1422
|
+
text-align: center;
|
|
1423
|
+
margin-bottom: 20px;
|
|
1424
|
+
`;
|
|
1425
|
+
const img = document.createElement("img");
|
|
1426
|
+
img.src = message.MsgContent.Image.URL;
|
|
1427
|
+
img.alt = "Message Image";
|
|
1428
|
+
img.style.cssText = `
|
|
1429
|
+
width: auto;
|
|
1430
|
+
height: auto;
|
|
1431
|
+
max-width: 432px;
|
|
1432
|
+
max-height: 222px;
|
|
1433
|
+
border-radius: 4px;
|
|
1434
|
+
object-fit: cover;
|
|
1435
|
+
cursor: pointer;
|
|
1436
|
+
display: block;
|
|
1437
|
+
margin: 0 auto;
|
|
1438
|
+
`;
|
|
1439
|
+
img.onclick = (e2) => {
|
|
1440
|
+
e2.stopPropagation();
|
|
1441
|
+
if (message.MsgContent.Image?.LinkURL) {
|
|
1442
|
+
window.open(message.MsgContent.Image.LinkURL, "_blank");
|
|
1443
|
+
}
|
|
1444
|
+
if (this.config.onClick) {
|
|
1445
|
+
this.config.onClick(message, popup);
|
|
1446
|
+
}
|
|
1447
|
+
this.close(messageId);
|
|
1448
|
+
};
|
|
1449
|
+
imageContainer.appendChild(img);
|
|
1450
|
+
popup.appendChild(imageContainer);
|
|
1451
|
+
}
|
|
1452
|
+
if (message.MsgContent.Text) {
|
|
1453
|
+
const contentArea = document.createElement("div");
|
|
1454
|
+
contentArea.className = "web-push-popup-content-area";
|
|
1455
|
+
if (message.MsgContent.Text.Title) {
|
|
1456
|
+
const title = document.createElement("div");
|
|
1457
|
+
title.className = "web-push-popup-standard-title";
|
|
1458
|
+
title.textContent = message.MsgContent.Text.Title;
|
|
1459
|
+
title.style.cssText = `
|
|
1460
|
+
font-size: 18px;
|
|
1461
|
+
line-height: 26px;
|
|
1462
|
+
font-weight: 600;
|
|
1463
|
+
color: #000000E5;
|
|
1464
|
+
margin-bottom: 8px;
|
|
1465
|
+
max-width: 432px;
|
|
1466
|
+
overflow: hidden;
|
|
1467
|
+
text-overflow: ellipsis;
|
|
1468
|
+
display: -webkit-box;
|
|
1469
|
+
-webkit-line-clamp: 2;
|
|
1470
|
+
-webkit-box-orient: vertical;
|
|
1471
|
+
word-wrap: break-word;
|
|
1472
|
+
`;
|
|
1473
|
+
contentArea.appendChild(title);
|
|
1474
|
+
}
|
|
1475
|
+
if (message.MsgContent.Text.Desc) {
|
|
1476
|
+
const desc = document.createElement("div");
|
|
1477
|
+
desc.className = "web-push-popup-standard-desc";
|
|
1478
|
+
desc.textContent = message.MsgContent.Text.Desc;
|
|
1479
|
+
desc.style.cssText = `
|
|
1480
|
+
font-size: 14px;
|
|
1481
|
+
font-weight: 400;
|
|
1482
|
+
color: #000000B2;
|
|
1483
|
+
line-height: 22px;
|
|
1484
|
+
max-width: 432px;
|
|
1485
|
+
overflow: hidden;
|
|
1486
|
+
text-overflow: ellipsis;
|
|
1487
|
+
display: -webkit-box;
|
|
1488
|
+
-webkit-line-clamp: 6;
|
|
1489
|
+
-webkit-box-orient: vertical;
|
|
1490
|
+
word-wrap: break-word;
|
|
1491
|
+
`;
|
|
1492
|
+
contentArea.appendChild(desc);
|
|
1493
|
+
}
|
|
1494
|
+
popup.appendChild(contentArea);
|
|
1495
|
+
}
|
|
1496
|
+
if (message.MsgContent.Button && message.MsgContent.Button.length > 0) {
|
|
1497
|
+
const buttonContainer = document.createElement("div");
|
|
1498
|
+
buttonContainer.className = "web-push-popup-buttons";
|
|
1499
|
+
buttonContainer.style.cssText = `
|
|
1500
|
+
display: flex;
|
|
1501
|
+
gap: 12px;
|
|
1502
|
+
margin-top: 24px;
|
|
1503
|
+
flex-wrap: wrap;
|
|
1504
|
+
`;
|
|
1505
|
+
message.MsgContent.Button.forEach((buttonConfig, index) => {
|
|
1506
|
+
const button = document.createElement("button");
|
|
1507
|
+
button.className = "web-push-popup-button";
|
|
1508
|
+
button.textContent = buttonConfig.Text;
|
|
1509
|
+
button.style.cssText = `
|
|
1510
|
+
flex: 1;
|
|
1511
|
+
min-width: 80px;
|
|
1512
|
+
padding: 8px 16px;
|
|
1513
|
+
border: 1px solid ${index === 0 ? "#E6E9EF" : "#0052D9"};
|
|
1514
|
+
background: ${index === 0 ? "transparent" : "#0052D9"};
|
|
1515
|
+
color: ${index === 0 ? "#000000E5" : "#FFFFFFE5"};
|
|
1516
|
+
border-radius: 4px;
|
|
1517
|
+
font-size: 14px;
|
|
1518
|
+
font-weight: 400;
|
|
1519
|
+
line-height: 22px;
|
|
1520
|
+
cursor: pointer;
|
|
1521
|
+
transition: all 0.2s ease;
|
|
1522
|
+
`;
|
|
1523
|
+
if (buttonConfig.Icon) {
|
|
1524
|
+
const icon = document.createElement("img");
|
|
1525
|
+
icon.src = buttonConfig.Icon;
|
|
1526
|
+
icon.style.cssText = `
|
|
1527
|
+
width: 16px;
|
|
1528
|
+
height: 16px;
|
|
1529
|
+
margin-right: 6px;
|
|
1530
|
+
vertical-align: middle;
|
|
1531
|
+
`;
|
|
1532
|
+
button.insertBefore(icon, button.firstChild);
|
|
1533
|
+
}
|
|
1534
|
+
button.onclick = (e2) => {
|
|
1535
|
+
e2.stopPropagation();
|
|
1536
|
+
if (buttonConfig.Url) {
|
|
1537
|
+
window.open(buttonConfig.Url, "_blank");
|
|
1538
|
+
}
|
|
1539
|
+
if (this.config.onClick) {
|
|
1540
|
+
this.config.onClick(message, popup);
|
|
1541
|
+
}
|
|
1542
|
+
this.close(messageId);
|
|
1543
|
+
};
|
|
1544
|
+
button.onmouseenter = () => {
|
|
1545
|
+
button.style.transform = "translateY(-1px)";
|
|
1546
|
+
button.style.boxShadow = "0 2px 8px rgba(0,122,255,0.3)";
|
|
1547
|
+
};
|
|
1548
|
+
button.onmouseleave = () => {
|
|
1549
|
+
button.style.transform = "translateY(0)";
|
|
1550
|
+
button.style.boxShadow = "none";
|
|
1551
|
+
};
|
|
1552
|
+
buttonContainer.appendChild(button);
|
|
1553
|
+
});
|
|
1554
|
+
popup.appendChild(buttonContainer);
|
|
1555
|
+
}
|
|
1556
|
+
if (message.MsgContent.Close === 1 && this.config.showCloseButton) {
|
|
1557
|
+
const closeBtn = document.createElement("button");
|
|
1558
|
+
closeBtn.className = "web-push-popup-close";
|
|
1559
|
+
closeBtn.innerHTML = "×";
|
|
1560
|
+
closeBtn.style.cssText = `
|
|
1561
|
+
position: absolute;
|
|
1562
|
+
top: 8px;
|
|
1563
|
+
right: 8px;
|
|
1564
|
+
width: 24px;
|
|
1565
|
+
height: 24px;
|
|
1566
|
+
border: none;
|
|
1567
|
+
background: rgba(0,0,0,0.1);
|
|
1568
|
+
color: #666;
|
|
1569
|
+
border-radius: 50%;
|
|
1570
|
+
cursor: pointer;
|
|
1571
|
+
font-size: 16px;
|
|
1572
|
+
display: flex;
|
|
1573
|
+
align-items: center;
|
|
1574
|
+
justify-content: center;
|
|
1575
|
+
transition: all 0.2s ease;
|
|
1576
|
+
`;
|
|
1577
|
+
closeBtn.onclick = (e2) => {
|
|
1578
|
+
e2.stopPropagation();
|
|
1579
|
+
this.close(messageId);
|
|
1580
|
+
};
|
|
1581
|
+
closeBtn.onmouseenter = () => {
|
|
1582
|
+
closeBtn.style.background = "rgba(0,0,0,0.2)";
|
|
1583
|
+
};
|
|
1584
|
+
closeBtn.onmouseleave = () => {
|
|
1585
|
+
closeBtn.style.background = "rgba(0,0,0,0.1)";
|
|
1586
|
+
};
|
|
1587
|
+
popup.appendChild(closeBtn);
|
|
1588
|
+
}
|
|
1589
|
+
if (this.config.clickable) {
|
|
1590
|
+
popup.onclick = () => {
|
|
1591
|
+
if (this.config.onClick) {
|
|
1592
|
+
this.config.onClick(message, popup);
|
|
1593
|
+
}
|
|
1594
|
+
this.close(messageId);
|
|
1595
|
+
};
|
|
1596
|
+
}
|
|
1597
|
+
return popup;
|
|
1598
|
+
}
|
|
1599
|
+
createHtmlPopup(message, messageId) {
|
|
1600
|
+
const popup = document.createElement("div");
|
|
1601
|
+
popup.className = "web-push-popup-html-container";
|
|
1602
|
+
popup.dataset.messageId = messageId;
|
|
1603
|
+
popup.style.cssText = `
|
|
1604
|
+
pointer-events: auto;
|
|
1605
|
+
position: relative;
|
|
1606
|
+
`;
|
|
1607
|
+
try {
|
|
1608
|
+
const base64ToUtf8 = (base64Str) => {
|
|
1609
|
+
try {
|
|
1610
|
+
const binaryStr = atob(base64Str);
|
|
1611
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
1612
|
+
for (let i2 = 0; i2 < binaryStr.length; i2++) {
|
|
1613
|
+
bytes[i2] = binaryStr.charCodeAt(i2);
|
|
1614
|
+
}
|
|
1615
|
+
const decoder = new TextDecoder("utf-8");
|
|
1616
|
+
return decoder.decode(bytes);
|
|
1617
|
+
} catch (error) {
|
|
1618
|
+
logger.warn("UTF-8 解码失败,使用原始 atob 解码:", error);
|
|
1619
|
+
return atob(base64Str);
|
|
1620
|
+
}
|
|
1621
|
+
};
|
|
1622
|
+
const decodedHtml = base64ToUtf8(message.MsgContent.Html);
|
|
1623
|
+
const iframe = document.createElement("iframe");
|
|
1624
|
+
iframe.className = "web-push-popup-html-iframe";
|
|
1625
|
+
iframe.style.cssText = `
|
|
1626
|
+
width: 100%;
|
|
1627
|
+
min-height: 200px;
|
|
1628
|
+
max-height: 400px;
|
|
1629
|
+
border: none;
|
|
1630
|
+
background: transparent;
|
|
1631
|
+
overflow: auto;
|
|
1632
|
+
display: block;
|
|
1633
|
+
`;
|
|
1634
|
+
iframe.setAttribute("sandbox", "allow-same-origin allow-scripts");
|
|
1635
|
+
iframe.setAttribute("loading", "eager");
|
|
1636
|
+
popup.appendChild(iframe);
|
|
1637
|
+
const messageHandler = (event) => {
|
|
1638
|
+
if (event.source === iframe.contentWindow) {
|
|
1639
|
+
if (event.data && event.data.type === "iframe-click") {
|
|
1640
|
+
if (this.config.onClick) {
|
|
1641
|
+
this.config.onClick(message, popup);
|
|
1642
|
+
}
|
|
1643
|
+
this.close(messageId);
|
|
1644
|
+
} else if (event.data && event.data.type === "iframe-content-loaded") {
|
|
1645
|
+
this.adjustIframeHeight(iframe);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
};
|
|
1649
|
+
window.addEventListener("message", messageHandler);
|
|
1650
|
+
this.messageHandlers.set(messageId, messageHandler);
|
|
1651
|
+
const writeContent = () => {
|
|
1652
|
+
try {
|
|
1653
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
1654
|
+
if (iframeDoc) {
|
|
1655
|
+
const fullHtml = this.createIframeHtml(decodedHtml, messageId);
|
|
1656
|
+
iframeDoc.open();
|
|
1657
|
+
iframeDoc.write(fullHtml);
|
|
1658
|
+
iframeDoc.close();
|
|
1659
|
+
const heightTimer = setTimeout(() => {
|
|
1660
|
+
this.adjustIframeHeight(iframe);
|
|
1661
|
+
this.adjustHeightTimers.delete(messageId);
|
|
1662
|
+
}, 100);
|
|
1663
|
+
this.adjustHeightTimers.set(messageId, heightTimer);
|
|
1664
|
+
}
|
|
1665
|
+
} catch (error) {
|
|
1666
|
+
logger.error("Failed to write content to iframe", error);
|
|
1667
|
+
}
|
|
1668
|
+
};
|
|
1669
|
+
iframe.onload = writeContent;
|
|
1670
|
+
const writeTimer = setTimeout(() => {
|
|
1671
|
+
writeContent();
|
|
1672
|
+
this.adjustHeightTimers.delete(`${messageId}_write`);
|
|
1673
|
+
}, 0);
|
|
1674
|
+
this.adjustHeightTimers.set(`${messageId}_write`, writeTimer);
|
|
1675
|
+
} catch (error) {
|
|
1676
|
+
logger.error("Failed to decode HTML message", error);
|
|
1677
|
+
const errorDiv = document.createElement("div");
|
|
1678
|
+
errorDiv.className = "web-push-popup-error";
|
|
1679
|
+
errorDiv.textContent = "消息内容解析失败";
|
|
1680
|
+
errorDiv.style.cssText = `
|
|
1681
|
+
padding: 16px;
|
|
1682
|
+
color: #ff4444;
|
|
1683
|
+
text-align: center;
|
|
1684
|
+
font-size: 14px;
|
|
1685
|
+
`;
|
|
1686
|
+
popup.appendChild(errorDiv);
|
|
1687
|
+
}
|
|
1688
|
+
if (this.config.clickable) {
|
|
1689
|
+
popup.onclick = () => {
|
|
1690
|
+
if (this.config.onClick) {
|
|
1691
|
+
this.config.onClick(message, popup);
|
|
1692
|
+
}
|
|
1693
|
+
this.close(messageId);
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
return popup;
|
|
1697
|
+
}
|
|
1698
|
+
addPopup(messageId, popup, messageDuration) {
|
|
1699
|
+
if (!this.container)
|
|
1700
|
+
return;
|
|
1701
|
+
this.popups.set(messageId, popup);
|
|
1702
|
+
this.container.appendChild(popup);
|
|
1703
|
+
const duration = messageDuration !== void 0 ? messageDuration * 1e3 : this.config.duration;
|
|
1704
|
+
if (duration > 0) {
|
|
1705
|
+
const timer = setTimeout(() => {
|
|
1706
|
+
this.timers.delete(messageId);
|
|
1707
|
+
this.close(messageId);
|
|
1708
|
+
}, duration);
|
|
1709
|
+
this.timers.set(messageId, timer);
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
removeOldestPopup() {
|
|
1713
|
+
const firstKey = this.popups.keys().next().value;
|
|
1714
|
+
if (firstKey) {
|
|
1715
|
+
this.close(firstKey);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
close(messageId) {
|
|
1719
|
+
const popup = this.popups.get(messageId);
|
|
1720
|
+
if (!popup)
|
|
1721
|
+
return;
|
|
1722
|
+
try {
|
|
1723
|
+
const timer = this.timers.get(messageId);
|
|
1724
|
+
if (timer) {
|
|
1725
|
+
clearTimeout(timer);
|
|
1726
|
+
this.timers.delete(messageId);
|
|
1727
|
+
}
|
|
1728
|
+
const heightTimer = this.adjustHeightTimers.get(messageId);
|
|
1729
|
+
if (heightTimer) {
|
|
1730
|
+
clearTimeout(heightTimer);
|
|
1731
|
+
this.adjustHeightTimers.delete(messageId);
|
|
1732
|
+
}
|
|
1733
|
+
const writeTimer = this.adjustHeightTimers.get(`${messageId}_write`);
|
|
1734
|
+
if (writeTimer) {
|
|
1735
|
+
clearTimeout(writeTimer);
|
|
1736
|
+
this.adjustHeightTimers.delete(`${messageId}_write`);
|
|
1737
|
+
}
|
|
1738
|
+
const messageHandler = this.messageHandlers.get(messageId);
|
|
1739
|
+
if (messageHandler) {
|
|
1740
|
+
window.removeEventListener("message", messageHandler);
|
|
1741
|
+
this.messageHandlers.delete(messageId);
|
|
1742
|
+
}
|
|
1743
|
+
popup.classList.add("web-push-popup-closing");
|
|
1744
|
+
if (this.config.onClose) {
|
|
1745
|
+
this.config.onClose({ ID: messageId }, popup);
|
|
1746
|
+
}
|
|
1747
|
+
const animationTimer = setTimeout(() => {
|
|
1748
|
+
if (popup.parentNode) {
|
|
1749
|
+
popup.parentNode.removeChild(popup);
|
|
1750
|
+
}
|
|
1751
|
+
this.popups.delete(messageId);
|
|
1752
|
+
this.animationTimers.delete(messageId);
|
|
1753
|
+
}, 300);
|
|
1754
|
+
this.animationTimers.set(messageId, animationTimer);
|
|
1755
|
+
} catch (error) {
|
|
1756
|
+
logger.error("Failed to close popup", error);
|
|
1757
|
+
if (popup.parentNode) {
|
|
1758
|
+
popup.parentNode.removeChild(popup);
|
|
1759
|
+
}
|
|
1760
|
+
this.popups.delete(messageId);
|
|
1761
|
+
const timer = this.timers.get(messageId);
|
|
1762
|
+
if (timer) {
|
|
1763
|
+
clearTimeout(timer);
|
|
1764
|
+
this.timers.delete(messageId);
|
|
1765
|
+
}
|
|
1766
|
+
const heightTimer = this.adjustHeightTimers.get(messageId);
|
|
1767
|
+
if (heightTimer) {
|
|
1768
|
+
clearTimeout(heightTimer);
|
|
1769
|
+
this.adjustHeightTimers.delete(messageId);
|
|
1770
|
+
}
|
|
1771
|
+
const writeTimer = this.adjustHeightTimers.get(`${messageId}_write`);
|
|
1772
|
+
if (writeTimer) {
|
|
1773
|
+
clearTimeout(writeTimer);
|
|
1774
|
+
this.adjustHeightTimers.delete(`${messageId}_write`);
|
|
1775
|
+
}
|
|
1776
|
+
const animationTimer = this.animationTimers.get(messageId);
|
|
1777
|
+
if (animationTimer) {
|
|
1778
|
+
clearTimeout(animationTimer);
|
|
1779
|
+
this.animationTimers.delete(messageId);
|
|
1780
|
+
}
|
|
1781
|
+
const messageHandler = this.messageHandlers.get(messageId);
|
|
1782
|
+
if (messageHandler) {
|
|
1783
|
+
window.removeEventListener("message", messageHandler);
|
|
1784
|
+
this.messageHandlers.delete(messageId);
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* 检查指定消息是否正在显示弹窗
|
|
1790
|
+
* @param messageId 消息ID
|
|
1791
|
+
* @returns 是否正在显示
|
|
1792
|
+
*/
|
|
1793
|
+
hasMessage(messageId) {
|
|
1794
|
+
return this.popups.has(messageId);
|
|
1795
|
+
}
|
|
1796
|
+
closeAll() {
|
|
1797
|
+
for (const messageId of this.popups.keys()) {
|
|
1798
|
+
this.close(messageId);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
updateConfig(newConfig) {
|
|
1802
|
+
this.config = { ...this.config, ...newConfig };
|
|
1803
|
+
if (!this.config.enabled) {
|
|
1804
|
+
this.closeAll();
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
destroy() {
|
|
1808
|
+
this.closeAll();
|
|
1809
|
+
this.timers.forEach((timer) => clearTimeout(timer));
|
|
1810
|
+
this.timers.clear();
|
|
1811
|
+
this.animationTimers.forEach((timer) => clearTimeout(timer));
|
|
1812
|
+
this.animationTimers.clear();
|
|
1813
|
+
this.adjustHeightTimers.forEach((timer) => clearTimeout(timer));
|
|
1814
|
+
this.adjustHeightTimers.clear();
|
|
1815
|
+
this.messageHandlers.forEach(
|
|
1816
|
+
(handler) => window.removeEventListener("message", handler)
|
|
1817
|
+
);
|
|
1818
|
+
this.messageHandlers.clear();
|
|
1819
|
+
if (this.container && this.container.parentNode) {
|
|
1820
|
+
this.container.parentNode.removeChild(this.container);
|
|
1821
|
+
}
|
|
1822
|
+
const styles = document.getElementById("web-push-popup-styles");
|
|
1823
|
+
if (styles && styles.parentNode) {
|
|
1824
|
+
styles.parentNode.removeChild(styles);
|
|
1825
|
+
}
|
|
1826
|
+
this.container = null;
|
|
1827
|
+
this.popups.clear();
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* 根据 Placement 值应用容器位置
|
|
1831
|
+
* 0-中间,1-左上,2-上中,3-右上,4-右中,5-右下,6-下中,7-左下,8-左中
|
|
1832
|
+
*/
|
|
1833
|
+
applyPlacement(placement) {
|
|
1834
|
+
if (!this.container)
|
|
1835
|
+
return;
|
|
1836
|
+
this.container.classList.remove(
|
|
1837
|
+
"web-push-popup-center",
|
|
1838
|
+
"web-push-popup-top-left",
|
|
1839
|
+
"web-push-popup-top-center",
|
|
1840
|
+
"web-push-popup-top-right",
|
|
1841
|
+
"web-push-popup-right-center",
|
|
1842
|
+
"web-push-popup-bottom-right",
|
|
1843
|
+
"web-push-popup-bottom-center",
|
|
1844
|
+
"web-push-popup-bottom-left",
|
|
1845
|
+
"web-push-popup-left-center"
|
|
1846
|
+
);
|
|
1847
|
+
switch (placement) {
|
|
1848
|
+
case 0:
|
|
1849
|
+
this.container.classList.add("web-push-popup-center");
|
|
1850
|
+
break;
|
|
1851
|
+
case 1:
|
|
1852
|
+
this.container.classList.add("web-push-popup-top-left");
|
|
1853
|
+
break;
|
|
1854
|
+
case 2:
|
|
1855
|
+
this.container.classList.add("web-push-popup-top-center");
|
|
1856
|
+
break;
|
|
1857
|
+
case 3:
|
|
1858
|
+
this.container.classList.add("web-push-popup-top-right");
|
|
1859
|
+
break;
|
|
1860
|
+
case 4:
|
|
1861
|
+
this.container.classList.add("web-push-popup-right-center");
|
|
1862
|
+
break;
|
|
1863
|
+
case 5:
|
|
1864
|
+
this.container.classList.add("web-push-popup-bottom-right");
|
|
1865
|
+
break;
|
|
1866
|
+
case 6:
|
|
1867
|
+
this.container.classList.add("web-push-popup-bottom-center");
|
|
1868
|
+
break;
|
|
1869
|
+
case 7:
|
|
1870
|
+
this.container.classList.add("web-push-popup-bottom-left");
|
|
1871
|
+
break;
|
|
1872
|
+
case 8:
|
|
1873
|
+
this.container.classList.add("web-push-popup-left-center");
|
|
1874
|
+
break;
|
|
1875
|
+
default:
|
|
1876
|
+
this.container.classList.add(`web-push-popup-${this.config.position}`);
|
|
1877
|
+
break;
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
/**
|
|
1881
|
+
* 调整iframe高度以适应内容
|
|
1882
|
+
*/
|
|
1883
|
+
adjustIframeHeight(iframe) {
|
|
1884
|
+
try {
|
|
1885
|
+
const iframeDoc = iframe.contentDocument || iframe.contentWindow?.document;
|
|
1886
|
+
if (!iframeDoc)
|
|
1887
|
+
return;
|
|
1888
|
+
const body = iframeDoc.body;
|
|
1889
|
+
const html = iframeDoc.documentElement;
|
|
1890
|
+
if (body && html) {
|
|
1891
|
+
const contentHeight = Math.max(
|
|
1892
|
+
body.scrollHeight,
|
|
1893
|
+
body.offsetHeight,
|
|
1894
|
+
html.clientHeight,
|
|
1895
|
+
html.scrollHeight,
|
|
1896
|
+
html.offsetHeight
|
|
1897
|
+
);
|
|
1898
|
+
const minHeight = 100;
|
|
1899
|
+
const maxHeight = 400;
|
|
1900
|
+
const finalHeight = Math.min(
|
|
1901
|
+
Math.max(contentHeight, minHeight),
|
|
1902
|
+
maxHeight
|
|
1903
|
+
);
|
|
1904
|
+
iframe.style.height = `${finalHeight}px`;
|
|
1905
|
+
if (contentHeight > maxHeight) {
|
|
1906
|
+
iframe.style.overflow = "auto";
|
|
1907
|
+
body.style.overflow = "auto";
|
|
1908
|
+
} else {
|
|
1909
|
+
iframe.style.overflow = "hidden";
|
|
1910
|
+
body.style.overflow = "hidden";
|
|
1911
|
+
}
|
|
1912
|
+
}
|
|
1913
|
+
} catch (error) {
|
|
1914
|
+
logger.warn("Failed to adjust iframe height", error);
|
|
1915
|
+
iframe.style.height = "200px";
|
|
1916
|
+
iframe.style.overflow = "auto";
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
/**
|
|
1920
|
+
* 创建iframe的完整HTML文档
|
|
1921
|
+
*/
|
|
1922
|
+
createIframeHtml(bodyContent, messageId) {
|
|
1923
|
+
return `
|
|
1924
|
+
<!DOCTYPE html>
|
|
1925
|
+
<html>
|
|
1926
|
+
<head>
|
|
1927
|
+
<meta charset="utf-8">
|
|
1928
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1929
|
+
<style>
|
|
1930
|
+
* {
|
|
1931
|
+
box-sizing: border-box;
|
|
1932
|
+
}
|
|
1933
|
+
html, body {
|
|
1934
|
+
margin: 0;
|
|
1935
|
+
padding: 8px;
|
|
1936
|
+
width: 100%;
|
|
1937
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
1938
|
+
font-size: 14px;
|
|
1939
|
+
line-height: 1.4;
|
|
1940
|
+
cursor: pointer;
|
|
1941
|
+
}
|
|
1942
|
+
body {
|
|
1943
|
+
min-height: auto;
|
|
1944
|
+
overflow-wrap: break-word;
|
|
1945
|
+
word-wrap: break-word;
|
|
1946
|
+
}
|
|
1947
|
+
img {
|
|
1948
|
+
max-width: 100%;
|
|
1949
|
+
height: auto;
|
|
1950
|
+
}
|
|
1951
|
+
a {
|
|
1952
|
+
color: #1976d2;
|
|
1953
|
+
text-decoration: none;
|
|
1954
|
+
}
|
|
1955
|
+
a:hover {
|
|
1956
|
+
text-decoration: underline;
|
|
1957
|
+
}
|
|
1958
|
+
</style>
|
|
1959
|
+
</head>
|
|
1960
|
+
<body>
|
|
1961
|
+
${bodyContent}
|
|
1962
|
+
<script>
|
|
1963
|
+
// 确保所有链接在新窗口打开
|
|
1964
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
1965
|
+
const links = document.querySelectorAll('a');
|
|
1966
|
+
links.forEach(function(link) {
|
|
1967
|
+
link.target = '_blank';
|
|
1968
|
+
link.rel = 'noopener noreferrer';
|
|
1969
|
+
});
|
|
1970
|
+
|
|
1971
|
+
// 添加点击事件监听器
|
|
1972
|
+
${messageId ? `
|
|
1973
|
+
document.addEventListener('click', function(e) {
|
|
1974
|
+
window.parent.postMessage({
|
|
1975
|
+
type: 'iframe-click',
|
|
1976
|
+
messageId: '${messageId}'
|
|
1977
|
+
}, '*');
|
|
1978
|
+
});
|
|
1979
|
+
` : ""}
|
|
1980
|
+
|
|
1981
|
+
// 通知父页面内容已加载,可以调整高度
|
|
1982
|
+
var contentLoadedTimer = setTimeout(function() {
|
|
1983
|
+
if (window.parent && window.parent !== window) {
|
|
1984
|
+
try {
|
|
1985
|
+
window.parent.postMessage({
|
|
1986
|
+
type: 'iframe-content-loaded',
|
|
1987
|
+
height: document.body.scrollHeight
|
|
1988
|
+
}, '*');
|
|
1989
|
+
} catch (e) {
|
|
1990
|
+
// 忽略跨域错误
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
}, 100);
|
|
1994
|
+
});
|
|
1995
|
+
|
|
1996
|
+
// 注意:不要重新定义 window.parent,否则会阻止与父页面的通信
|
|
1997
|
+
<\/script>
|
|
1998
|
+
</body>
|
|
1999
|
+
</html>`;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
1175
2002
|
var e = "undefined" != typeof global ? global : "undefined" != typeof self ? self : "undefined" != typeof window ? window : {}, t = [], r = [], n = "undefined" != typeof Uint8Array ? Uint8Array : Array, i = false;
|
|
1176
2003
|
function o() {
|
|
1177
2004
|
i = true;
|
|
@@ -5470,12 +6297,14 @@ function genTestUserSig(options) {
|
|
|
5470
6297
|
}
|
|
5471
6298
|
class WebPushSDK {
|
|
5472
6299
|
constructor() {
|
|
6300
|
+
this.messagePopup = null;
|
|
5473
6301
|
this.isRegistered = false;
|
|
5474
6302
|
this.registrationID = "";
|
|
5475
6303
|
this.chat = null;
|
|
5476
6304
|
this.SDKAppID = 0;
|
|
5477
6305
|
this.appKey = "";
|
|
5478
6306
|
this.vapidPublicKey = "";
|
|
6307
|
+
this.pendingMessages = [];
|
|
5479
6308
|
this.EVENT = EVENT;
|
|
5480
6309
|
this.VERSION = version;
|
|
5481
6310
|
logger.log("version:", version);
|
|
@@ -5487,6 +6316,7 @@ class WebPushSDK {
|
|
|
5487
6316
|
logger.error("Browser compatibility initialization failed", error);
|
|
5488
6317
|
});
|
|
5489
6318
|
this.setupInternalListeners();
|
|
6319
|
+
this.setupVisibilityChangeListener();
|
|
5490
6320
|
}
|
|
5491
6321
|
static getInstance() {
|
|
5492
6322
|
if (!this.instance) {
|
|
@@ -5497,7 +6327,10 @@ class WebPushSDK {
|
|
|
5497
6327
|
async registerPush(options) {
|
|
5498
6328
|
try {
|
|
5499
6329
|
Validator.validateRegisterPushOptions(options);
|
|
5500
|
-
const { SDKAppID, appKey, userID, chat } = options;
|
|
6330
|
+
const { SDKAppID, appKey, userID, chat, logLevel } = options;
|
|
6331
|
+
if (logLevel !== void 0) {
|
|
6332
|
+
logger.setLogLevel(logLevel);
|
|
6333
|
+
}
|
|
5501
6334
|
if (this.isRegistered) {
|
|
5502
6335
|
logger.warn(
|
|
5503
6336
|
"Push service already registered, will unregister first and then re-register"
|
|
@@ -5512,6 +6345,17 @@ class WebPushSDK {
|
|
|
5512
6345
|
this.SDKAppID = SDKAppID;
|
|
5513
6346
|
this.appKey = appKey;
|
|
5514
6347
|
this.registrationID = userID;
|
|
6348
|
+
this.messagePopup = new MessagePopup({
|
|
6349
|
+
onClick: (message, _popup) => {
|
|
6350
|
+
this.serviceWorkerManager.postMessage({
|
|
6351
|
+
type: "REPORT_WEBPUSH_EVENT",
|
|
6352
|
+
payload: {
|
|
6353
|
+
...message,
|
|
6354
|
+
eventType: 3
|
|
6355
|
+
}
|
|
6356
|
+
});
|
|
6357
|
+
}
|
|
6358
|
+
});
|
|
5515
6359
|
if (chat) {
|
|
5516
6360
|
this.chat = chat;
|
|
5517
6361
|
} else {
|
|
@@ -5524,9 +6368,16 @@ class WebPushSDK {
|
|
|
5524
6368
|
SDKAppID: this.SDKAppID,
|
|
5525
6369
|
...options
|
|
5526
6370
|
});
|
|
6371
|
+
if (logLevel !== void 0) {
|
|
6372
|
+
this.chat.setLogLevel(logLevel);
|
|
6373
|
+
}
|
|
5527
6374
|
}
|
|
6375
|
+
this.addChatListener();
|
|
5528
6376
|
await this.serviceWorkerManager.register();
|
|
5529
|
-
|
|
6377
|
+
if (logLevel !== void 0) {
|
|
6378
|
+
await this.sendLogLevelToServiceWorker(logLevel);
|
|
6379
|
+
}
|
|
6380
|
+
await this.pushLogin();
|
|
5530
6381
|
const subscriptionInfo = await this.serviceWorkerManager.getPushSubscription(
|
|
5531
6382
|
this.vapidPublicKey
|
|
5532
6383
|
);
|
|
@@ -5553,6 +6404,11 @@ class WebPushSDK {
|
|
|
5553
6404
|
return true;
|
|
5554
6405
|
}
|
|
5555
6406
|
if (this.chat) {
|
|
6407
|
+
this.removeChatListener();
|
|
6408
|
+
}
|
|
6409
|
+
if (this.messagePopup) {
|
|
6410
|
+
this.messagePopup.destroy();
|
|
6411
|
+
this.messagePopup = null;
|
|
5556
6412
|
}
|
|
5557
6413
|
await this.serviceWorkerManager.unsubscribe();
|
|
5558
6414
|
await this.serviceWorkerManager.unregister();
|
|
@@ -5589,6 +6445,23 @@ class WebPushSDK {
|
|
|
5589
6445
|
throw new Error("Add push listener failed");
|
|
5590
6446
|
}
|
|
5591
6447
|
}
|
|
6448
|
+
/**
|
|
6449
|
+
* 内部方法:向 Service Worker 发送日志级别配置
|
|
6450
|
+
* @param logLevel 日志级别 0-4
|
|
6451
|
+
*/
|
|
6452
|
+
async sendLogLevelToServiceWorker(logLevel) {
|
|
6453
|
+
try {
|
|
6454
|
+
if (this.serviceWorkerManager) {
|
|
6455
|
+
await this.serviceWorkerManager.postMessage({
|
|
6456
|
+
type: "SET_LOG_LEVEL",
|
|
6457
|
+
payload: { logLevel }
|
|
6458
|
+
});
|
|
6459
|
+
logger.log("Log level sent to Service Worker:", logLevel);
|
|
6460
|
+
}
|
|
6461
|
+
} catch (error) {
|
|
6462
|
+
logger.warn("Failed to send log level to Service Worker", error);
|
|
6463
|
+
}
|
|
6464
|
+
}
|
|
5592
6465
|
removePushListener(eventName, listener) {
|
|
5593
6466
|
try {
|
|
5594
6467
|
Validator.validateEventType(eventName);
|
|
@@ -5645,7 +6518,7 @@ class WebPushSDK {
|
|
|
5645
6518
|
throw error;
|
|
5646
6519
|
}
|
|
5647
6520
|
}
|
|
5648
|
-
async
|
|
6521
|
+
async pushLogin() {
|
|
5649
6522
|
try {
|
|
5650
6523
|
const res = await this.chat.callExperimentalAPI("loginWebPush", {
|
|
5651
6524
|
userID: this.registrationID,
|
|
@@ -5653,7 +6526,8 @@ class WebPushSDK {
|
|
|
5653
6526
|
SDKAppID: this.SDKAppID,
|
|
5654
6527
|
secretKey: this.appKey,
|
|
5655
6528
|
userID: this.registrationID
|
|
5656
|
-
}).userSig
|
|
6529
|
+
}).userSig,
|
|
6530
|
+
pushSDKVersion: version
|
|
5657
6531
|
});
|
|
5658
6532
|
if (res.data.vapid) {
|
|
5659
6533
|
this.vapidPublicKey = res.data.vapid;
|
|
@@ -5671,39 +6545,124 @@ class WebPushSDK {
|
|
|
5671
6545
|
throw error;
|
|
5672
6546
|
}
|
|
5673
6547
|
}
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5701
|
-
|
|
5702
|
-
|
|
5703
|
-
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
|
|
6548
|
+
onMessageReceived(event) {
|
|
6549
|
+
logger.log("Received message data", event);
|
|
6550
|
+
event.data.forEach((item) => {
|
|
6551
|
+
const { webPush: webPush2 } = item;
|
|
6552
|
+
const { content, info, extension } = webPush2;
|
|
6553
|
+
const { TaskId, WebpushReportUrl, OnlineClickExt } = extension;
|
|
6554
|
+
if (content) {
|
|
6555
|
+
try {
|
|
6556
|
+
const message = JSON.parse(content);
|
|
6557
|
+
const outerMessage = {
|
|
6558
|
+
id: TaskId,
|
|
6559
|
+
...message
|
|
6560
|
+
};
|
|
6561
|
+
this.eventEmitter.emit(EVENT.MESSAGE_RECEIVED, outerMessage);
|
|
6562
|
+
if (message.MsgType !== "custom") {
|
|
6563
|
+
const messageWithExtras = {
|
|
6564
|
+
...outerMessage,
|
|
6565
|
+
rptURL: WebpushReportUrl,
|
|
6566
|
+
rptExt: OnlineClickExt
|
|
6567
|
+
};
|
|
6568
|
+
if (this.messagePopup && document.visibilityState === "visible") {
|
|
6569
|
+
this.messagePopup.show(messageWithExtras);
|
|
6570
|
+
} else if (this.messagePopup) {
|
|
6571
|
+
this.pendingMessages.push(messageWithExtras);
|
|
6572
|
+
logger.log(
|
|
6573
|
+
"Message added to pending queue (page hidden)",
|
|
6574
|
+
TaskId
|
|
6575
|
+
);
|
|
6576
|
+
}
|
|
6577
|
+
}
|
|
6578
|
+
} catch (error) {
|
|
6579
|
+
logger.error("Failed to parse message content", error);
|
|
6580
|
+
this.eventEmitter.emit(EVENT.MESSAGE_RECEIVED, content);
|
|
6581
|
+
}
|
|
6582
|
+
} else if (info) {
|
|
6583
|
+
try {
|
|
6584
|
+
this.sendNotificationToServiceWorker({
|
|
6585
|
+
id: TaskId,
|
|
6586
|
+
...info,
|
|
6587
|
+
rptURL: WebpushReportUrl,
|
|
6588
|
+
rptExt: OnlineClickExt
|
|
6589
|
+
});
|
|
6590
|
+
} catch (error) {
|
|
6591
|
+
logger.error("Failed to send notification to service worker", error);
|
|
6592
|
+
this.eventEmitter.emit(EVENT.MESSAGE_RECEIVED, info);
|
|
6593
|
+
}
|
|
6594
|
+
}
|
|
6595
|
+
});
|
|
6596
|
+
}
|
|
6597
|
+
onMessageRevoked(event) {
|
|
6598
|
+
event.data.forEach((item) => {
|
|
6599
|
+
const { ID } = item;
|
|
6600
|
+
logger.log("Message revoked", ID);
|
|
6601
|
+
const isPopupMessage = this.messagePopup && this.messagePopup.hasMessage(ID);
|
|
6602
|
+
const pendingIndex = this.pendingMessages.findIndex(
|
|
6603
|
+
(msg) => msg.id === ID
|
|
6604
|
+
);
|
|
6605
|
+
if (pendingIndex !== -1) {
|
|
6606
|
+
this.pendingMessages.splice(pendingIndex, 1);
|
|
6607
|
+
logger.log("Pending message removed from queue", ID);
|
|
6608
|
+
this.eventEmitter.emit(EVENT.MESSAGE_REVOKED, {
|
|
6609
|
+
messageID: ID
|
|
6610
|
+
});
|
|
6611
|
+
return;
|
|
6612
|
+
}
|
|
6613
|
+
if (isPopupMessage) {
|
|
6614
|
+
this.messagePopup.close(ID);
|
|
6615
|
+
this.eventEmitter.emit(EVENT.MESSAGE_REVOKED, {
|
|
6616
|
+
messageID: ID
|
|
6617
|
+
});
|
|
6618
|
+
logger.log("Popup message revoked and closed", ID);
|
|
6619
|
+
} else {
|
|
6620
|
+
try {
|
|
6621
|
+
this.sendMessageRevokeToServiceWorker(ID);
|
|
6622
|
+
logger.log("Message revoke sent to service worker", ID);
|
|
6623
|
+
} catch (error) {
|
|
6624
|
+
logger.error(
|
|
6625
|
+
"Failed to send message revoke to service worker",
|
|
6626
|
+
error
|
|
6627
|
+
);
|
|
6628
|
+
this.eventEmitter.emit(EVENT.MESSAGE_REVOKED, {
|
|
6629
|
+
messageID: ID
|
|
6630
|
+
});
|
|
6631
|
+
}
|
|
6632
|
+
}
|
|
6633
|
+
});
|
|
6634
|
+
}
|
|
6635
|
+
addChatListener() {
|
|
6636
|
+
if (!this.chat)
|
|
6637
|
+
return;
|
|
6638
|
+
try {
|
|
6639
|
+
this.chat.on(
|
|
6640
|
+
ChatSDK.EVENT.WEB_PUSH_MESSAGE_RECEIVED,
|
|
6641
|
+
this.onMessageReceived.bind(this)
|
|
6642
|
+
);
|
|
6643
|
+
this.chat.on(
|
|
6644
|
+
ChatSDK.EVENT.MESSAGE_REVOKED,
|
|
6645
|
+
this.onMessageRevoked.bind(this)
|
|
6646
|
+
);
|
|
6647
|
+
logger.log("Chat listeners added for online push");
|
|
6648
|
+
} catch (error) {
|
|
6649
|
+
logger.error("Failed to add chat listeners", error);
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
removeChatListener() {
|
|
6653
|
+
if (!this.chat)
|
|
6654
|
+
return;
|
|
6655
|
+
try {
|
|
6656
|
+
this.chat.off(
|
|
6657
|
+
ChatSDK.EVENT.WEB_PUSH_MESSAGE_RECEIVED,
|
|
6658
|
+
this.onMessageReceived
|
|
6659
|
+
);
|
|
6660
|
+
this.chat.off(ChatSDK.EVENT.MESSAGE_REVOKED, this.onMessageRevoked);
|
|
6661
|
+
logger.log("Chat listeners removed");
|
|
6662
|
+
} catch (error) {
|
|
6663
|
+
logger.error("Failed to remove chat listeners", error);
|
|
6664
|
+
}
|
|
6665
|
+
}
|
|
5707
6666
|
getSystemPermissionMessage(browserName) {
|
|
5708
6667
|
const userAgent = navigator.userAgent.toLowerCase();
|
|
5709
6668
|
const isMacOS = userAgent.includes("mac os");
|
|
@@ -5779,12 +6738,35 @@ Please refresh the page after enabling notifications.`;
|
|
|
5779
6738
|
logger.error("Browser compatibility initialization failed", error);
|
|
5780
6739
|
}
|
|
5781
6740
|
}
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
if (
|
|
5785
|
-
|
|
6741
|
+
setupVisibilityChangeListener() {
|
|
6742
|
+
document.addEventListener("visibilitychange", () => {
|
|
6743
|
+
if (document.visibilityState === "visible" && this.messagePopup && this.pendingMessages.length > 0) {
|
|
6744
|
+
logger.log(
|
|
6745
|
+
"Page became visible, showing pending messages",
|
|
6746
|
+
this.pendingMessages.length
|
|
6747
|
+
);
|
|
6748
|
+
const messagesToShow = [...this.pendingMessages];
|
|
6749
|
+
this.pendingMessages = [];
|
|
6750
|
+
const timeout = setTimeout(() => {
|
|
6751
|
+
messagesToShow.forEach((message) => {
|
|
6752
|
+
if (this.messagePopup) {
|
|
6753
|
+
this.messagePopup.show(message);
|
|
6754
|
+
}
|
|
6755
|
+
});
|
|
6756
|
+
clearTimeout(timeout);
|
|
6757
|
+
}, 100);
|
|
5786
6758
|
}
|
|
5787
6759
|
});
|
|
6760
|
+
}
|
|
6761
|
+
setupInternalListeners() {
|
|
6762
|
+
this.eventEmitter.on(
|
|
6763
|
+
EVENT.MESSAGE_RECEIVED,
|
|
6764
|
+
(message) => {
|
|
6765
|
+
if (this.SDKAppID && this.registrationID && message.messageID) {
|
|
6766
|
+
this.pushStatistics(message.messageID, "reach");
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
6769
|
+
);
|
|
5788
6770
|
this.eventEmitter.on(EVENT.NOTIFICATION_CLICKED, (data) => {
|
|
5789
6771
|
if (this.SDKAppID && this.registrationID && data.notification?.messageID) {
|
|
5790
6772
|
this.pushStatistics(data.notification.messageID, "click");
|
|
@@ -5815,83 +6797,61 @@ Please refresh the page after enabling notifications.`;
|
|
|
5815
6797
|
this.SDKAppID = 0;
|
|
5816
6798
|
this.appKey = "";
|
|
5817
6799
|
this.vapidPublicKey = "";
|
|
6800
|
+
this.pendingMessages = [];
|
|
6801
|
+
if (this.messagePopup) {
|
|
6802
|
+
this.messagePopup.destroy();
|
|
6803
|
+
this.messagePopup = null;
|
|
6804
|
+
}
|
|
5818
6805
|
}
|
|
5819
6806
|
/**
|
|
5820
|
-
* 向 service-worker
|
|
5821
|
-
* @param
|
|
5822
|
-
* @param data 通知数据
|
|
6807
|
+
* 向 service-worker 发送通知消息,使用与 push 事件相同的数据格式
|
|
6808
|
+
* @param webpushInfo webpush 信息,格式与 SW push 事件接收的数据一致
|
|
5823
6809
|
*/
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
// tag: `${type}-${data.messageID || Date.now()}`,
|
|
5842
|
-
// requireInteraction: false,
|
|
5843
|
-
// silent: false,
|
|
5844
|
-
// timestamp: data.timestamp || Date.now(),
|
|
5845
|
-
// data: {
|
|
5846
|
-
// messageID: data.messageID || data.data?.messageID,
|
|
5847
|
-
// type: type,
|
|
5848
|
-
// SDKAppID: this.SDKAppID,
|
|
5849
|
-
// registrationID: this.registrationID
|
|
5850
|
-
// }
|
|
5851
|
-
// }
|
|
5852
|
-
// }
|
|
5853
|
-
// });
|
|
5854
|
-
// logger.log(`Notification sent to service-worker: ${type}`, data);
|
|
5855
|
-
// } catch (error) {
|
|
5856
|
-
// logger.error(`Failed to send notification to service-worker: ${type}`, error);
|
|
5857
|
-
// }
|
|
5858
|
-
// }
|
|
6810
|
+
async sendNotificationToServiceWorker(webpushInfo) {
|
|
6811
|
+
try {
|
|
6812
|
+
if (!this.serviceWorkerManager) {
|
|
6813
|
+
logger.warn(
|
|
6814
|
+
"ServiceWorkerManager not initialized, skipping notification"
|
|
6815
|
+
);
|
|
6816
|
+
return;
|
|
6817
|
+
}
|
|
6818
|
+
await this.serviceWorkerManager.postMessage({
|
|
6819
|
+
type: "PROCESS_WEBPUSH_DATA",
|
|
6820
|
+
payload: webpushInfo
|
|
6821
|
+
});
|
|
6822
|
+
logger.log("WebPush data sent to service-worker", webpushInfo);
|
|
6823
|
+
} catch (error) {
|
|
6824
|
+
logger.error("Failed to send webpush data to service-worker", error);
|
|
6825
|
+
}
|
|
6826
|
+
}
|
|
5859
6827
|
/**
|
|
5860
|
-
*
|
|
5861
|
-
* @param
|
|
5862
|
-
* @param data 通知数据
|
|
5863
|
-
* @returns 格式化后的通知内容
|
|
6828
|
+
* 向 service-worker 发送消息撤回请求
|
|
6829
|
+
* @param messageID 要撤回的消息ID
|
|
5864
6830
|
*/
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
|
|
5878
|
-
|
|
5879
|
-
|
|
5880
|
-
|
|
5881
|
-
|
|
5882
|
-
|
|
5883
|
-
// return '有一条消息被撤回';
|
|
5884
|
-
// }
|
|
5885
|
-
// return '您有新的消息通知';
|
|
5886
|
-
// } catch (error) {
|
|
5887
|
-
// logger.error('Failed to format notification body', error);
|
|
5888
|
-
// return '您有新的消息通知';
|
|
5889
|
-
// }
|
|
5890
|
-
// }
|
|
6831
|
+
async sendMessageRevokeToServiceWorker(messageID) {
|
|
6832
|
+
try {
|
|
6833
|
+
if (!this.serviceWorkerManager) {
|
|
6834
|
+
logger.warn(
|
|
6835
|
+
"ServiceWorkerManager not initialized, skipping message revoke"
|
|
6836
|
+
);
|
|
6837
|
+
return;
|
|
6838
|
+
}
|
|
6839
|
+
await this.serviceWorkerManager.postMessage({
|
|
6840
|
+
type: "REVOKE_MESSAGE",
|
|
6841
|
+
payload: { messageID }
|
|
6842
|
+
});
|
|
6843
|
+
logger.log("Message revoke sent to service-worker", messageID);
|
|
6844
|
+
} catch (error) {
|
|
6845
|
+
logger.error("Failed to send message revoke to service-worker", error);
|
|
6846
|
+
throw error;
|
|
6847
|
+
}
|
|
6848
|
+
}
|
|
5891
6849
|
}
|
|
5892
6850
|
const webPush = WebPushSDK.getInstance();
|
|
5893
6851
|
export {
|
|
5894
6852
|
EVENT,
|
|
6853
|
+
MessagePopup,
|
|
6854
|
+
Placement,
|
|
5895
6855
|
webPush as default,
|
|
5896
6856
|
webPush
|
|
5897
6857
|
};
|