diff --git a/docs.json b/docs.json index 172825868..f66ecd986 100644 --- a/docs.json +++ b/docs.json @@ -2032,7 +2032,8 @@ "ui-kit/flutter/extensions" ] }, - "ui-kit/flutter/call-features" + "ui-kit/flutter/call-features", + "ui-kit/flutter/campaigns" ] }, { @@ -2062,7 +2063,8 @@ "ui-kit/flutter/outgoing-call", "ui-kit/flutter/call-buttons", "ui-kit/flutter/call-logs", - "ui-kit/flutter/search" + "ui-kit/flutter/search", + "ui-kit/flutter/notification-feed" ] }, { @@ -4418,6 +4420,7 @@ }, "sdk/flutter/ai-moderation", "sdk/flutter/ai-agents", + "sdk/flutter/campaigns", { "group": "Resources", "pages": [ diff --git a/images/announcement.png b/images/announcement.png new file mode 100644 index 000000000..db37af243 Binary files /dev/null and b/images/announcement.png differ diff --git a/images/campaigns-overview.png b/images/campaigns-overview.png new file mode 100644 index 000000000..6877cfce3 Binary files /dev/null and b/images/campaigns-overview.png differ diff --git a/images/create-bubble.png b/images/create-bubble.png new file mode 100644 index 000000000..65e01d45f Binary files /dev/null and b/images/create-bubble.png differ diff --git a/images/create-campaign.png b/images/create-campaign.png new file mode 100644 index 000000000..79d1a73d6 Binary files /dev/null and b/images/create-campaign.png differ diff --git a/images/create-category.png b/images/create-category.png new file mode 100644 index 000000000..60df6af3a Binary files /dev/null and b/images/create-category.png differ diff --git a/images/create-channel.png b/images/create-channel.png new file mode 100644 index 000000000..90aa852ce Binary files /dev/null and b/images/create-channel.png differ diff --git a/images/create-template.png b/images/create-template.png new file mode 100644 index 000000000..b3dab20ca Binary files /dev/null and b/images/create-template.png differ diff --git a/sdk/flutter/campaigns.mdx b/sdk/flutter/campaigns.mdx new file mode 100644 index 000000000..0d98a23e2 --- /dev/null +++ b/sdk/flutter/campaigns.mdx @@ -0,0 +1,489 @@ +--- +title: "Campaigns" +description: "Fetch notification feed items, listen for real-time delivery, mark items as read/delivered, report engagement, and retrieve unread counts in Flutter." +--- + +CometChat Campaigns lets you deliver targeted, rich notifications to users via an in-app notification feed. Each notification is a **Card Schema JSON** — a structured layout rendered natively by the CometChat Cards library. + +The SDK provides APIs to fetch feed items, listen for real-time delivery, mark items as read/delivered, report engagement, and retrieve unread counts. + +--- + +## Key Concepts + +| Concept | Description | +| --- | --- | +| **NotificationFeedItem** | A single notification in the feed. Contains Card Schema JSON in its `content` field, a `category` for filtering, timestamps, and metadata. | +| **NotificationCategory** | A category label used for filter chips (e.g., "Promotions", "Updates"). | +| **Card Schema JSON** | The fully rendered card layout (images, text, buttons) inside `NotificationFeedItem.content`. Passed directly to the CometChat Cards renderer. | +| **PushNotification** | Represents a campaign push notification payload received via FCM/APNs. | + +--- + +## How Cards Render in the Notification Feed + +Each `NotificationFeedItem` has a `content` field containing a `Map` — this is the **Card Schema JSON**. This JSON is passed directly to the **CometChat Cards** renderer package (`cometchat_cards`). + +The rendering flow: + +1. Fetch feed items via `NotificationFeedRequest` +2. For each item, extract `item.content` — this is the Card Schema JSON +3. Convert to string: `jsonEncode(item.content)` +4. Pass to the Cards renderer (`CometChatCardView`) +5. The renderer produces a native Flutter widget from the JSON + +### Card Schema JSON Structure + +```json +{ + "version": "1.0", + "body": [ + { + "type": "column", + "backgroundColor": { + "light": "transparent", + "dark": "transparent" + }, + "gap": 5, + "items": [ + { + "type": "text", + "content": "📢 Announcement", + "variant": "heading2", + "id": "txt_99323141-2459-4e33-88d3-ca39c5fd2f50" + }, + { + "type": "text", + "content": "Your announcement message here.", + "variant": "body", + "id": "txt_61a417bc-5e4a-4ba2-bfe7-b7bc64dbaf35" + }, + { + "type": "divider", + "id": "div_80f5c7fb-fd10-41d1-8c2f-51498f0f62d0" + }, + { + "type": "button", + "label": "Learn More", + "backgroundColor": { + "light": "transparent", + "dark": "transparent" + }, + "textColor": { + "light": "#6C5CE7", + "dark": "#6C5CE7" + }, + "size": 40, + "fontSize": 13, + "borderRadius": 6, + "padding": { + "top": 0, + "right": 16, + "bottom": 0, + "left": 16 + }, + "action": { + "type": "openUrl", + "url": "" + }, + "id": "btn_9b87a3f1-b0c6-45b9-a4c2-e22ea590f17f" + } + ], + "id": "col_98fed9bd-1a95-4cee-aa81-84a9016e41f2" + } + ], + "fallbackText": "", + "style": { + "background": { + "light": "#E8E8E8", + "dark": "#E8E8E8" + }, + "borderRadius": 16, + "borderColor": { + "light": "#DFE6E9", + "dark": "#DFE6E9" + }, + "padding": 12 + } +} +``` + +The `body` array contains elements (text, image, button, row, column, etc.) rendered top-to-bottom. Interactive elements like buttons emit actions via a callback — the consumer handles navigation, deep links, or API calls. + +--- + +## Retrieve Notification Feed Items + +Use `NotificationFeedRequest` to fetch a paginated list of feed items. Uses cursor-based pagination internally. + +### Build the Request + + + +```dart +final request = (NotificationFeedRequestBuilder() + ..setLimit(20)) + .build(); +``` + + + +### Builder Parameters + +| Method | Type | Default | Description | +| --- | --- | --- | --- | +| `setLimit(int)` | int | 20 | Items per page (max 100) | +| `setReadState(FeedReadState)` | enum | `FeedReadState.all` | Filter by `read`, `unread`, or `all` | +| `setCategory(String)` | String | null | Filter by category ID | +| `setChannelId(String)` | String | null | Filter by channel | +| `setTags(List)` | List | null | Filter by tags | +| `setDateFrom(String)` | String | null | ISO 8601 date — items sent on or after | +| `setDateTo(String)` | String | null | ISO 8601 date — items sent on or before | + +### Fetch Items + + + +```dart +request.fetchNext( + onSuccess: (List items) { + for (final item in items) { + final cardJson = jsonEncode(item.content); + // Pass cardJson to CometChatCardView + } + }, + onError: (CometChatException e) { + debugPrint("Error: ${e.message}"); + }, +); +``` + + + +Call `fetchNext()` repeatedly for pagination. When the server has no more items, subsequent calls return an empty list. + +### NotificationFeedItem Fields + +| Field | Type | Description | +| --- | --- | --- | +| `id` | String | Unique item identifier | +| `category` | String | Notification category (e.g., "promotions") | +| `categoryId` | String? | Category ID for programmatic filtering | +| `content` | Map\ | Card Schema JSON — pass to CometChat Cards renderer | +| `readAt` | int? | Unix timestamp when read, or null if unread | +| `deliveredAt` | int? | Unix timestamp when delivered, or null | +| `sentAt` | int | Unix timestamp when sent | +| `metadata` | Map\ | Custom key-value metadata | +| `tags` | List\ | Tags for filtering | +| `sender` | String | Sender identifier | +| `receiver` | String | Receiver identifier | +| `receiverType` | String | Receiver type | +| `isRead` | bool | Computed property — `true` if `readAt != null` | + +--- + +## Retrieve Notification Categories + +Use `NotificationCategoriesRequest` to fetch available categories for filter chips. + + + +```dart +final categoriesRequest = (NotificationCategoriesRequestBuilder() + ..setLimit(50)) + .build(); + +categoriesRequest.fetchNext( + onSuccess: (List categories) { + for (final category in categories) { + debugPrint("Category: ${category.name}"); + } + }, + onError: (CometChatException e) { + debugPrint("Error: ${e.message}"); + }, +); +``` + + + +### NotificationCategory Fields + +| Field | Type | Description | +| --- | --- | --- | +| `id` | String | Category identifier | +| `name` | String | Display name for filter UI | +| `description` | String | Category description | +| `appId` | String | Associated app ID | + +--- + +## Real-Time Notification Feed Listener + +Listen for new feed items arriving via WebSocket. This listener is independent from `MessageListener`, `GroupListener`, and `CallListener`. + + + +```dart +class MyNotificationFeedListener with NotificationFeedListener { + @override + void onFeedItemReceived(NotificationFeedItem feedItem) { + debugPrint("New item: ${feedItem.id}"); + final cardJson = jsonEncode(feedItem.content); + // Insert at top of feed and render + } +} + +CometChat.addNotificationFeedListener( + "feedListener", + MyNotificationFeedListener(), +); +``` + + + +Remove the listener when no longer needed: + + + +```dart +CometChat.removeNotificationFeedListener("feedListener"); +``` + + + +--- + +## Mark Feed Item as Read + +Mark a single item as read. Idempotent — safe to call multiple times. + + + +```dart +CometChat.markFeedItemAsRead( + feedItem, + onSuccess: (result) { + debugPrint("Marked as read"); + }, + onError: (CometChatException e) { + debugPrint("Error: ${e.message}"); + }, +); +``` + + + +--- + +## Mark Feed Item as Delivered + +Mark a single item as delivered. Idempotent. + + + +```dart +CometChat.markFeedItemAsDelivered( + feedItem, + onSuccess: (result) { + // Success + }, + onError: (CometChatException e) { + debugPrint("Error: ${e.message}"); + }, +); +``` + + + +--- + +## Report Engagement + +Report that a user engaged with a feed item (e.g., viewed, clicked, interacted). Idempotent. + + + +```dart +CometChat.reportFeedEngagement( + feedItem, + "clicked", + onSuccess: (result) {}, + onError: (CometChatException e) {}, +); +``` + + + +The `interactionString` parameter is a free-form string describing the engagement (e.g., `"viewed"`, `"clicked"`, `"interacted"`). + +--- + +## Get Unread Count + +Fetch the total number of unread notification feed items. + + + +```dart +CometChat.getNotificationFeedUnreadCount( + onSuccess: (int count) { + debugPrint("Unread: $count"); + }, + onError: (CometChatException e) { + debugPrint("Error: ${e.message}"); + }, +); +``` + + + +--- + +## Fetch Single Feed Item + +Fetch a specific item by ID — useful for deep linking from push notifications. + + + +```dart +CometChat.getNotificationFeedItem( + "item-id-123", + onSuccess: (NotificationFeedItem item) { + final cardJson = jsonEncode(item.content); + // Render the card + }, + onError: (CometChatException e) { + debugPrint("Error: ${e.message}"); + }, +); +``` + + + +--- + +## Push Notification Tracking + +When a campaign push notification arrives via FCM/APNs, use these methods to report delivery and click engagement. + +### Mark Push Notification as Delivered + +Call this when you receive the push notification payload: + + + +```dart +final pushNotification = PushNotification( + id: pushPayload['announcementId'], + announcementId: pushPayload['announcementId'], + campaignId: pushPayload['campaignId'], + source: "campaign", +); + +CometChat.markPushNotificationDelivered( + pushNotification, + onSuccess: (result) {}, + onError: (CometChatException e) {}, +); +``` + + + +### Mark Push Notification as Clicked + +Call this when the user taps the push notification: + + + +```dart +CometChat.markPushNotificationClicked( + pushNotification, + onSuccess: (result) {}, + onError: (CometChatException e) {}, +); +``` + + + +### PushNotification Fields + +| Field | Type | Description | +| --- | --- | --- | +| `id` | String | Announcement ID from the push payload | +| `announcementId` | String | Same as id (for clarity) | +| `campaignId` | String? | Campaign ID if from a campaign | +| `source` | String | Always `"campaign"` for notification feed pushes | + +--- + +## FeedReadState Enum + +| Value | Description | +| --- | --- | +| `FeedReadState.read` | Only read items | +| `FeedReadState.unread` | Only unread items | +| `FeedReadState.all` | All items (default) | + +--- + +## Rendering Cards + +The `content` field of each `NotificationFeedItem` is a Card Schema JSON map. To render it natively, use the CometChat Cards library. + +### Add the Cards Dependency + +Add the cards package to your `pubspec.yaml`: + +```yaml +dependencies: + cometchat_cards: ^1.0.0 +``` + +### Render a Card from a Feed Item + + + +```dart +import 'package:cometchat_cards/cometchat_cards.dart'; +import 'dart:convert'; + +Widget buildNotificationCard(NotificationFeedItem item) { + return CometChatCardView( + cardJson: jsonEncode(item.content), + themeMode: CometChatCardThemeMode.auto, + onAction: (CometChatCardActionEvent event) { + // Handle action: event.action, event.elementId + if (event.action is CometChatCardOpenUrlAction) { + // Open URL in browser + } else if (event.action is CometChatCardChatWithUserAction) { + // Navigate to chat + } + }, + ); +} +``` + + + + +The Cards library is a pure renderer — it does not execute actions. Your code must handle action callbacks (opening URLs, navigating to chats, making API calls, etc.). + + +--- + +## Supported Card Actions + +When a user taps a button or link inside a card, the action callback receives one of these action types: + +| Action Type | Parameters | Description | +| --- | --- | --- | +| `openUrl` | url, openIn | Open a URL in browser or webview | +| `chatWithUser` | uid | Navigate to 1:1 chat | +| `chatWithGroup` | guid | Navigate to group chat | +| `sendMessage` | text, receiverUid, receiverGuid | Send a text message | +| `copyToClipboard` | value | Copy text to clipboard | +| `downloadFile` | url, filename | Download a file | +| `initiateCall` | callType (audio/video), uid, guid | Start a call | +| `apiCall` | url, method, headers, body | Make an HTTP request | +| `customCallback` | callbackId, payload | App-specific logic | diff --git a/ui-kit/flutter/campaigns.mdx b/ui-kit/flutter/campaigns.mdx new file mode 100644 index 000000000..d63c4ddc6 --- /dev/null +++ b/ui-kit/flutter/campaigns.mdx @@ -0,0 +1,268 @@ +--- +title: "Campaigns" +description: "Deliver targeted, rich notifications to users via an in-app notification feed powered by the CometChat Cards renderer." +--- + +CometChat Campaigns enables you to send rich, interactive notifications to users through an in-app notification feed. Each notification is rendered as a native card using the **CometChat Cards** library — supporting images, text, buttons, layouts, and interactive actions. + + + + + +--- + +## Overview + +Campaigns delivers notifications as **Card Schema JSON** — a structured format that defines the visual layout of each notification card. The system consists of three layers: + +1. **CometChat Chat SDK** — Fetches feed items, manages read/delivered state, provides real-time listeners, handles push notification tracking +2. **CometChat Cards Library** — Renders Card Schema JSON into native Flutter widgets +3. **CometChat UI Kit** — Provides the ready-to-use `CometChatNotificationFeed` component that wires everything together + +### Architecture Flow + +``` +Dashboard / API → Campaign Created → Push + WebSocket Delivery + ↓ + SDK: NotificationFeedRequest.fetchNext() + ↓ + NotificationFeedItem.content → Card Schema JSON + ↓ + Cards Library: CometChatCardView + ↓ + Native Rendered Card (images, text, buttons, layouts) + ↓ + User taps button → ActionCallback → Your code handles it +``` + +--- + +## How Cards Work + +Each `NotificationFeedItem` from the SDK contains a `content` field — a `Map` holding the Card Schema JSON. This JSON is passed directly to the CometChat Cards renderer which produces a native Flutter widget. + +The Cards library is a **pure renderer**: +- **Input**: Card Schema JSON string + theme mode + optional action callback +- **Output**: Flutter widget tree + +It does not execute actions, manage message state, or call any SDK methods. When users tap interactive elements (buttons, links), the library emits the action to your callback. You decide what happens — open a URL, navigate to a chat, make an API call, etc. + +### Card Schema JSON Example + +```json +{ + "version": "1.0", + "body": [ + { + "type": "column", + "backgroundColor": { + "light": "transparent", + "dark": "transparent" + }, + "gap": 5, + "items": [ + { + "type": "text", + "content": "📢 Announcement", + "variant": "heading2", + "id": "txt_99323141-2459-4e33-88d3-ca39c5fd2f50" + }, + { + "type": "text", + "content": "Your announcement message here.", + "variant": "body", + "id": "txt_61a417bc-5e4a-4ba2-bfe7-b7bc64dbaf35" + }, + { + "type": "divider", + "id": "div_80f5c7fb-fd10-41d1-8c2f-51498f0f62d0" + }, + { + "type": "button", + "label": "Learn More", + "backgroundColor": { + "light": "transparent", + "dark": "transparent" + }, + "textColor": { + "light": "#6C5CE7", + "dark": "#6C5CE7" + }, + "size": 40, + "fontSize": 13, + "borderRadius": 6, + "padding": { + "top": 0, + "right": 16, + "bottom": 0, + "left": 16 + }, + "action": { + "type": "openUrl", + "url": "" + }, + "id": "btn_9b87a3f1-b0c6-45b9-a4c2-e22ea590f17f" + } + ], + "id": "col_98fed9bd-1a95-4cee-aa81-84a9016e41f2" + } + ], + "fallbackText": "", + "style": { + "background": { + "light": "#E8E8E8", + "dark": "#E8E8E8" + }, + "borderRadius": 16, + "borderColor": { + "light": "#DFE6E9", + "dark": "#DFE6E9" + }, + "padding": 12 + } +} +``` + +The schema supports **20 element types** (text, image, icon, avatar, badge, divider, spacer, chip, progressBar, codeBlock, markdown, row, column, grid, accordion, tabs, button, iconButton, link, table) and **9 action types** (openUrl, chatWithUser, chatWithGroup, sendMessage, copyToClipboard, downloadFile, initiateCall, apiCall, customCallback). + +Here's how the above JSON renders as a native card: + + + + + +--- + +## How Cards Work in the UI Kit + +The `CometChatNotificationFeed` component uses the **CometChat Cards** library internally to render each notification. Here's what happens under the hood: + +1. The component fetches `NotificationFeedItem` objects from the SDK +2. For each item, it extracts the `content` field (Card Schema JSON) +3. It passes the JSON to `CometChatCardView` from the Cards library +4. The Cards renderer produces native Flutter widgets — text, images, buttons, layouts — directly from the JSON +5. When users tap buttons/links inside a card, the action is emitted back to the component which handles navigation (open URL, navigate to chat, etc.) + +You don't need to interact with the Cards library directly when using `CometChatNotificationFeed` — it's all wired up. But if you want to render cards outside the feed (e.g., a standalone card in a dialog), you can use the Cards library directly. See the [SDK Campaigns documentation](/sdk/flutter/campaigns#rendering-cards) for standalone usage. + +--- + +## Handling Push Notifications for Campaigns + +When a campaign push notification arrives via FCM/APNs, you should: + +1. **Report delivery** — Call `CometChat.markPushNotificationDelivered()` in your push notification handler +2. **Report click** — Call `CometChat.markPushNotificationClicked()` when the user taps the notification +3. **Deep link** — Use the announcement ID from the push payload to fetch the full item via `CometChat.getNotificationFeedItem(id)` and display it + +```dart +// When push notification is received +final pushNotification = PushNotification( + id: payload['announcementId'], + announcementId: payload['announcementId'], + campaignId: payload['campaignId'], + source: "campaign", +); +CometChat.markPushNotificationDelivered(pushNotification, onSuccess: (_) {}, onError: (_) {}); + +// When user taps the notification +CometChat.markPushNotificationClicked(pushNotification, onSuccess: (_) {}, onError: (_) {}); + +// Navigate to feed or show specific item +CometChat.getNotificationFeedItem( + pushNotification.id, + onSuccess: (item) { /* render card */ }, + onError: (e) { /* handle error */ }, +); +``` + +See the [SDK Campaigns documentation](/sdk/flutter/campaigns) for the complete push notification tracking API. + +--- + +## Sending Campaigns + +Campaigns are created and managed from the **CometChat Dashboard**. Follow these steps to set up and send your first campaign: + +### Step 1: Create a Channel + +Channels define the delivery method for your campaigns (e.g., in-app notification feed, push notifications). + + + + + +### Step 2: Create a Category + +Categories are used for filter chips in the notification feed UI. Users can filter notifications by category (e.g., "Promotions", "Updates", "Orders"). + + + + + +### Step 3: Create a Template + +Templates define the card layout using the Card Schema JSON. You can design the visual structure — text, images, buttons, and layouts. + + + + + +### Step 4: Create a Bubble for the Template + +Design the card bubble — this is the actual Card Schema JSON that gets rendered natively in the notification feed using the Cards library. + + + + + +### Step 5: Create and Send a Campaign + +Define your audience, select the channel, category, and template, then send or schedule the campaign. + + + + + +--- + +## Using the UI Kit Component + +The easiest way to add a notification feed to your app is the `CometChatNotificationFeed` component. It handles fetching, rendering, pagination, filtering, real-time updates, and engagement reporting out of the box. + + + +```dart +import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart'; + +class NotificationsScreen extends StatelessWidget { + const NotificationsScreen({super.key}); + + @override + Widget build(BuildContext context) { + return CometChatNotificationFeed( + onItemClick: (NotificationFeedItem item) { + // Handle item tap + }, + onBackPress: () => Navigator.of(context).pop(), + ); + } +} +``` + + + +See the full [CometChatNotificationFeed component documentation](/ui-kit/flutter/notification-feed) for all configuration options, styling, and customization. + +--- + +## Next Steps + + + + Full API reference for feed items, categories, engagement, and push tracking + + + Ready-to-use component with filtering, real-time updates, and styling + + diff --git a/ui-kit/flutter/notification-feed.mdx b/ui-kit/flutter/notification-feed.mdx new file mode 100644 index 000000000..8705df47c --- /dev/null +++ b/ui-kit/flutter/notification-feed.mdx @@ -0,0 +1,409 @@ +--- +title: "Notification Feed" +description: "Full-screen notification feed component with category filtering, card rendering, real-time updates, and engagement reporting." +--- + +`CometChatNotificationFeed` displays a scrollable notification feed where each item is rendered as a native card using the CometChat Cards library. It handles fetching, pagination, category filtering, timestamp grouping, real-time updates, and read/delivered/engagement reporting automatically. + + + + + +--- + +## Where It Fits + +`CometChatNotificationFeed` is a full-screen component. Drop it into a route or screen. It manages its own data fetching, state, and real-time listeners — you just handle navigation callbacks. + + + +```dart +import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart'; + +class NotificationsScreen extends StatelessWidget { + const NotificationsScreen({super.key}); + + @override + Widget build(BuildContext context) { + return CometChatNotificationFeed( + showBackButton: true, + onBackPress: () => Navigator.of(context).pop(), + onItemClick: (NotificationFeedItem item) { + // Handle item tap (e.g., open detail or deep link) + }, + ); + } +} +``` + + + +--- + +## Quick Start + + + +```dart +import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart'; + +@override +Widget build(BuildContext context) { + return const CometChatNotificationFeed(); +} +``` + + + +Prerequisites: CometChat SDK initialized with `CometChatUIKit.init()` and a user logged in. + +--- + +## Filtering Feed Items + +Control what loads using custom request builders: + + + +```dart +CometChatNotificationFeed( + notificationFeedRequestBuilder: NotificationFeedRequestBuilder() + ..setLimit(30) + ..setReadState(FeedReadState.unread) + ..setCategory("promotions"), +) +``` + + + +### Filter Options + +| Builder Method | Description | +| --- | --- | +| `.setLimit(int)` | Items per page (default 20, max 100) | +| `.setReadState(FeedReadState)` | `read`, `unread`, or `all` | +| `.setCategory(String)` | Filter by category ID | +| `.setChannelId(String)` | Filter by channel | +| `.setTags(List)` | Filter by tags | +| `.setDateFrom(String)` | ISO 8601 date lower bound | +| `.setDateTo(String)` | ISO 8601 date upper bound | + + +Pass the builder object (without calling `.build()`). The component calls `.build()` internally. + + +--- + +## Actions and Events + +### Callback Methods + +#### `onItemClick` + +Fires when a feed item card is tapped. + + + +```dart +CometChatNotificationFeed( + onItemClick: (NotificationFeedItem item) { + // item.id, item.content (Card JSON), item.category + }, +) +``` + + + +#### `onActionClick` + +Fires when an interactive element (button, link) inside a card is tapped. + + + +```dart +CometChatNotificationFeed( + onActionClick: (NotificationFeedItem item, CometChatCardActionEvent action) { + if (action.action is CometChatCardOpenUrlAction) { + // Open URL in browser + } else if (action.action is CometChatCardChatWithUserAction) { + // Navigate to chat + } + }, +) +``` + + + +#### `onError` + +Fires when an internal error occurs (network failure, SDK exception). + + + +```dart +CometChatNotificationFeed( + onError: (String error) { + debugPrint("Feed error: $error"); + }, +) +``` + + + +#### `onBackPress` + +Fires when the back button in the header is tapped. + + + +```dart +CometChatNotificationFeed( + showBackButton: true, + onBackPress: () => Navigator.of(context).pop(), +) +``` + + + +### Automatic Behaviors + +The component handles these automatically — no manual setup needed: + +| Behavior | Description | +| --- | --- | +| Real-time updates | New items appear at the top via WebSocket listener | +| Delivery reporting | Items are reported as delivered when fetched | +| Read reporting | Items are reported as read after 1 second of visibility | +| Infinite scroll | Fetches next page when scrolling near the bottom | +| Pull-to-refresh | Resets and fetches fresh data on pull | +| Timestamp grouping | Groups items as "Today", "Yesterday", day name, or date | +| Category filtering | Filter chips row for category-based filtering | + +--- + +## Properties + +| Property | Type | Default | Description | +| --- | --- | --- | --- | +| `title` | String | `"Notifications"` | Header title text | +| `showHeader` | bool | `true` | Toggle header visibility | +| `showBackButton` | bool | `false` | Toggle back button | +| `showFilterChips` | bool | `true` | Toggle category filter chips | +| `headerView` | Widget? | null | Custom header widget | +| `scrollToItemId` | String? | null | Deep link to a specific item | +| `notificationFeedRequestBuilder` | NotificationFeedRequestBuilder? | null | Custom feed request | +| `notificationCategoriesRequestBuilder` | NotificationCategoriesRequestBuilder? | null | Custom categories request | +| `cardThemeMode` | CometChatCardThemeMode? | null | Card renderer theme mode | +| `cardThemeOverride` | CometChatCardThemeOverride? | null | Card renderer theme override | + +--- + +## Custom View Slots + +### Header View + +Replace the entire header: + + + +```dart +CometChatNotificationFeed( + headerView: Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Text( + "My Notifications", + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + ], + ), + ), +) +``` + + + +### State Views + + + +```dart +CometChatNotificationFeed( + emptyStateView: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.notifications_off, size: 64, color: Colors.grey), + SizedBox(height: 16), + Text("No notifications yet"), + ], + ), + ), + errorStateView: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text("Something went wrong"), + ElevatedButton( + onPressed: () { /* retry logic */ }, + child: Text("Retry"), + ), + ], + ), + ), + loadingStateView: const Center( + child: CircularProgressIndicator(), + ), +) +``` + + + +--- + +## Style + + + +```dart +CometChatNotificationFeed( + style: CometChatNotificationFeedStyle( + backgroundColor: Color(0xFFF5F5F5), + headerTitleColor: Color(0xFF141414), + chipActiveBackgroundColor: Color(0xFF3399FF), + chipActiveTextColor: Colors.white, + chipInactiveBackgroundColor: Colors.transparent, + chipInactiveTextColor: Color(0xFF727272), + chipBorderColor: Color(0xFFE0E0E0), + cardBackgroundColor: Colors.white, + cardBorderColor: Color(0xFFE0E0E0), + cardBorderRadius: 12, + unreadIndicatorColor: Color(0xFF3399FF), + ), +) +``` + + + +### Style Properties + +| Property | Type | Description | +| --- | --- | --- | +| `backgroundColor` | Color? | Screen background color | +| `headerTitleColor` | Color? | Header title text color | +| `headerTitleTextStyle` | TextStyle? | Header title text style | +| `backIconColor` | Color? | Back button icon color | +| `chipActiveBackgroundColor` | Color? | Selected filter chip background | +| `chipActiveTextColor` | Color? | Selected filter chip text | +| `chipInactiveBackgroundColor` | Color? | Unselected filter chip background | +| `chipInactiveTextColor` | Color? | Unselected filter chip text | +| `chipBorderColor` | Color? | Filter chip border | +| `chipTextStyle` | TextStyle? | Filter chip text style | +| `badgeBackgroundColor` | Color? | Badge background | +| `badgeTextColor` | Color? | Badge text | +| `badgeTextStyle` | TextStyle? | Badge text style | +| `timestampTextColor` | Color? | Item timestamp color | +| `timestampTextStyle` | TextStyle? | Item timestamp style | +| `timestampHeaderTextStyle` | TextStyle? | Section header timestamp style | +| `timestampHeaderTextColor` | Color? | Section header timestamp color | +| `cardBackgroundColor` | Color? | Card container background | +| `cardBorderColor` | Color? | Card container border | +| `cardBorderRadius` | double? | Card corner radius | +| `cardBorderWidth` | double? | Card border width | +| `unreadIndicatorColor` | Color? | Unread dot indicator color | +| `separatorColor` | Color? | Separator between cards | + +All colors default to `null` to inherit from `CometChatTheme`. Override individual values without losing theme support. + +--- + +## Deep Linking + +Navigate directly to a specific feed item using `scrollToItemId`: + + + +```dart +CometChatNotificationFeed( + scrollToItemId: "announcement-id-from-push", +) +``` + + + +If the item is already loaded, the feed scrolls to it. If not, it fetches the item by ID and inserts it at the top. + +--- + +## Common Patterns + +### Show only unread items + + + +```dart +CometChatNotificationFeed( + notificationFeedRequestBuilder: NotificationFeedRequestBuilder() + ..setReadState(FeedReadState.unread), +) +``` + + + +### Hide filter chips and header + + + +```dart +CometChatNotificationFeed( + showHeader: false, + showFilterChips: false, +) +``` + + + +### Custom categories request + + + +```dart +CometChatNotificationFeed( + notificationCategoriesRequestBuilder: NotificationCategoriesRequestBuilder() + ..setLimit(10), +) +``` + + + +### Card theme mode override + + + +```dart +CometChatNotificationFeed( + cardThemeMode: CometChatCardThemeMode.dark, +) +``` + + + +--- + +## Next Steps + + + + Overview of how campaigns work end-to-end + + + Low-level SDK APIs for feed items, categories, and engagement + + + Full styling reference for all components + + + Custom BLoCs, repositories, and data sources + + diff --git a/ui-kit/flutter/v5/getting-started.mdx b/ui-kit/flutter/v5/getting-started.mdx index 96032dc2b..2b9496dcf 100644 --- a/ui-kit/flutter/v5/getting-started.mdx +++ b/ui-kit/flutter/v5/getting-started.mdx @@ -86,8 +86,8 @@ Add to your `pubspec.yaml`: dependencies: flutter: sdk: flutter - cometchat_chat_uikit: ^5.2.14 - cometchat_calls_uikit: ^5.0.15 # Optional: for voice/video calling + cometchat_chat_uikit: ^5.2.16 + cometchat_calls_uikit: ^5.0.16 # Optional: for voice/video calling ``` Then run: