@tencentcloud/web-push 1.0.3 → 1.0.4

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +100 -92
  3. package/{dist/index.esm.js → index.esm.js} +1 -1
  4. package/{dist/index.umd.js → index.umd.js} +1 -1
  5. package/package.json +9 -47
  6. package/src/__tests__/index.test.ts +0 -120
  7. package/src/__tests__/integration.test.ts +0 -285
  8. package/src/__tests__/setup.ts +0 -210
  9. package/src/__tests__/types.test.ts +0 -303
  10. package/src/__tests__/web-push-sdk.test.ts +0 -257
  11. package/src/components/message-popup.ts +0 -1007
  12. package/src/core/event-emitter.ts +0 -61
  13. package/src/core/service-worker-manager.ts +0 -614
  14. package/src/core/web-push-sdk.ts +0 -690
  15. package/src/debug/GenerateTestUserSig.js +0 -37
  16. package/src/debug/index.d.ts +0 -6
  17. package/src/debug/index.js +0 -1
  18. package/src/debug/lib-generate-test-usersig-es.min.js +0 -2
  19. package/src/index.ts +0 -9
  20. package/src/service-worker/sw.ts +0 -494
  21. package/src/types/index.ts +0 -2
  22. package/src/types/inner.ts +0 -44
  23. package/src/types/outer.ts +0 -142
  24. package/src/utils/browser-support.ts +0 -412
  25. package/src/utils/logger.ts +0 -66
  26. package/src/utils/storage.ts +0 -51
  27. package/src/utils/validator.ts +0 -267
  28. /package/{dist/index.d.ts → index.d.ts} +0 -0
  29. /package/{dist/src → src}/components/message-popup.d.ts +0 -0
  30. /package/{dist/src → src}/core/event-emitter.d.ts +0 -0
  31. /package/{dist/src → src}/core/service-worker-manager.d.ts +0 -0
  32. /package/{dist/src → src}/core/web-push-sdk.d.ts +0 -0
  33. /package/{dist/src → src}/index.d.ts +0 -0
  34. /package/{dist/src → src}/service-worker/sw.d.ts +0 -0
  35. /package/{dist/src → src}/types/index.d.ts +0 -0
  36. /package/{dist/src → src}/types/inner.d.ts +0 -0
  37. /package/{dist/src → src}/types/outer.d.ts +0 -0
  38. /package/{dist/src → src}/utils/browser-support.d.ts +0 -0
  39. /package/{dist/src → src}/utils/logger.d.ts +0 -0
  40. /package/{dist/src → src}/utils/storage.d.ts +0 -0
  41. /package/{dist/src → src}/utils/validator.d.ts +0 -0
  42. /package/{dist/sw.js → sw.js} +0 -0
@@ -1,690 +0,0 @@
1
- import ChatSDK from '@tencentcloud/lite-chat/professional';
2
- import { version } from '../../package.json';
3
- import {
4
- WebPushSDK as IWebPushSDK,
5
- RegisterPushOptions,
6
- EVENT,
7
- NotificationMessage,
8
- SubscriptionInfo,
9
- MessageReceivedData,
10
- } from '../types';
11
- import { EventEmitter } from './event-emitter';
12
- import { ServiceWorkerManager } from './service-worker-manager';
13
- import { MessagePopup } from '../components/message-popup';
14
- import { logger } from '../utils/logger';
15
- import { Validator, ValidationError } from '../utils/validator';
16
- import { browserSupport } from '../utils/browser-support';
17
- import { genTestUserSig } from '../debug';
18
-
19
- export class WebPushSDK implements IWebPushSDK {
20
- static instance: WebPushSDK;
21
-
22
- private eventEmitter: EventEmitter;
23
- private serviceWorkerManager: ServiceWorkerManager;
24
- private messagePopup: MessagePopup | null = null;
25
- private isRegistered: boolean = false;
26
- private registrationID: string = '';
27
- private chat: any = null;
28
- private SDKAppID: number = 0;
29
- private appKey: string = '';
30
- private vapidPublicKey: string = '';
31
- private pendingMessages: any[] = []; // 存储页面隐藏时接收的消息
32
-
33
- public EVENT = EVENT;
34
- public VERSION: string = version;
35
-
36
- constructor() {
37
- logger.log('version:', version);
38
-
39
- this.eventEmitter = new EventEmitter();
40
- this.serviceWorkerManager = ServiceWorkerManager.getInstance(
41
- this.eventEmitter
42
- );
43
-
44
- this.initializeBrowserCompatibility().catch((error) => {
45
- logger.error('Browser compatibility initialization failed', error);
46
- });
47
-
48
- this.setupInternalListeners();
49
- this.setupVisibilityChangeListener();
50
- }
51
-
52
- static getInstance() {
53
- if (!this.instance) {
54
- this.instance = new WebPushSDK();
55
- }
56
- return this.instance;
57
- }
58
-
59
- async registerPush(options?: RegisterPushOptions) {
60
- try {
61
- Validator.validateRegisterPushOptions(options);
62
-
63
- const { SDKAppID, appKey, userID, chat, logLevel } = options!;
64
-
65
- // 设置主线程日志级别
66
- if (logLevel !== undefined) {
67
- logger.setLogLevel(logLevel);
68
- }
69
-
70
- if (this.isRegistered) {
71
- logger.warn(
72
- 'Push service already registered, will unregister first and then re-register'
73
- );
74
- await this.unRegisterPush();
75
- }
76
-
77
- this.checkBrowserSupport();
78
-
79
- const permission = await this.requestNotificationPermission();
80
- if (permission !== 'granted') {
81
- throw new Error('User denied notification permission');
82
- }
83
-
84
- this.SDKAppID = SDKAppID;
85
- this.appKey = appKey;
86
- this.registrationID = userID;
87
-
88
- // 初始化弹窗组件(使用默认配置)
89
- this.messagePopup = new MessagePopup({
90
- onClick: (message: any, _popup: HTMLElement) => {
91
- this.serviceWorkerManager.postMessage({
92
- type: 'REPORT_WEBPUSH_EVENT',
93
- payload: {
94
- ...message,
95
- eventType: 3,
96
- },
97
- });
98
- },
99
- });
100
-
101
- if (chat) {
102
- this.chat = chat;
103
- } else {
104
- // 检查 ChatSDK 是否可用
105
- if (typeof ChatSDK === 'undefined') {
106
- throw new Error(
107
- 'TencentCloudChat SDK is not available. Please ensure you have imported @tencentcloud/lite-chat/professional or provided a chat instance in the options.'
108
- );
109
- }
110
-
111
- this.chat = ChatSDK.create({
112
- SDKAppID: this.SDKAppID,
113
- ...options,
114
- });
115
- if (logLevel !== undefined) {
116
- this.chat.setLogLevel(logLevel);
117
- }
118
- }
119
-
120
- // 启用在线推送监听
121
- this.addChatListener();
122
-
123
- await this.serviceWorkerManager.register();
124
-
125
- // 向 Service Worker 发送日志级别配置
126
- if (logLevel !== undefined) {
127
- await this.sendLogLevelToServiceWorker(logLevel);
128
- }
129
-
130
- await this.pushLogin();
131
-
132
- const subscriptionInfo =
133
- await this.serviceWorkerManager.getPushSubscription(
134
- this.vapidPublicKey
135
- );
136
-
137
- await this.setToken(subscriptionInfo);
138
-
139
- this.isRegistered = true;
140
-
141
- logger.log('Push service registration successful', this.registrationID);
142
- return this.registrationID;
143
- } catch (error) {
144
- if (error instanceof ValidationError) {
145
- logger.error(
146
- 'Push service registration parameter validation failed',
147
- error.message
148
- );
149
- throw error;
150
- }
151
- logger.error('Push service registration failed', error);
152
- throw error;
153
- }
154
- }
155
-
156
- async unRegisterPush() {
157
- try {
158
- if (!this.isRegistered) {
159
- logger.warn('Push service is not registered, no need to unregister');
160
- return true;
161
- }
162
-
163
- if (this.chat) {
164
- this.removeChatListener();
165
- }
166
-
167
- // 销毁弹窗组件
168
- if (this.messagePopup) {
169
- this.messagePopup.destroy();
170
- this.messagePopup = null;
171
- }
172
-
173
- await this.serviceWorkerManager.unsubscribe();
174
- await this.serviceWorkerManager.unregister();
175
- await this.chat.callExperimentalAPI('logoutWebPush');
176
-
177
- this.isRegistered = false;
178
- this.registrationID = '';
179
- this.SDKAppID = 0;
180
- this.appKey = '';
181
- this.vapidPublicKey = '';
182
- this.clearState();
183
-
184
- logger.log('Push service unregistration successful');
185
- return true;
186
- } catch (error) {
187
- logger.error('Push service unregistration failed', error);
188
- return false;
189
- }
190
- }
191
-
192
- addPushListener(eventName: EVENT, listener: Function) {
193
- try {
194
- Validator.validateEventType(eventName);
195
- Validator.validateListener(listener);
196
-
197
- const listenerId = this.eventEmitter.on(eventName, listener);
198
- logger.log('Add push listener', eventName, listenerId);
199
- return listenerId;
200
- } catch (error) {
201
- if (error instanceof ValidationError) {
202
- logger.error(
203
- 'Add push listener parameter validation failed',
204
- error.message
205
- );
206
- throw error;
207
- }
208
- logger.error('Add push listener failed', error);
209
- throw new Error('Add push listener failed');
210
- }
211
- }
212
-
213
- /**
214
- * 内部方法:向 Service Worker 发送日志级别配置
215
- * @param logLevel 日志级别 0-4
216
- */
217
- private async sendLogLevelToServiceWorker(
218
- logLevel: 0 | 1 | 2 | 3 | 4
219
- ): Promise<void> {
220
- try {
221
- if (this.serviceWorkerManager) {
222
- await this.serviceWorkerManager.postMessage({
223
- type: 'SET_LOG_LEVEL',
224
- payload: { logLevel },
225
- });
226
- logger.log('Log level sent to Service Worker:', logLevel);
227
- }
228
- } catch (error) {
229
- logger.warn('Failed to send log level to Service Worker', error);
230
- }
231
- }
232
-
233
- removePushListener(eventName: EVENT, listener: Function) {
234
- try {
235
- Validator.validateEventType(eventName);
236
- Validator.validateListener(listener);
237
-
238
- const result = this.eventEmitter.off(eventName, listener);
239
- logger.log('Remove push listener', eventName, result);
240
- return result;
241
- } catch (error) {
242
- if (error instanceof ValidationError) {
243
- logger.error(
244
- 'Remove push listener parameter validation failed',
245
- error.message
246
- );
247
- throw error;
248
- }
249
- logger.error('Remove push listener failed', error);
250
- return false;
251
- }
252
- }
253
-
254
- private checkBrowserSupport(): void {
255
- if (!browserSupport.checkBrowserSupport()) {
256
- const capability = browserSupport.detectWebPushCapability();
257
- throw new Error(`Browser not supported: ${capability.reason}`);
258
- }
259
- }
260
-
261
- private async requestNotificationPermission(): Promise<NotificationPermission> {
262
- try {
263
- const currentPermission =
264
- await browserSupport.checkNotificationPermission();
265
-
266
- if (currentPermission === 'granted') {
267
- return 'granted';
268
- }
269
-
270
- const capability = browserSupport.detectWebPushCapability();
271
- const browserName = capability.browserName;
272
-
273
- if (currentPermission === 'denied') {
274
- const errorMessage = `Notification permission denied for ${browserName}. Please check your system settings.`;
275
- throw new Error(errorMessage);
276
- }
277
-
278
- if (browserSupport.requiresUserGesture()) {
279
- logger.warn(
280
- 'Current browser requires user gesture to request notification permission'
281
- );
282
- }
283
-
284
- const permission = await browserSupport.requestNotificationPermission();
285
-
286
- if (permission !== 'granted') {
287
- throw new Error(
288
- `User denied notification permission for ${browserName}`
289
- );
290
- } else {
291
- this.showSystemPermissionAlert(browserName);
292
- }
293
-
294
- return permission;
295
- } catch (error) {
296
- logger.error('Request notification permission failed', error);
297
- throw error;
298
- }
299
- }
300
-
301
- private async pushLogin(): Promise<void> {
302
- try {
303
- const res = await this.chat.callExperimentalAPI('loginWebPush', {
304
- userID: this.registrationID,
305
- userSig: genTestUserSig({
306
- SDKAppID: this.SDKAppID,
307
- secretKey: this.appKey,
308
- userID: this.registrationID,
309
- }).userSig,
310
- pushSDKVersion: version,
311
- });
312
- if (res.data.vapid) {
313
- this.vapidPublicKey = res.data.vapid;
314
- } else {
315
- logger.error('Failed to fetch VAPID public key');
316
- }
317
- } catch (error: any) {
318
- // 处理专业版功能错误码
319
- if (error?.code === 2905) {
320
- const modifiedError = new Error(
321
- 'The API you are calling is only available in the Professional edition. Please change your import from @tencentcloud/lite-chat to @tencentcloud/lite-chat/professional to access this feature.'
322
- );
323
- (modifiedError as any).code = error.code;
324
- throw modifiedError;
325
- }
326
-
327
- throw error;
328
- }
329
- }
330
-
331
- private onMessageReceived(event: any) {
332
- logger.log('Received message data', event);
333
- event.data.forEach((item: any) => {
334
- const { webPush } = item;
335
- const { content, info, extension } = webPush as MessageReceivedData;
336
- const { TaskId, WebpushReportUrl, OnlineClickExt } = extension;
337
-
338
- if (content) {
339
- try {
340
- const message = JSON.parse(content);
341
- const outerMessage = {
342
- id: TaskId,
343
- ...message,
344
- };
345
- this.eventEmitter.emit(EVENT.MESSAGE_RECEIVED, outerMessage);
346
-
347
- if (message.MsgType !== 'custom') {
348
- const messageWithExtras = {
349
- ...outerMessage,
350
- rptURL: WebpushReportUrl,
351
- rptExt: OnlineClickExt,
352
- };
353
-
354
- if (this.messagePopup && document.visibilityState === 'visible') {
355
- this.messagePopup.show(messageWithExtras);
356
- } else if (this.messagePopup) {
357
- this.pendingMessages.push(messageWithExtras);
358
- logger.log(
359
- 'Message added to pending queue (page hidden)',
360
- TaskId
361
- );
362
- }
363
- }
364
- } catch (error) {
365
- logger.error('Failed to parse message content', error);
366
- this.eventEmitter.emit(EVENT.MESSAGE_RECEIVED, content);
367
- }
368
- } else if (info) {
369
- try {
370
- this.sendNotificationToServiceWorker({
371
- id: TaskId,
372
- ...info,
373
- rptURL: WebpushReportUrl,
374
- rptExt: OnlineClickExt,
375
- });
376
- } catch (error) {
377
- logger.error('Failed to send notification to service worker', error);
378
- this.eventEmitter.emit(EVENT.MESSAGE_RECEIVED, info);
379
- }
380
- }
381
- });
382
- }
383
-
384
- private onMessageRevoked(event: any) {
385
- event.data.forEach((item: { ID: any }) => {
386
- const { ID } = item;
387
- logger.log('Message revoked', ID);
388
-
389
- const isPopupMessage =
390
- this.messagePopup && this.messagePopup.hasMessage(ID);
391
-
392
- // 检查待处理消息队列中是否有该消息
393
- const pendingIndex = this.pendingMessages.findIndex(
394
- (msg) => msg.id === ID
395
- );
396
- if (pendingIndex !== -1) {
397
- this.pendingMessages.splice(pendingIndex, 1);
398
- logger.log('Pending message removed from queue', ID);
399
-
400
- this.eventEmitter.emit(EVENT.MESSAGE_REVOKED, {
401
- messageID: ID,
402
- });
403
- return;
404
- }
405
-
406
- if (isPopupMessage) {
407
- this.messagePopup!.close(ID);
408
-
409
- this.eventEmitter.emit(EVENT.MESSAGE_REVOKED, {
410
- messageID: ID,
411
- });
412
-
413
- logger.log('Popup message revoked and closed', ID);
414
- } else {
415
- try {
416
- this.sendMessageRevokeToServiceWorker(ID);
417
- logger.log('Message revoke sent to service worker', ID);
418
- } catch (error) {
419
- logger.error(
420
- 'Failed to send message revoke to service worker',
421
- error
422
- );
423
- this.eventEmitter.emit(EVENT.MESSAGE_REVOKED, {
424
- messageID: ID,
425
- });
426
- }
427
- }
428
- });
429
- }
430
-
431
- private addChatListener() {
432
- if (!this.chat) return;
433
-
434
- try {
435
- this.chat.on(
436
- ChatSDK.EVENT.WEB_PUSH_MESSAGE_RECEIVED,
437
- this.onMessageReceived.bind(this)
438
- );
439
- this.chat.on(
440
- ChatSDK.EVENT.MESSAGE_REVOKED,
441
- this.onMessageRevoked.bind(this)
442
- );
443
- logger.log('Chat listeners added for online push');
444
- } catch (error) {
445
- logger.error('Failed to add chat listeners', error);
446
- }
447
- }
448
-
449
- private removeChatListener() {
450
- if (!this.chat) return;
451
-
452
- try {
453
- this.chat.off(
454
- ChatSDK.EVENT.WEB_PUSH_MESSAGE_RECEIVED,
455
- this.onMessageReceived
456
- );
457
- this.chat.off(ChatSDK.EVENT.MESSAGE_REVOKED, this.onMessageRevoked);
458
- logger.log('Chat listeners removed');
459
- } catch (error) {
460
- logger.error('Failed to remove chat listeners', error);
461
- }
462
- }
463
-
464
- private getSystemPermissionMessage(browserName: string): string {
465
- const userAgent = navigator.userAgent.toLowerCase();
466
- const isMacOS = userAgent.includes('mac os');
467
-
468
- if (isMacOS) {
469
- return `For macOS: System Preferences > Notifications > ${browserName}, then enable notifications.`;
470
- } else {
471
- return `For Windows: Settings > Privacy > Notifications > ${browserName}, then enable notifications.`;
472
- }
473
- }
474
-
475
- private showSystemPermissionAlert(browserName: string): void {
476
- const message = this.getSystemPermissionMessage(browserName);
477
- const fullMessage = `System notification permission for ${browserName}.\n\n${message}\n\nPlease refresh the page after enabling notifications.`;
478
- alert(fullMessage);
479
- }
480
-
481
- private getBrowserInstType(): number {
482
- const userAgent = navigator.userAgent.toLowerCase();
483
-
484
- if (userAgent.includes('edg/')) {
485
- return 3003; // Edge
486
- } else if (userAgent.includes('yabrowser/')) {
487
- return 3004; // Yandex
488
- } else if (userAgent.includes('opr/') || userAgent.includes('opera/')) {
489
- return 3005; // Opera
490
- } else if (userAgent.includes('chrome/') && !userAgent.includes('edg/')) {
491
- return 3000; // Chrome
492
- } else if (userAgent.includes('firefox/')) {
493
- return 3001; // Firefox
494
- } else if (
495
- userAgent.includes('safari/') &&
496
- !userAgent.includes('chrome/')
497
- ) {
498
- return 3002; // Safari
499
- } else {
500
- return 1; // 未知或其他浏览器
501
- }
502
- }
503
-
504
- private async setToken(subscriptionInfo: SubscriptionInfo): Promise<void> {
505
- try {
506
- const capability = browserSupport.detectWebPushCapability();
507
- const browserInfo = browserSupport.getBrowserInfo();
508
-
509
- const data = {
510
- browserType: this.getBrowserInstType(),
511
- pushToken: subscriptionInfo.endpoint,
512
- webPushAuthKey: subscriptionInfo.auth,
513
- webPushP256: subscriptionInfo.p256dh,
514
- pushSDKVersion: version,
515
- browserVersion: `${capability.browserName} ${capability.browserVersion}`,
516
- browserPlatform: browserInfo.platform,
517
- browserLanguage: browserInfo.language,
518
- };
519
-
520
- const res = await this.chat.callExperimentalAPI('setWebPushToken', data);
521
- return res;
522
- } catch (error) {
523
- logger.error('Device registration failed', error);
524
- throw error;
525
- }
526
- }
527
-
528
- private async initializeBrowserCompatibility(): Promise<void> {
529
- try {
530
- const capability = browserSupport.detectWebPushCapability();
531
-
532
- logger.log('Browser Web Push capability initialization completed', {
533
- browser: `${capability.browserName} ${capability.browserVersion}`,
534
- supported: capability.supported,
535
- reason: capability.reason,
536
- });
537
-
538
- if (!capability.supported) {
539
- logger.warn(
540
- '[WebPush] Browser compatibility warning:',
541
- capability.reason
542
- );
543
- }
544
- } catch (error) {
545
- logger.error('Browser compatibility initialization failed', error);
546
- }
547
- }
548
-
549
- private setupVisibilityChangeListener(): void {
550
- document.addEventListener('visibilitychange', () => {
551
- if (
552
- document.visibilityState === 'visible' &&
553
- this.messagePopup &&
554
- this.pendingMessages.length > 0
555
- ) {
556
- logger.log(
557
- 'Page became visible, showing pending messages',
558
- this.pendingMessages.length
559
- );
560
-
561
- const messagesToShow = [...this.pendingMessages];
562
- this.pendingMessages = [];
563
-
564
- const timeout = setTimeout(() => {
565
- messagesToShow.forEach((message) => {
566
- if (this.messagePopup) {
567
- this.messagePopup.show(message);
568
- }
569
- });
570
- clearTimeout(timeout);
571
- }, 100);
572
- }
573
- });
574
- }
575
-
576
- private setupInternalListeners(): void {
577
- this.eventEmitter.on(
578
- EVENT.MESSAGE_RECEIVED,
579
- (message: NotificationMessage) => {
580
- if (this.SDKAppID && this.registrationID && message.messageID) {
581
- this.pushStatistics(message.messageID, 'reach');
582
- }
583
- }
584
- );
585
-
586
- this.eventEmitter.on(EVENT.NOTIFICATION_CLICKED, (data: any) => {
587
- if (
588
- this.SDKAppID &&
589
- this.registrationID &&
590
- data.notification?.messageID
591
- ) {
592
- this.pushStatistics(data.notification.messageID, 'click');
593
- }
594
- });
595
- }
596
-
597
- private async pushStatistics(messageID: string, type: string): Promise<void> {
598
- try {
599
- if (!this.chat) {
600
- logger.warn('Chat SDK not initialized, skipping statistics');
601
- return;
602
- }
603
-
604
- const data = {
605
- messageID,
606
- type,
607
- timestamp: Date.now(),
608
- SDKAppID: this.SDKAppID,
609
- registrationID: this.registrationID,
610
- };
611
-
612
- // Call chat pushStatistics API
613
- // await this.chat.callExperimentalAPI('pushStatistics', data);
614
- logger.log(`Message ${type} statistics recorded`, data);
615
- } catch (error) {
616
- logger.error(`Failed to record message ${type} statistics`, error);
617
- }
618
- }
619
-
620
- private clearState(): void {
621
- this.isRegistered = false;
622
- this.registrationID = '';
623
- this.SDKAppID = 0;
624
- this.appKey = '';
625
- this.vapidPublicKey = '';
626
- this.pendingMessages = []; // 清空待处理消息
627
-
628
- // 清理弹窗
629
- if (this.messagePopup) {
630
- this.messagePopup.destroy();
631
- this.messagePopup = null;
632
- }
633
- }
634
-
635
- /**
636
- * 向 service-worker 发送通知消息,使用与 push 事件相同的数据格式
637
- * @param webpushInfo webpush 信息,格式与 SW push 事件接收的数据一致
638
- */
639
- private async sendNotificationToServiceWorker(
640
- webpushInfo: any
641
- ): Promise<void> {
642
- try {
643
- if (!this.serviceWorkerManager) {
644
- logger.warn(
645
- 'ServiceWorkerManager not initialized, skipping notification'
646
- );
647
- return;
648
- }
649
-
650
- // 直接使用 webpushInfo 数据,格式与 push 事件一致
651
- // 通过 ServiceWorkerManager 向 service-worker 发送消息,模拟 push 事件的处理
652
- await this.serviceWorkerManager.postMessage({
653
- type: 'PROCESS_WEBPUSH_DATA',
654
- payload: webpushInfo,
655
- });
656
-
657
- logger.log('WebPush data sent to service-worker', webpushInfo);
658
- } catch (error) {
659
- logger.error('Failed to send webpush data to service-worker', error);
660
- }
661
- }
662
-
663
- /**
664
- * 向 service-worker 发送消息撤回请求
665
- * @param messageID 要撤回的消息ID
666
- */
667
- private async sendMessageRevokeToServiceWorker(
668
- messageID: string
669
- ): Promise<void> {
670
- try {
671
- if (!this.serviceWorkerManager) {
672
- logger.warn(
673
- 'ServiceWorkerManager not initialized, skipping message revoke'
674
- );
675
- return;
676
- }
677
-
678
- // 向 ServiceWorker 发送消息撤回请求
679
- await this.serviceWorkerManager.postMessage({
680
- type: 'REVOKE_MESSAGE',
681
- payload: { messageID },
682
- });
683
-
684
- logger.log('Message revoke sent to service-worker', messageID);
685
- } catch (error) {
686
- logger.error('Failed to send message revoke to service-worker', error);
687
- throw error;
688
- }
689
- }
690
- }