CometChat Flutter UIKit

repository·v6·Indexed 19 days ago

https://github.com/cometchat/cometchat-uikit-flutter

CometChat Flutter UIKit v6 provides a unified set of agent skills to build chat and calling features. This documentation focuses on the E2E integration test suite, detailing a single-device, dual-user testing model that uses a live CometChat backend and REST API to simulate real-time WebSocket events across iOS, Android, and Web platforms.

Tokens
82.9K
Snippets
176
Records
306
Agent score
66%

What's inside cometchat-uikit-flutter

  1. Use AI-powered Views

    v6

    The UIKit includes specialized views for AI features:

    • CometChatAISmartReplies: Tappable chips for AI-generated suggestions.
    • CometChatAIConversationStarter: Suggestions for starting conversations in empty chats.
    • CometChatAIConversationSummary: Displays a summary of the chat history.
    • CometChatAIAssistantBubble: A message bubble specifically for AI assistant responses, supporting streaming text.
  2. Use Utility Widgets

    v6

    The following utility widgets assist with common UI patterns:

    • CometChatListItem: A row component for lists, combining an avatar, status indicator, title, and subtitle. Supports slots like subtitleView and tailView.
    • CometChatConfirmDialog: A modal dialog. Use .show() to display it. Requires context, title, and messageText.
    • CometChatActionSheet: A bottom sheet for message actions (copy, reply, delete) or attachment options.
  3. Understand CometChat Flutter UIKit v6 feature categories

    v6

    Features in cometchat_chat_uikit are categorized by how they are activated:

    1. Auto-enabled: Work immediately when rendering standard components like CometChatMessageHeader, CometChatMessageList, and CometChatMessageComposer. Examples include text/media messages, reactions, and @mentions.
    2. UIKitSettings flag: Requires setting a property on UIKitSettingsBuilder before calling CometChatUIKit.init(). Examples include enabling voice/video calls or configuring presence/typing subscription types.
    3. Dashboard-toggle: Requires enabling an extension in the CometChat dashboard (app.cometchat.com → Extensions). The UIKit automatically wires the UI once the extension is active. Examples include Polls, Stickers, Smart Replies, and Message Translation.
  4. Understand the Image Bubble BLoC Architecture

    v6
    The ImageBubbleBloc is responsible for managing the lifecycle of image message bubbles. It handles image loading, caching, HEIC/HEIF format detection, and image display state. It follows a BLoC (Business Logic Component) pattern to separate the image processing logic from the UI presentation.
  5. Understand the Bubble BLoC Architecture

    v6

    The CometChat UI Kit uses the BLoC (Business Logic Component) pattern to manage the state of different message bubble types. This architecture separates business logic from the UI, ensuring that message-specific behaviors (like audio playback, file downloading, or AI streaming) are handled independently of the widget rendering.

    Each bubble type has a dedicated BLoC implementation located in lib/shared_ui/src/views/ (or within the clean_architecture directory for newer versions).

  6. Use Bubble Widgets inside CometChatMessageBubble

    v6

    Bubble widgets are content components designed to be rendered inside the contentView slot of a CometChatMessageBubble. Most accept colorPalette, spacing, and typography for theme optimization.

    • CometChatTextBubble: For text messages. Requires text.
    • CometChatImageBubble: For images. Requires imageUrl.
    • CometChatVideoBubble: For videos. Requires videoUrl and thumbnailUrl.
    • CometChatAudioBubble: For audio. Requires audioUrl.
    • CometChatFileBubble: For files. Requires fileUrl, title, and subtitle.
    • CometChatDeletedBubble: Placeholder for deleted messages.
    • CometChatCardBubble: Interactive cards with title, body, and action buttons.
  7. Secure CometChat production authentication

    v6

    In production, never include the authKey in your client-side code. The authKey grants full administrative access (logging in as any user, creating/updating users) and can be easily extracted from a decompiled APK or IPA.

    The Secure Workflow

    1. Server-Side Token Generation: Your backend should generate a server-minted authToken for the user.
    2. Client Login: Use CometChatUIKit.loginWithAuthToken() instead of CometChatUIKit.login().
    3. User Management: All user creation and profile updates must be performed server-side, not via the Flutter client.

    Handling Token Expiry

    If you have configured token expiry in the CometChat dashboard, handle the error in the onError callback to trigger a token refresh from your backend.

    // ✅ SECURE: Use server-minted tokens in production
    final settings = (UIKitSettingsBuilder()
          ..appId = appId
          ..region = region
          ..subscriptionType = CometChatSubscriptionType.allUsers)
        .build();
    
    // Login using the token
    CometChatUIKit.loginWithAuthToken(authToken, 
      onSuccess: (user) {
        // Proceed
      },
      onError: (e) {
        if (e.code == 'ERR_AUTH_TOKEN_NOT_FOUND' || e.code == 'AUTH_ERR_AUTH_TOKEN_NOT_FOUND') {
          // Token expired or invalid — fetch a new one from your backend
          refreshAndRetryLogin();
        }
      },
    );
  8. Understand the E2E Test Lifecycle and Structure

    v6

    Every integration test follows a standardized five-phase lifecycle to ensure consistency and isolation. This pattern uses dedicated helpers to manage the app state and peer interactions.

    1. Launch + Login: Uses AppLauncher.launchAndLogin(tester) to wipe the iOS Keychain, seed credentials, and log in as User A.
    2. Navigate: Uses NavigationHelper (e.g., goToTab, openUserBConversation) to move to the target screen.
    3. Act: Performs actions via the UI (using MessageHelper for User A) or via REST (using SdkUserB / UserBMessaging for User B).
    4. Wait: Uses realtime-aware helpers like pumpForRealtime or AssertionHelper.waitForMessage to wait for WebSocket events (avoid using pumpAndSettle).
    5. Assert: Verifies the UI using AssertionHelper. Structural assertions (presence of messages, navigation state) are fatal, while timing-dependent UI details (colors, exact presence text) are logged as non-fatal.
    6. Cleanup: Uses CleanupHelper.fullReset() to restore state (unblock users, delete conversations) so subsequent tests start clean.
    testWidgets('RT-MSG-001: Receive text message', (WidgetTester tester) async {
      await CleanupHelper.fullReset();                      // clean state
      await AppLauncher.launchAndLogin(tester);             // launch + login as User A
    
      await NavigationHelper.openUserBConversation(tester); // navigate to B's chat
    
      await SdkUserB.login();                               // make B "online"
      await UserBMessaging.sendTextToA('Hello from User B'); // B acts via REST
    
      await AssertionHelper.waitForMessage(                 // wait for the WebSocket event
        tester, 'Hello from User B',
      );
      AssertionHelper.expectMessageVisible(                 // fatal structural assertion
        tester, 'Hello from User B',
      );
    
      await CleanupHelper.fullReset();                      // cleanup
    });
  9. How Smart Content Resolution works in CometChatMessageBubble

    v6

    The CometChatMessageBubble is a smart component that automatically determines which content view to display based on the message category and type. It uses a BubbleFactory registry to resolve the correct UI.

    Resolution Process:

    1. The component calls BubbleFactory.getFactoryKey(message) to determine the appropriate factory key.
    2. It looks up the corresponding factory in the bubbleFactories map (e.g., "message_text" maps to TextBubbleFactory, "message_image" maps to ImageBubbleFactory).
    3. It calls factory.build(context, message, alignment) to generate the contentWidget.

    Precedence Rule: If you provide a contentView widget directly to the CometChatMessageBubble, it will take precedence over the auto-generated content from the factories.

  10. Best practices for Stream Playback

    v6

    Follow these guidelines to ensure stable playback and resource management:

    1. Initialize ServiceLocator: Always call _serviceLocator.initialize() before accessing any use cases.
    2. Unique Stream IDs: Use unique streamId strings for every concurrent stream to avoid collisions.
    3. Cleanup Subscriptions: Always cancel StreamSubscription in your widget's dispose() method.
    4. Resource Management: Explicitly call StopStreamUseCase when a stream is no longer needed to release underlying video_player resources.
    5. UI Updates: Use GetStreamStatusStreamUseCase for real-time UI updates instead of manual polling.
  11. How the two-user / realtime testing model works

    v6

    The E2E integration test suite uses a single-device model to simulate realtime interactions. While the Flutter SDK (User A) runs on the device/emulator, a second user (User B) is driven entirely via the CometChat REST API from within the test process using integration_test/sdk_user_b/.

    The Realtime Flow:

    1. User B makes a REST call (e.g., sending a message) using the onBehalfOf: userB header.
    2. The CometChat server receives the request.
    3. The server broadcasts a WebSocket event to User A.
    4. User A's SDK listener receives the event, triggering a UIKit update.
    5. The WidgetTester asserts that the UI reflects the change.

    Key Components:

    • SdkUserB (sdk_user_b.dart): An HTTP client used to drive User B. Calling login() or logout() manages User B's auth token to trigger presence events. Every request uses an onBehalfOf header to act as User B.
    • Capabilities of User B: Can drive messaging, reactions, threads, presence, blocking, receipts, calls, and group operations via specific action files (e.g., messaging_actions.dart, reaction_actions.dart).
    • Receipt Logic: Since User A's UI doesn't capture message IDs immediately, User B uses UserBMessaging.fetchLatestMessageIdFromA() to find the latest message authored by A to mark it as delivered or read.
    • Cumulative Receipts: markAsRead(id) marks all messages with an ID $\le$ id as read. To optimize API calls, markAllAsRead(list) should only target the highest ID in the list.
    • Isolation: Tests use CleanupHelper.seedConversation in setUpAll to prepare state and CleanupHelper.fullReset() in tearDown/setUp to unblock users and delete conversations, ensuring test isolation.