@cometchat/skills 4.3.0 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/bin/install.js +27 -0
- package/package.json +14 -1
- package/skills/cometchat/SKILL.md +233 -69
- package/skills/cometchat/references/asking-questions.md +48 -0
- package/skills/cometchat-a11y/SKILL.md +3 -2
- package/skills/cometchat-android-v5/SKILL.md +2 -1
- package/skills/cometchat-android-v5-calls/SKILL.md +36 -22
- package/skills/cometchat-android-v5-calls/references/README.md +1 -1
- package/skills/cometchat-android-v5-calls/references/add-calls-to-existing-chat.md +7 -5
- package/skills/cometchat-android-v5-calls/references/audio-controls.md +4 -4
- package/skills/cometchat-android-v5-calls/references/call-layouts.md +33 -25
- package/skills/cometchat-android-v5-calls/references/call-session.md +2 -2
- package/skills/cometchat-android-v5-calls/references/custom-ui.md +5 -5
- package/skills/cometchat-android-v5-calls/references/event-listeners.md +2 -2
- package/skills/cometchat-android-v5-calls/references/idle-timeout.md +20 -14
- package/skills/cometchat-android-v5-calls/references/in-call-chat.md +1 -1
- package/skills/cometchat-android-v5-calls/references/migration-v4-to-v5.md +43 -27
- package/skills/cometchat-android-v5-calls/references/participant-management.md +3 -3
- package/skills/cometchat-android-v5-calls/references/raise-hand.md +25 -19
- package/skills/cometchat-android-v5-calls/references/recording.md +2 -2
- package/skills/cometchat-android-v5-calls/references/ringing-integration.md +1 -1
- package/skills/cometchat-android-v5-calls/references/screen-sharing.md +5 -9
- package/skills/cometchat-android-v5-calls/references/session-settings.md +3 -3
- package/skills/cometchat-android-v5-calls/references/setup.md +1 -1
- package/skills/cometchat-android-v5-calls/references/share-invite.md +9 -4
- package/skills/cometchat-android-v5-calls/references/video-controls.md +4 -4
- package/skills/cometchat-android-v5-calls/references/voip-calling.md +2 -2
- package/skills/cometchat-android-v5-components/SKILL.md +4 -3
- package/skills/cometchat-android-v5-core/SKILL.md +5 -3
- package/skills/cometchat-android-v5-customization/SKILL.md +171 -7
- package/skills/cometchat-android-v5-extensions/SKILL.md +7 -4
- package/skills/cometchat-android-v5-features/SKILL.md +5 -4
- package/skills/cometchat-android-v5-placement/SKILL.md +2 -1
- package/skills/cometchat-android-v5-production/SKILL.md +2 -1
- package/skills/cometchat-android-v5-push/SKILL.md +2 -3
- package/skills/cometchat-android-v5-testing/SKILL.md +2 -1
- package/skills/cometchat-android-v5-theming/SKILL.md +2 -1
- package/skills/cometchat-android-v5-troubleshooting/SKILL.md +3 -2
- package/skills/cometchat-android-v6/SKILL.md +2 -1
- package/skills/cometchat-android-v6-builder-settings/SKILL.md +11 -7
- package/skills/cometchat-android-v6-calls/SKILL.md +79 -18
- package/skills/cometchat-android-v6-calls/references/advanced-features.md +87 -0
- package/skills/cometchat-android-v6-calls/references/call-layouts.md +24 -15
- package/skills/cometchat-android-v6-calls/references/call-session.md +2 -2
- package/skills/cometchat-android-v6-calls/references/device-management.md +17 -16
- package/skills/cometchat-android-v6-calls/references/idle-timeout.md +7 -4
- package/skills/cometchat-android-v6-calls/references/in-call-chat.md +13 -8
- package/skills/cometchat-android-v6-calls/references/raise-hand.md +6 -4
- package/skills/cometchat-android-v6-compose-components/SKILL.md +52 -29
- package/skills/cometchat-android-v6-compose-customization/SKILL.md +156 -1
- package/skills/cometchat-android-v6-compose-placement/SKILL.md +129 -40
- package/skills/cometchat-android-v6-compose-theming/SKILL.md +27 -1
- package/skills/cometchat-android-v6-core/SKILL.md +208 -28
- package/skills/cometchat-android-v6-events/SKILL.md +4 -1
- package/skills/cometchat-android-v6-extensions/SKILL.md +2 -1
- package/skills/cometchat-android-v6-features/SKILL.md +26 -2
- package/skills/cometchat-android-v6-kotlin-components/SKILL.md +31 -1
- package/skills/cometchat-android-v6-kotlin-customization/SKILL.md +172 -1
- package/skills/cometchat-android-v6-kotlin-placement/SKILL.md +20 -5
- package/skills/cometchat-android-v6-kotlin-theming/SKILL.md +36 -5
- package/skills/cometchat-android-v6-migration/SKILL.md +44 -42
- package/skills/cometchat-android-v6-production/SKILL.md +6 -3
- package/skills/cometchat-android-v6-push/SKILL.md +43 -2
- package/skills/cometchat-android-v6-testing/SKILL.md +11 -8
- package/skills/cometchat-android-v6-troubleshooting/SKILL.md +26 -5
- package/skills/cometchat-angular-calls/SKILL.md +256 -389
- package/skills/cometchat-angular-calls/references/add-calls-to-existing-chat.md +3 -2
- package/skills/cometchat-angular-calls/references/call-layouts.md +29 -12
- package/skills/cometchat-angular-calls/references/call-session.md +2 -2
- package/skills/cometchat-angular-calls/references/custom-ui.md +18 -10
- package/skills/cometchat-angular-calls/references/device-management.md +53 -34
- package/skills/cometchat-angular-calls/references/group-calls.md +45 -24
- package/skills/cometchat-angular-calls/references/idle-timeout.md +31 -15
- package/skills/cometchat-angular-calls/references/ngzone-and-async-callbacks.md +7 -6
- package/skills/cometchat-angular-calls/references/raise-hand.md +9 -4
- package/skills/cometchat-angular-calls/references/recording-screen-share.md +32 -39
- package/skills/cometchat-angular-calls/references/ringing-integration.md +3 -1
- package/skills/cometchat-angular-calls/references/share-invite.md +11 -5
- package/skills/cometchat-angular-calls/references/virtual-background.md +29 -0
- package/skills/cometchat-angular-components/SKILL.md +149 -620
- package/skills/cometchat-angular-core/SKILL.md +232 -312
- package/skills/cometchat-angular-customization/SKILL.md +415 -223
- package/skills/cometchat-angular-features/SKILL.md +216 -334
- package/skills/cometchat-angular-patterns/SKILL.md +168 -359
- package/skills/cometchat-angular-placement/SKILL.md +189 -560
- package/skills/cometchat-angular-production/SKILL.md +241 -92
- package/skills/cometchat-angular-push/SKILL.md +280 -294
- package/skills/cometchat-angular-testing/SKILL.md +430 -158
- package/skills/cometchat-angular-theming/SKILL.md +190 -265
- package/skills/cometchat-angular-troubleshooting/SKILL.md +192 -157
- package/skills/cometchat-astro-patterns/SKILL.md +3 -2
- package/skills/cometchat-calls/SKILL.md +25 -19
- package/skills/cometchat-calls/references/use-case-broadcast.md +15 -10
- package/skills/cometchat-calls/references/use-case-marketplace.md +2 -3
- package/skills/cometchat-calls/references/use-case-support.md +3 -4
- package/skills/cometchat-calls/references/use-case-team.md +23 -12
- package/skills/cometchat-calls/references/use-case-telehealth.md +3 -4
- package/skills/cometchat-components/SKILL.md +163 -25
- package/skills/cometchat-core/SKILL.md +258 -20
- package/skills/cometchat-customization/SKILL.md +50 -25
- package/skills/cometchat-features/SKILL.md +314 -35
- package/skills/cometchat-flutter-v5/SKILL.md +10 -4
- package/skills/cometchat-flutter-v5-calls/SKILL.md +188 -158
- package/skills/cometchat-flutter-v5-calls/references/add-calls-to-existing-chat.md +48 -24
- package/skills/cometchat-flutter-v5-calls/references/call-layouts.md +20 -15
- package/skills/cometchat-flutter-v5-calls/references/call-session.md +100 -145
- package/skills/cometchat-flutter-v5-calls/references/device-management.md +12 -8
- package/skills/cometchat-flutter-v5-calls/references/group-calls.md +30 -36
- package/skills/cometchat-flutter-v5-calls/references/idle-timeout.md +15 -13
- package/skills/cometchat-flutter-v5-calls/references/in-call-chat.md +12 -9
- package/skills/cometchat-flutter-v5-calls/references/migration-v4-to-v5.md +115 -65
- package/skills/cometchat-flutter-v5-calls/references/raise-hand.md +41 -30
- package/skills/cometchat-flutter-v5-calls/references/ringing-integration.md +17 -14
- package/skills/cometchat-flutter-v5-calls/references/share-invite.md +8 -2
- package/skills/cometchat-flutter-v5-conversations/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-core/SKILL.md +5 -4
- package/skills/cometchat-flutter-v5-customization/SKILL.md +136 -5
- package/skills/cometchat-flutter-v5-events/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-messages/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-production/SKILL.md +15 -6
- package/skills/cometchat-flutter-v5-push/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-testing/SKILL.md +17 -6
- package/skills/cometchat-flutter-v5-theming/SKILL.md +2 -1
- package/skills/cometchat-flutter-v5-troubleshooting/SKILL.md +7 -6
- package/skills/cometchat-flutter-v5-users-groups/SKILL.md +3 -2
- package/skills/cometchat-flutter-v6/SKILL.md +17 -16
- package/skills/cometchat-flutter-v6-calls/SKILL.md +72 -57
- package/skills/cometchat-flutter-v6-calls/references/add-calls-to-existing-chat.md +5 -3
- package/skills/cometchat-flutter-v6-calls/references/advanced-features.md +89 -0
- package/skills/cometchat-flutter-v6-calls/references/call-layouts.md +15 -12
- package/skills/cometchat-flutter-v6-calls/references/call-session.md +2 -2
- package/skills/cometchat-flutter-v6-calls/references/device-management.md +9 -3
- package/skills/cometchat-flutter-v6-calls/references/group-calls.md +10 -10
- package/skills/cometchat-flutter-v6-calls/references/idle-timeout.md +15 -7
- package/skills/cometchat-flutter-v6-calls/references/in-call-chat.md +6 -3
- package/skills/cometchat-flutter-v6-calls/references/raise-hand.md +23 -16
- package/skills/cometchat-flutter-v6-components/SKILL.md +32 -11
- package/skills/cometchat-flutter-v6-conversations/SKILL.md +39 -11
- package/skills/cometchat-flutter-v6-core/SKILL.md +182 -21
- package/skills/cometchat-flutter-v6-customization/SKILL.md +97 -25
- package/skills/cometchat-flutter-v6-events/SKILL.md +3 -2
- package/skills/cometchat-flutter-v6-features/SKILL.md +15 -6
- package/skills/cometchat-flutter-v6-messages/SKILL.md +111 -60
- package/skills/cometchat-flutter-v6-migration/SKILL.md +18 -25
- package/skills/cometchat-flutter-v6-placement/SKILL.md +79 -50
- package/skills/cometchat-flutter-v6-production/SKILL.md +13 -12
- package/skills/cometchat-flutter-v6-push/SKILL.md +41 -19
- package/skills/cometchat-flutter-v6-testing/SKILL.md +4 -4
- package/skills/cometchat-flutter-v6-theming/SKILL.md +38 -5
- package/skills/cometchat-flutter-v6-troubleshooting/SKILL.md +182 -17
- package/skills/cometchat-flutter-v6-users-groups/SKILL.md +12 -4
- package/skills/cometchat-i18n/SKILL.md +140 -79
- package/skills/cometchat-ios/SKILL.md +4 -2
- package/skills/cometchat-ios-calls/SKILL.md +225 -95
- package/skills/cometchat-ios-calls/references/add-calls-to-existing-chat.md +11 -9
- package/skills/cometchat-ios-calls/references/audio-modes-and-controls.md +45 -0
- package/skills/cometchat-ios-calls/references/avaudiosession-routing.md +6 -7
- package/skills/cometchat-ios-calls/references/call-layouts.md +31 -91
- package/skills/cometchat-ios-calls/references/call-session.md +51 -54
- package/skills/cometchat-ios-calls/references/callkit-and-pushkit.md +33 -29
- package/skills/cometchat-ios-calls/references/custom-ui.md +38 -38
- package/skills/cometchat-ios-calls/references/group-calls.md +33 -70
- package/skills/cometchat-ios-calls/references/idle-timeout.md +24 -25
- package/skills/cometchat-ios-calls/references/in-call-chat.md +19 -23
- package/skills/cometchat-ios-calls/references/migration-v4-to-v5.md +128 -70
- package/skills/cometchat-ios-calls/references/picture-in-picture.md +20 -20
- package/skills/cometchat-ios-calls/references/raise-hand.md +14 -227
- package/skills/cometchat-ios-calls/references/recording-screen-share.md +35 -122
- package/skills/cometchat-ios-calls/references/ringing-integration.md +17 -16
- package/skills/cometchat-ios-calls/references/share-invite.md +8 -12
- package/skills/cometchat-ios-calls/references/swiftui-uikit-hosting.md +4 -4
- package/skills/cometchat-ios-components/SKILL.md +200 -12
- package/skills/cometchat-ios-core/SKILL.md +173 -45
- package/skills/cometchat-ios-customization/SKILL.md +276 -110
- package/skills/cometchat-ios-features/SKILL.md +64 -36
- package/skills/cometchat-ios-placement/SKILL.md +15 -12
- package/skills/cometchat-ios-production/SKILL.md +12 -4
- package/skills/cometchat-ios-push/SKILL.md +53 -19
- package/skills/cometchat-ios-testing/SKILL.md +14 -9
- package/skills/cometchat-ios-theming/SKILL.md +39 -3
- package/skills/cometchat-ios-troubleshooting/SKILL.md +41 -21
- package/skills/cometchat-native-bare-patterns/SKILL.md +36 -19
- package/skills/cometchat-native-calls/SKILL.md +29 -17
- package/skills/cometchat-native-calls/references/add-calls-to-existing-chat.md +2 -2
- package/skills/cometchat-native-calls/references/call-layouts.md +15 -14
- package/skills/cometchat-native-calls/references/call-session.md +2 -2
- package/skills/cometchat-native-calls/references/custom-ui.md +12 -8
- package/skills/cometchat-native-calls/references/device-management.md +53 -30
- package/skills/cometchat-native-calls/references/group-calls.md +35 -30
- package/skills/cometchat-native-calls/references/idle-timeout.md +6 -6
- package/skills/cometchat-native-calls/references/in-call-chat.md +10 -8
- package/skills/cometchat-native-calls/references/migration-v4-to-v5.md +2 -2
- package/skills/cometchat-native-calls/references/raise-hand.md +15 -13
- package/skills/cometchat-native-calls/references/recording-screen-share.md +49 -170
- package/skills/cometchat-native-calls/references/share-invite.md +7 -5
- package/skills/cometchat-native-calls/references/voip-push-end-to-end.md +4 -2
- package/skills/cometchat-native-components/SKILL.md +84 -52
- package/skills/cometchat-native-core/SKILL.md +102 -33
- package/skills/cometchat-native-customization/SKILL.md +150 -28
- package/skills/cometchat-native-expo-patterns/SKILL.md +60 -29
- package/skills/cometchat-native-features/SKILL.md +24 -17
- package/skills/cometchat-native-placement/SKILL.md +19 -10
- package/skills/cometchat-native-production/SKILL.md +9 -3
- package/skills/cometchat-native-push/SKILL.md +2 -1
- package/skills/cometchat-native-testing/SKILL.md +1 -2
- package/skills/cometchat-native-theming/SKILL.md +54 -29
- package/skills/cometchat-native-troubleshooting/SKILL.md +11 -5
- package/skills/cometchat-nextjs-patterns/SKILL.md +22 -8
- package/skills/cometchat-placement/SKILL.md +42 -3
- package/skills/cometchat-production/SKILL.md +12 -5
- package/skills/cometchat-react-calls/SKILL.md +220 -10
- package/skills/cometchat-react-calls/references/add-calls-to-existing-chat.md +4 -3
- package/skills/cometchat-react-calls/references/call-layouts.md +5 -6
- package/skills/cometchat-react-calls/references/call-session.md +1 -1
- package/skills/cometchat-react-calls/references/custom-ui.md +61 -15
- package/skills/cometchat-react-calls/references/device-management.md +55 -51
- package/skills/cometchat-react-calls/references/group-calls.md +18 -23
- package/skills/cometchat-react-calls/references/idle-timeout.md +25 -12
- package/skills/cometchat-react-calls/references/in-call-chat.md +7 -7
- package/skills/cometchat-react-calls/references/migration-v4-to-v5.md +9 -11
- package/skills/cometchat-react-calls/references/raise-hand.md +14 -14
- package/skills/cometchat-react-calls/references/recording-screen-share.md +39 -38
- package/skills/cometchat-react-calls/references/ringing-integration.md +2 -2
- package/skills/cometchat-react-calls/references/share-invite.md +4 -5
- package/skills/cometchat-react-calls/references/testing-calls-on-web.md +20 -2
- package/skills/cometchat-react-calls/references/virtual-background.md +32 -0
- package/skills/cometchat-react-patterns/SKILL.md +45 -5
- package/skills/cometchat-react-push/SKILL.md +258 -72
- package/skills/cometchat-react-router-patterns/SKILL.md +12 -6
- package/skills/cometchat-react-testing/SKILL.md +14 -5
- package/skills/cometchat-theming/SKILL.md +181 -18
- package/skills/cometchat-troubleshooting/SKILL.md +40 -20
|
@@ -1,403 +1,389 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: cometchat-angular-push
|
|
3
|
-
description: Push notifications for CometChat Angular UI Kit
|
|
3
|
+
description: Push notifications for CometChat Angular UI Kit v5 (@cometchat/chat-uikit-angular@5) — web push via Firebase Cloud Messaging (FCM) + the CometChat Notifications API. Covers dashboard FCM provider setup, the firebase-messaging-sw.js service worker, Notification permission, getting the FCM token, registering it with CometChatNotifications.registerPushToken + PushPlatforms.FCM_WEB AFTER login, an Angular PushService, environment config, foreground vs background handling, click-through routing, and logout cleanup.
|
|
4
4
|
license: "MIT"
|
|
5
|
-
compatibility: "Angular
|
|
6
|
-
allowed-tools: "shell, file-read, file-search, file-list, ask-user"
|
|
5
|
+
compatibility: "Angular >=17 <22; @cometchat/chat-uikit-angular ^5.0; @cometchat/chat-sdk-javascript ^4.1"
|
|
7
6
|
metadata:
|
|
8
7
|
author: "CometChat"
|
|
9
8
|
version: "4.0.0"
|
|
10
|
-
tags: "cometchat angular web push notifications service-worker
|
|
9
|
+
tags: "cometchat angular web push notifications fcm firebase service-worker registerPushToken PushPlatforms notifications-api standalone v5"
|
|
11
10
|
---
|
|
12
11
|
|
|
13
12
|
## Purpose
|
|
14
13
|
|
|
15
|
-
Web
|
|
14
|
+
Web push for CometChat **Angular UI Kit v5** (`@cometchat/chat-uikit-angular@5`). On the web, CometChat push runs through **Firebase Cloud Messaging (FCM)** plus the **CometChat Notifications API** — CometChat hosts the send path. You do NOT build your own push server or webhook for the basic flow: configure an FCM provider in the CometChat dashboard, register the browser's FCM token with `CometChatNotifications.registerPushToken(...)`, and CometChat delivers a push whenever a message arrives for that user.
|
|
16
15
|
|
|
17
|
-
**
|
|
18
|
-
- `cometchat-angular-core` — UIKitSettingsBuilder, login order
|
|
19
|
-
- `cometchat-angular-patterns` — module setup
|
|
20
|
-
- `cometchat-react-push` — same Web Push spec, React-flavored explanation; shared concepts (VAPID, server-side webhook, iOS PWA caveat) covered there in depth
|
|
16
|
+
This is the v5 (standalone, Angular 17–21) rewrite. The previous v4 skill used `@angular/service-worker` + `SwPush` + a self-hosted VAPID web-push server + a CometChat webhook. **That hand-rolled path is replaced** — v5 uses FCM end-to-end through the CometChat Notifications API, which is the documented, supported web-push path.
|
|
21
17
|
|
|
22
|
-
**
|
|
23
|
-
-
|
|
24
|
-
- `
|
|
25
|
-
-
|
|
18
|
+
**Read these skills first:**
|
|
19
|
+
- `cometchat-angular-core` — `UIKitSettingsBuilder` init, Promise-based `login(uid)` (bare string), `loggedInUser$`, environment config. Push registration hangs off the same login lifecycle.
|
|
20
|
+
- `cometchat-react-push` is the React sibling for the *self-hosted* Web Push model; the FCM + `CometChatNotifications` plumbing in THIS skill is the shared web SDK API and is the recommended path for both. Where they differ, this skill wins for Angular.
|
|
21
|
+
- `cometchat-angular-production` — server-minted auth tokens (push registration is tied to the logged-in auth token).
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
**Ground truth (verify before relying on any symbol):** **Official docs:** https://www.cometchat.com/docs/notifications/overview · **Docs MCP:** `claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp` (or fetch the URL directly without MCP).
|
|
24
|
+
- Chat SDK types: `node_modules/@cometchat/chat-sdk-javascript/CometChat.d.ts` — `CometChatNotifications`, `PushPlatforms`.
|
|
25
|
+
- FCM (web): https://firebase.google.com/docs/cloud-messaging/js/client
|
|
26
|
+
- CometChat dashboard → **Notifications** → **Push Notifications** (FCM provider config).
|
|
30
27
|
|
|
31
|
-
|
|
28
|
+
> The Chat SDK is `@cometchat/chat-sdk-javascript@^4.1`. The web push API documented below is its **real** notification API — `CometChatNotifications.registerPushToken`, `PushPlatforms.FCM_WEB`, `CometChatNotifications.unregisterPushToken`. Do not substitute mobile-only symbols (APNs, FCM_ANDROID, etc.) — the only web platform enum value is `FCM_WEB`.
|
|
32
29
|
|
|
33
30
|
---
|
|
34
31
|
|
|
35
|
-
##
|
|
32
|
+
## 1. Architecture
|
|
36
33
|
|
|
37
|
-
```bash
|
|
38
|
-
ng add @angular/service-worker
|
|
39
34
|
```
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
BrowserModule,
|
|
53
|
-
ServiceWorkerModule.register('ngsw-worker.js', {
|
|
54
|
-
enabled: !isDevMode(), // SW disabled in dev mode by default
|
|
55
|
-
registrationStrategy: 'registerWhenStable:30000',
|
|
56
|
-
}),
|
|
57
|
-
],
|
|
58
|
-
})
|
|
59
|
-
export class AppModule {}
|
|
35
|
+
Browser (your Angular app)
|
|
36
|
+
├── Firebase JS SDK (firebase/messaging) — gets the FCM registration token
|
|
37
|
+
├── firebase-messaging-sw.js — service worker; receives background push
|
|
38
|
+
└── Notification permission — granted by the user
|
|
39
|
+
|
|
40
|
+
CometChat backend
|
|
41
|
+
├── FCM provider config (server key / service account) ← set in dashboard
|
|
42
|
+
└── Notifications service — sends an FCM push to the user's registered token(s)
|
|
43
|
+
whenever a message arrives for them
|
|
44
|
+
|
|
45
|
+
Your Angular code
|
|
46
|
+
└── After login → get FCM token → CometChatNotifications.registerPushToken(token, FCM_WEB)
|
|
60
47
|
```
|
|
61
48
|
|
|
49
|
+
You own: the Firebase project, the service worker file, the permission prompt, token registration after login, and token cleanup on logout. CometChat owns the actual send. No self-hosted push server, no VAPID web-push library, no CometChat webhook for the basic flow.
|
|
50
|
+
|
|
62
51
|
---
|
|
63
52
|
|
|
64
|
-
##
|
|
53
|
+
## 2. Dashboard — enable the FCM push provider (one-time)
|
|
65
54
|
|
|
66
|
-
|
|
55
|
+
In the CometChat dashboard:
|
|
67
56
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"assetGroups": [
|
|
73
|
-
{
|
|
74
|
-
"name": "app",
|
|
75
|
-
"installMode": "prefetch",
|
|
76
|
-
"resources": {
|
|
77
|
-
"files": ["/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js"]
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
"name": "assets",
|
|
82
|
-
"installMode": "lazy",
|
|
83
|
-
"updateMode": "prefetch",
|
|
84
|
-
"resources": {
|
|
85
|
-
"files": ["/assets/**", "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"]
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
],
|
|
89
|
-
"dataGroups": [
|
|
90
|
-
{
|
|
91
|
-
"name": "cometchat-api",
|
|
92
|
-
"urls": ["https://api-*.cometchat.io/**"],
|
|
93
|
-
"cacheConfig": {
|
|
94
|
-
"maxSize": 100,
|
|
95
|
-
"maxAge": "0d",
|
|
96
|
-
"strategy": "freshness"
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
]
|
|
100
|
-
}
|
|
101
|
-
```
|
|
57
|
+
1. **Notifications** → **Push Notifications** → enable.
|
|
58
|
+
2. Add a **provider** of type **FCM**.
|
|
59
|
+
3. Supply your Firebase credentials. Modern FCM (HTTP v1) wants the **service-account JSON** (from Firebase Console → Project settings → Service accounts → Generate new private key). Older configs accept the legacy **Server Key** + **Sender ID** (Cloud Messaging tab). Match whatever the dashboard's FCM form currently asks for.
|
|
60
|
+
4. Note the **Provider ID** you assign (default is `default`). You pass this same string as the third arg to `registerPushToken` if you used a non-default provider.
|
|
102
61
|
|
|
103
|
-
**
|
|
62
|
+
The Firebase **web app config** (`apiKey`, `authDomain`, `projectId`, `messagingSenderId`, `appId`) and the **VAPID key pair** (Firebase Console → Cloud Messaging → Web configuration → "Web Push certificates") are client-side — they go in `environment.ts` (§4). The service-account JSON / Server Key is **server-side only** — it lives in the CometChat dashboard, never in your Angular bundle.
|
|
104
63
|
|
|
105
64
|
---
|
|
106
65
|
|
|
107
|
-
##
|
|
66
|
+
## 3. Install Firebase + add the service worker
|
|
108
67
|
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
import { SwPush } from "@angular/service-worker";
|
|
113
|
-
import { Router } from "@angular/router";
|
|
114
|
-
import { environment } from "../../environments/environment";
|
|
115
|
-
|
|
116
|
-
@Injectable({ providedIn: "root" })
|
|
117
|
-
export class PushService {
|
|
118
|
-
constructor(private swPush: SwPush, private router: Router) {
|
|
119
|
-
// Listen for notification clicks — fired when user taps a push notification
|
|
120
|
-
this.swPush.notificationClicks.subscribe(({ notification }) => {
|
|
121
|
-
const data = notification.data;
|
|
122
|
-
const targetUrl = data.receiverType === "group"
|
|
123
|
-
? `/messages/group/${data.conversationId}`
|
|
124
|
-
: `/messages/user/${data.senderUid}`;
|
|
125
|
-
this.router.navigateByUrl(targetUrl);
|
|
126
|
-
});
|
|
127
|
-
}
|
|
68
|
+
```bash
|
|
69
|
+
npm install firebase
|
|
70
|
+
```
|
|
128
71
|
|
|
129
|
-
|
|
130
|
-
if (!this.swPush.isEnabled) {
|
|
131
|
-
console.warn("SwPush not enabled — Service Worker not registered or not supported");
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
72
|
+
> Do **not** use `@angular/service-worker` / `SwPush` for CometChat web push — FCM ships its own service worker contract (`firebase-messaging-sw.js`) and the Firebase JS SDK manages the token. The v4 `ngsw` path is gone.
|
|
134
73
|
|
|
135
|
-
|
|
136
|
-
const subscription = await this.swPush.requestSubscription({
|
|
137
|
-
serverPublicKey: environment.vapidPublic,
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
// Send to YOUR push server, keyed by uid
|
|
141
|
-
await fetch("/api/push/subscribe", {
|
|
142
|
-
method: "POST",
|
|
143
|
-
headers: { "Content-Type": "application/json" },
|
|
144
|
-
body: JSON.stringify({ uid, subscription }),
|
|
145
|
-
});
|
|
146
|
-
} catch (err) {
|
|
147
|
-
// User denied permission, or push not supported
|
|
148
|
-
console.warn("Web Push subscription failed:", err);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
74
|
+
### `src/firebase-messaging-sw.js`
|
|
151
75
|
|
|
152
|
-
|
|
153
|
-
if (!this.swPush.isEnabled) return;
|
|
154
|
-
const subscription = await this.swPush.subscription.toPromise();
|
|
155
|
-
if (!subscription) return;
|
|
76
|
+
This file MUST be served from the origin root (`/firebase-messaging-sw.js`) — `firebase.messaging()` registers it by that exact path. Add it as an Angular asset so the build copies it to the output root.
|
|
156
77
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
```
|
|
78
|
+
```js
|
|
79
|
+
// src/firebase-messaging-sw.js
|
|
80
|
+
// Loaded by the browser as a service worker — runs OUTSIDE Angular.
|
|
81
|
+
// Use the compat builds; ES module imports are not available in classic SWs.
|
|
82
|
+
importScripts("https://www.gstatic.com/firebasejs/10.12.0/firebase-app-compat.js");
|
|
83
|
+
importScripts("https://www.gstatic.com/firebasejs/10.12.0/firebase-messaging-compat.js");
|
|
166
84
|
|
|
167
|
-
|
|
85
|
+
firebase.initializeApp({
|
|
86
|
+
apiKey: "YOUR_FIREBASE_API_KEY",
|
|
87
|
+
authDomain: "YOUR_PROJECT.firebaseapp.com",
|
|
88
|
+
projectId: "YOUR_PROJECT_ID",
|
|
89
|
+
messagingSenderId: "YOUR_SENDER_ID",
|
|
90
|
+
appId: "YOUR_APP_ID",
|
|
91
|
+
});
|
|
168
92
|
|
|
169
|
-
|
|
93
|
+
const messaging = firebase.messaging();
|
|
94
|
+
|
|
95
|
+
// Background handler — fires when the tab is closed/backgrounded.
|
|
96
|
+
messaging.onBackgroundMessage((payload) => {
|
|
97
|
+
const title = payload.notification?.title ?? payload.data?.senderName ?? "New message";
|
|
98
|
+
self.registration.showNotification(title, {
|
|
99
|
+
body: payload.notification?.body ?? payload.data?.text ?? "",
|
|
100
|
+
icon: payload.notification?.icon ?? "/assets/chat-icon.png",
|
|
101
|
+
tag: payload.data?.conversationId, // dedupe per conversation
|
|
102
|
+
data: payload.data ?? {}, // carried into notificationclick
|
|
103
|
+
});
|
|
104
|
+
});
|
|
170
105
|
|
|
171
|
-
|
|
106
|
+
// Click-through — focus an open tab or open a new one, deep-linking to the thread.
|
|
107
|
+
self.addEventListener("notificationclick", (event) => {
|
|
108
|
+
event.notification.close();
|
|
109
|
+
const data = event.notification.data || {};
|
|
110
|
+
const url = data.receiverType === "group"
|
|
111
|
+
? `/messages/group/${data.conversationId}`
|
|
112
|
+
: `/messages/user/${data.sender}`;
|
|
113
|
+
event.waitUntil(
|
|
114
|
+
clients.matchAll({ type: "window", includeUncontrolled: true }).then((wins) => {
|
|
115
|
+
for (const w of wins) {
|
|
116
|
+
if ("focus" in w) { w.focus(); w.postMessage({ type: "open_conversation", ...data }); return; }
|
|
117
|
+
}
|
|
118
|
+
return clients.openWindow(url);
|
|
119
|
+
})
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
```
|
|
172
123
|
|
|
173
|
-
|
|
174
|
-
// services/auth.service.ts (or wherever login happens)
|
|
175
|
-
import { PushService } from "./push.service";
|
|
124
|
+
> The `payload.data` keys (`conversationId`, `sender`, `receiverType`, `text`, `senderName`) are whatever CometChat's FCM payload carries — confirm the exact field names against a real push in DevTools → Application → Service Workers, and adjust. Do not assume; CometChat's data-payload shape is the source of truth.
|
|
176
125
|
|
|
177
|
-
|
|
178
|
-
export class AuthService {
|
|
179
|
-
constructor(private pushService: PushService) {}
|
|
126
|
+
### Register the SW file as an Angular asset
|
|
180
127
|
|
|
181
|
-
|
|
182
|
-
await CometChatUIKit.login(uid);
|
|
183
|
-
// Don't auto-subscribe to push — let the user opt in via a button
|
|
184
|
-
}
|
|
128
|
+
`angular.json` → `projects.<app>.architect.build.options.assets` (alongside the mandatory CometChat assets glob from `cometchat-angular-core` §2):
|
|
185
129
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
await CometChatUIKit.logout();
|
|
189
|
-
}
|
|
190
|
-
}
|
|
130
|
+
```json
|
|
131
|
+
{ "glob": "firebase-messaging-sw.js", "input": "src", "output": "/" }
|
|
191
132
|
```
|
|
192
133
|
|
|
193
|
-
|
|
134
|
+
Build output then serves it at `/firebase-messaging-sw.js`. Verify after `ng build` that the file is at the dist root, not under `assets/`.
|
|
194
135
|
|
|
195
|
-
|
|
136
|
+
---
|
|
196
137
|
|
|
197
|
-
|
|
198
|
-
// components/notification-prompt.component.ts
|
|
199
|
-
@Component({
|
|
200
|
-
selector: "app-notification-prompt",
|
|
201
|
-
template: `
|
|
202
|
-
<button (click)="enable()" *ngIf="!enabled">
|
|
203
|
-
Enable notifications
|
|
204
|
-
</button>
|
|
205
|
-
`,
|
|
206
|
-
})
|
|
207
|
-
export class NotificationPromptComponent {
|
|
208
|
-
enabled = false;
|
|
138
|
+
## 4. Environment config
|
|
209
139
|
|
|
210
|
-
|
|
140
|
+
Angular has no `process.env`. The Firebase web config + VAPID key live in `src/environments/environment.ts` (these are publishable client values — `apiKey` here is a Firebase identifier, not a secret):
|
|
211
141
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
142
|
+
```typescript
|
|
143
|
+
// src/environments/environment.ts
|
|
144
|
+
export const environment = {
|
|
145
|
+
production: false,
|
|
146
|
+
cometchat: {
|
|
147
|
+
appId: "YOUR_APP_ID",
|
|
148
|
+
region: "us", // "us" | "eu" | "in"
|
|
149
|
+
authKey: "YOUR_AUTH_KEY", // dev only
|
|
150
|
+
},
|
|
151
|
+
firebase: {
|
|
152
|
+
apiKey: "YOUR_FIREBASE_API_KEY",
|
|
153
|
+
authDomain: "YOUR_PROJECT.firebaseapp.com",
|
|
154
|
+
projectId: "YOUR_PROJECT_ID",
|
|
155
|
+
messagingSenderId: "YOUR_SENDER_ID",
|
|
156
|
+
appId: "YOUR_FIREBASE_APP_ID",
|
|
157
|
+
vapidKey: "YOUR_WEB_PUSH_CERTIFICATE_KEY_PAIR", // FCM → Web configuration
|
|
158
|
+
},
|
|
159
|
+
// Provider ID set in the dashboard (§2). Omit / "default" if you didn't change it.
|
|
160
|
+
cometchatPushProviderId: "default",
|
|
161
|
+
};
|
|
219
162
|
```
|
|
220
163
|
|
|
221
|
-
|
|
164
|
+
Keep the same shape in `environment.prod.ts`. The CometChat **REST API Key** and the Firebase **service-account JSON** never appear in any `src/` file — Angular ships `src/` to the client.
|
|
222
165
|
|
|
223
166
|
---
|
|
224
167
|
|
|
225
|
-
##
|
|
168
|
+
## 5. PushService — get the FCM token and register it
|
|
226
169
|
|
|
227
|
-
|
|
170
|
+
```typescript
|
|
171
|
+
// src/app/services/push.service.ts
|
|
172
|
+
import { Injectable, Inject, PLATFORM_ID } from "@angular/core";
|
|
173
|
+
import { isPlatformBrowser } from "@angular/common";
|
|
174
|
+
import { Router } from "@angular/router";
|
|
175
|
+
import { initializeApp } from "firebase/app";
|
|
176
|
+
import { getMessaging, getToken, onMessage, deleteToken, Messaging } from "firebase/messaging";
|
|
177
|
+
import { CometChatNotifications } from "@cometchat/chat-sdk-javascript";
|
|
178
|
+
import { environment } from "../../environments/environment";
|
|
228
179
|
|
|
229
|
-
|
|
180
|
+
@Injectable({ providedIn: "root" })
|
|
181
|
+
export class PushService {
|
|
182
|
+
private messaging: Messaging | null = null;
|
|
230
183
|
|
|
231
|
-
|
|
184
|
+
constructor(
|
|
185
|
+
private router: Router,
|
|
186
|
+
@Inject(PLATFORM_ID) private platformId: object,
|
|
187
|
+
) {
|
|
188
|
+
if (!isPlatformBrowser(this.platformId)) return; // SSR / prerender guard
|
|
189
|
+
if (!("serviceWorker" in navigator) || !("Notification" in window)) return;
|
|
190
|
+
|
|
191
|
+
const app = initializeApp(environment.firebase);
|
|
192
|
+
this.messaging = getMessaging(app);
|
|
193
|
+
|
|
194
|
+
// Foreground messages: the SW background handler does NOT fire while the tab
|
|
195
|
+
// is focused. Decide your own UX here (toast, in-app banner, or a manual
|
|
196
|
+
// Notification). Don't double-notify.
|
|
197
|
+
onMessage(this.messaging, (payload) => {
|
|
198
|
+
// e.g. show an in-app toast; skip an OS notification if the chat is focused.
|
|
199
|
+
console.debug("Foreground push:", payload);
|
|
200
|
+
});
|
|
232
201
|
|
|
233
|
-
|
|
202
|
+
// SW → app messages from notificationclick (deep-link into the thread).
|
|
203
|
+
navigator.serviceWorker?.addEventListener("message", (event: MessageEvent) => {
|
|
204
|
+
const d = event.data;
|
|
205
|
+
if (d?.type === "open_conversation") {
|
|
206
|
+
const url = d.receiverType === "group"
|
|
207
|
+
? `/messages/group/${d.conversationId}`
|
|
208
|
+
: `/messages/user/${d.sender}`;
|
|
209
|
+
this.router.navigateByUrl(url);
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
234
213
|
|
|
235
|
-
|
|
214
|
+
/** Call AFTER CometChatUIKit.login(uid) resolves. Must be user-gesture-initiated
|
|
215
|
+
* (Notification.requestPermission requires it on most browsers). */
|
|
216
|
+
async register(): Promise<void> {
|
|
217
|
+
if (!this.messaging) return;
|
|
218
|
+
|
|
219
|
+
const permission = await Notification.requestPermission();
|
|
220
|
+
if (permission !== "granted") return; // user declined — bail quietly
|
|
221
|
+
|
|
222
|
+
// The Firebase SDK registers /firebase-messaging-sw.js itself; pass the
|
|
223
|
+
// VAPID key from the FCM Web configuration.
|
|
224
|
+
const fcmToken = await getToken(this.messaging, { vapidKey: environment.firebase.vapidKey });
|
|
225
|
+
if (!fcmToken) return;
|
|
226
|
+
|
|
227
|
+
// The ONE call that wires the browser into CometChat's push pipeline.
|
|
228
|
+
await CometChatNotifications.registerPushToken(
|
|
229
|
+
fcmToken,
|
|
230
|
+
CometChatNotifications.PushPlatforms.FCM_WEB, // = "fcm_web" — the only web value
|
|
231
|
+
environment.cometchatPushProviderId, // optional; defaults to "default"
|
|
232
|
+
);
|
|
233
|
+
}
|
|
236
234
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
"conversationId": "conversation-123",
|
|
246
|
-
"senderUid": "cometchat-uid-1",
|
|
247
|
-
"receiverType": "user"
|
|
235
|
+
/** Call BEFORE CometChatUIKit.logout(). Order matters — registration is tied
|
|
236
|
+
* to the current auth token, which logout invalidates. */
|
|
237
|
+
async unregister(): Promise<void> {
|
|
238
|
+
if (!this.messaging) return;
|
|
239
|
+
try {
|
|
240
|
+
await CometChatNotifications.unregisterPushToken(); // clears CometChat-side
|
|
241
|
+
} finally {
|
|
242
|
+
await deleteToken(this.messaging).catch(() => {}); // clears the FCM token too
|
|
248
243
|
}
|
|
249
244
|
}
|
|
250
245
|
}
|
|
251
246
|
```
|
|
252
247
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
---
|
|
260
|
-
|
|
261
|
-
## 8. Server-side push send
|
|
262
|
-
|
|
263
|
-
Same shape as `cometchat-react-push` Section 6. Different payload shape — Angular SW expects the wrapped `{ notification: {...} }` form:
|
|
264
|
-
|
|
265
|
-
```ts
|
|
266
|
-
const payload = JSON.stringify({
|
|
267
|
-
notification: {
|
|
268
|
-
title: sender.name,
|
|
269
|
-
body: truncate(data.text, 80),
|
|
270
|
-
icon: sender.avatar ?? "/icons/chat.png",
|
|
271
|
-
tag: `chat-${receiver}`,
|
|
272
|
-
data: {
|
|
273
|
-
conversationId: receiver,
|
|
274
|
-
senderUid: sender.uid,
|
|
275
|
-
receiverType: data.entityType,
|
|
276
|
-
},
|
|
277
|
-
},
|
|
278
|
-
});
|
|
279
|
-
```
|
|
280
|
-
|
|
281
|
-
The webhook setup, signature verification, and dead-subscription cleanup are identical to the React version.
|
|
282
|
-
|
|
283
|
-
---
|
|
284
|
-
|
|
285
|
-
## 9. CometChat webhook setup
|
|
248
|
+
**API notes (verified against the v5 Chat SDK `.d.ts`):**
|
|
249
|
+
- `CometChatNotifications.registerPushToken(pushToken: string, platform: PushPlatforms, providerId?: string): Promise<string>` — registers the FCM token against the **current logged-in auth token**. Third arg is optional and defaults to `"default"`.
|
|
250
|
+
- `PushPlatforms.FCM_WEB = "fcm_web"` — the **only** web platform value in the enum. There is no web APNs/Android variant.
|
|
251
|
+
- `CometChatNotifications.unregisterPushToken(): Promise<string>` — unregisters the token for the current auth token. Takes **no arguments**.
|
|
252
|
+
- Both are static members of the **top-level** `CometChatNotifications` class — import it directly: `import { CometChatNotifications } from "@cometchat/chat-sdk-javascript"`. It is NOT nested under the `CometChat` namespace (there is no `CometChat.CometChatNotifications`).
|
|
253
|
+
- `PushPlatforms` is itself a top-level export of the SDK; the enum is also re-exposed as a static on the class (`CometChatNotifications.PushPlatforms`). Either `PushPlatforms.FCM_WEB` (with a top-level import) or `CometChatNotifications.PushPlatforms.FCM_WEB` is valid — both resolve to `"fcm_web"`.
|
|
286
254
|
|
|
287
|
-
|
|
255
|
+
> Legacy note: the SDK also exposes the deprecated `CometChat.registerTokenForPushNotification(token, settings?)`. It predates the Notifications service. Do **not** use it for new v5 integrations — `CometChatNotifications.registerPushToken` is the current API.
|
|
288
256
|
|
|
289
257
|
---
|
|
290
258
|
|
|
291
|
-
##
|
|
259
|
+
## 6. Wire into the login lifecycle
|
|
292
260
|
|
|
293
|
-
|
|
261
|
+
Registration MUST happen **after** `login(uid)` resolves — `registerPushToken` binds the token to the live auth token. (See `cometchat-angular-core` §3–§4 for the init → login order; init resolves in `main.ts` before `bootstrapApplication` — the v5 canonical path; `APP_INITIALIZER` is an alternative — and login happens in your auth service / route guard.)
|
|
294
262
|
|
|
295
|
-
```
|
|
296
|
-
// services/
|
|
297
|
-
import {
|
|
298
|
-
import {
|
|
263
|
+
```typescript
|
|
264
|
+
// src/app/services/auth.service.ts
|
|
265
|
+
import { Injectable } from "@angular/core";
|
|
266
|
+
import { CometChatUIKit } from "@cometchat/chat-uikit-angular";
|
|
267
|
+
import { PushService } from "./push.service";
|
|
299
268
|
|
|
300
269
|
@Injectable({ providedIn: "root" })
|
|
301
|
-
export class
|
|
302
|
-
constructor(
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
270
|
+
export class AuthService {
|
|
271
|
+
constructor(private push: PushService) {}
|
|
272
|
+
|
|
273
|
+
async login(uid: string): Promise<void> {
|
|
274
|
+
const existing = CometChatUIKit.getLoggedInUser(); // sync getter, capital "In"
|
|
275
|
+
if (!existing) {
|
|
276
|
+
await CometChatUIKit.login(uid); // bare string in v5
|
|
277
|
+
}
|
|
278
|
+
// Push is opt-in + gesture-gated — do NOT auto-register here.
|
|
279
|
+
// Call this.push.register() from a button click (see §7).
|
|
309
280
|
}
|
|
310
281
|
|
|
311
|
-
async
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
// ...
|
|
282
|
+
async logout(): Promise<void> {
|
|
283
|
+
await this.push.unregister(); // CRITICAL: before logout
|
|
284
|
+
await CometChatUIKit.logout();
|
|
315
285
|
}
|
|
316
286
|
}
|
|
317
287
|
```
|
|
318
288
|
|
|
319
|
-
|
|
289
|
+
---
|
|
320
290
|
|
|
321
|
-
|
|
291
|
+
## 7. "Enable notifications" button (gesture requirement)
|
|
322
292
|
|
|
323
|
-
|
|
293
|
+
`Notification.requestPermission()` must be called from a user gesture on most browsers — calling it from `ngOnInit` is silently rejected. Wire `register()` to a click:
|
|
324
294
|
|
|
325
|
-
|
|
295
|
+
```typescript
|
|
296
|
+
// src/app/components/enable-push.component.ts
|
|
297
|
+
import { Component } from "@angular/core";
|
|
298
|
+
import { CommonModule } from "@angular/common";
|
|
299
|
+
import { PushService } from "../services/push.service";
|
|
300
|
+
import { CometChatUIKit } from "@cometchat/chat-uikit-angular";
|
|
326
301
|
|
|
327
|
-
|
|
302
|
+
@Component({
|
|
303
|
+
selector: "app-enable-push",
|
|
304
|
+
standalone: true,
|
|
305
|
+
imports: [CommonModule],
|
|
306
|
+
template: `
|
|
307
|
+
<button *ngIf="!enabled" (click)="enable()">Enable notifications</button>
|
|
308
|
+
`,
|
|
309
|
+
})
|
|
310
|
+
export class EnablePushComponent {
|
|
311
|
+
enabled = Notification.permission === "granted";
|
|
328
312
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
"start_url": "/",
|
|
337
|
-
"icons": [/* ... */]
|
|
313
|
+
constructor(private push: PushService) {}
|
|
314
|
+
|
|
315
|
+
async enable(): Promise<void> {
|
|
316
|
+
if (!CometChatUIKit.getLoggedInUser()) return; // must be logged in first
|
|
317
|
+
await this.push.register();
|
|
318
|
+
this.enabled = Notification.permission === "granted";
|
|
319
|
+
}
|
|
338
320
|
}
|
|
339
321
|
```
|
|
340
322
|
|
|
341
|
-
|
|
323
|
+
Mount it in the chat header, a settings page, or a one-time onboarding card.
|
|
342
324
|
|
|
343
325
|
---
|
|
344
326
|
|
|
345
|
-
##
|
|
327
|
+
## 8. Foreground vs background
|
|
346
328
|
|
|
347
|
-
|
|
329
|
+
- **Background / tab closed:** `onBackgroundMessage` in `firebase-messaging-sw.js` fires; you call `showNotification` (§3).
|
|
330
|
+
- **Foreground / tab focused:** the SW handler does **not** fire. `onMessage` in `PushService` fires instead (§5). Show an in-app toast/banner, or skip entirely if the relevant conversation is already on screen — never both, or the user sees a duplicate. CometChat's UI Kit already updates the message list live when the tab is focused, so a silent foreground handler is often the right call.
|
|
348
331
|
|
|
349
|
-
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 9. Notification permission states
|
|
335
|
+
|
|
336
|
+
`Notification.permission` is `"default"` (not yet asked), `"granted"`, or `"denied"`. Once `"denied"`, you cannot re-prompt programmatically — the user must change it in browser site settings. Reflect this in the UI: show the enable button only when `permission === "default"`, and a "notifications blocked — enable in browser settings" hint when `"denied"`.
|
|
350
337
|
|
|
351
338
|
---
|
|
352
339
|
|
|
353
|
-
##
|
|
340
|
+
## 10. HTTPS requirement
|
|
354
341
|
|
|
355
|
-
|
|
342
|
+
Service Workers, the Push API, and FCM all require **HTTPS** (or `http://localhost` for dev). On a LAN IP or plain `http://`, `getToken` and SW registration fail. Use `ng serve` (localhost is allowed) or `ng serve --ssl` for HTTPS-in-dev. Production hosts (Vercel / Netlify / Cloudflare Pages / Firebase Hosting) are HTTPS by default.
|
|
356
343
|
|
|
357
|
-
|
|
358
|
-
ng build --configuration production
|
|
359
|
-
```
|
|
344
|
+
---
|
|
360
345
|
|
|
361
|
-
|
|
346
|
+
## 11. SSR / prerender (Angular Universal)
|
|
362
347
|
|
|
363
|
-
|
|
348
|
+
If the app uses SSR or prerendering, every Firebase/Notification touch must be browser-guarded — the `PushService` constructor already short-circuits with `isPlatformBrowser` (§5). Without it, `initializeApp` / `navigator.serviceWorker` throw `ReferenceError` at server boot. Keep all `firebase/messaging` access behind that guard; never call `register()` from server-rendered code paths.
|
|
364
349
|
|
|
365
350
|
---
|
|
366
351
|
|
|
367
|
-
##
|
|
352
|
+
## 12. Anti-patterns
|
|
368
353
|
|
|
369
|
-
1. **
|
|
370
|
-
2. **
|
|
371
|
-
3. **
|
|
372
|
-
4. **
|
|
373
|
-
5. **
|
|
374
|
-
6. **
|
|
375
|
-
7. **
|
|
354
|
+
1. **Registering the token before login resolves.** `registerPushToken` ties the token to the current auth token — call it only after `CometChatUIKit.login(uid)` succeeds.
|
|
355
|
+
2. **Calling `Notification.requestPermission()` from `ngOnInit`.** Browsers reject permission requests not tied to a user gesture. Use a clicked button (§7).
|
|
356
|
+
3. **Using `@angular/service-worker` / `SwPush`.** That was the v4 path. v5 web push uses Firebase's own `firebase-messaging-sw.js` + the FCM token — the two SW systems conflict if both register.
|
|
357
|
+
4. **Inventing platform enum values.** The only web value is `PushPlatforms.FCM_WEB` (`"fcm_web"`). There is no `FCM_ANDROID`/`APNS` for web.
|
|
358
|
+
5. **Using the deprecated `registerTokenForPushNotification`.** It predates the Notifications service; use `CometChatNotifications.registerPushToken`.
|
|
359
|
+
6. **Putting the Firebase service-account JSON / CometChat REST API Key in `environment.ts`.** Those are server-only (dashboard). The Firebase web config + VAPID key are the only push values that belong client-side.
|
|
360
|
+
7. **Serving `firebase-messaging-sw.js` from `/assets/`.** It must be at the origin root (`/firebase-messaging-sw.js`) or Firebase can't register it.
|
|
361
|
+
8. **Not unregistering on logout.** The previous user keeps receiving pushes. Call `unregisterPushToken()` (+ `deleteToken`) before `CometChatUIKit.logout()`.
|
|
362
|
+
9. **Double-notifying in the foreground.** `onMessage` and the SW `onBackgroundMessage` are mutually exclusive by tab focus — don't manually `showNotification` from foreground on top of the SW.
|
|
363
|
+
10. **No SSR guard in a Universal app.** `initializeApp` at server boot throws. Guard with `isPlatformBrowser`.
|
|
376
364
|
|
|
377
365
|
---
|
|
378
366
|
|
|
379
|
-
##
|
|
380
|
-
|
|
381
|
-
- [ ]
|
|
382
|
-
- [ ] `
|
|
383
|
-
- [ ] `
|
|
384
|
-
- [ ] `PushService`
|
|
385
|
-
- [ ] `
|
|
386
|
-
- [ ]
|
|
387
|
-
- [ ]
|
|
388
|
-
- [ ]
|
|
389
|
-
- [ ]
|
|
390
|
-
- [ ]
|
|
391
|
-
- [ ] CometChat dashboard webhook configured + signature verified
|
|
367
|
+
## 13. Verification checklist
|
|
368
|
+
|
|
369
|
+
- [ ] Dashboard: **Notifications → Push Notifications** enabled with an **FCM** provider; service-account JSON (or Server Key) supplied server-side
|
|
370
|
+
- [ ] `firebase` installed; `firebase-messaging-sw.js` in `src/`, registered as an Angular asset, served at `/firebase-messaging-sw.js` after build
|
|
371
|
+
- [ ] Firebase web config + VAPID key in `environment.ts`; service-account JSON / REST API Key NOT in any `src/` file
|
|
372
|
+
- [ ] `PushService` guards on `isPlatformBrowser` + `"serviceWorker" in navigator`
|
|
373
|
+
- [ ] `Notification.requestPermission()` fired from a user gesture (button), not `ngOnInit`
|
|
374
|
+
- [ ] FCM token fetched via `getToken(messaging, { vapidKey })`
|
|
375
|
+
- [ ] Token registered with `CometChatNotifications.registerPushToken(token, PushPlatforms.FCM_WEB, providerId)` **after** `login(uid)` resolves
|
|
376
|
+
- [ ] `onMessage` foreground handler defined; does not double-notify with the SW
|
|
377
|
+
- [ ] `onBackgroundMessage` + `notificationclick` in the SW deep-link to the conversation
|
|
378
|
+
- [ ] Logout calls `unregisterPushToken()` (+ `deleteToken`) BEFORE `CometChatUIKit.logout()`
|
|
392
379
|
- [ ] HTTPS or localhost only
|
|
393
|
-
- [ ] `
|
|
394
|
-
- [ ] Angular Universal: `isPlatformBrowser` guards in PushService
|
|
380
|
+
- [ ] SSR projects keep all `firebase/messaging` access behind the browser guard
|
|
395
381
|
|
|
396
382
|
---
|
|
397
383
|
|
|
398
|
-
##
|
|
384
|
+
## 14. Pointers
|
|
399
385
|
|
|
400
|
-
- `cometchat-
|
|
401
|
-
- `cometchat-angular-
|
|
402
|
-
- `cometchat-
|
|
403
|
-
- `cometchat-angular-troubleshooting` — SW registration
|
|
386
|
+
- `cometchat-angular-core` — init → login order, `loggedInUser$`, environment config
|
|
387
|
+
- `cometchat-angular-production` — server-minted auth tokens (registration binds to the auth token)
|
|
388
|
+
- `cometchat-react-push` — sibling web-push concepts (self-hosted Web Push model; FCM + Notifications API here is the shared, recommended SDK path)
|
|
389
|
+
- `cometchat-angular-troubleshooting` — SW registration / FCM token debugging
|