cometchat-flutter-v6

SkillCommunication

Use when building chat with CometChat Flutter UIKit v6 (cometchat_chat_uikit). Triggers on CometChatUIKit, CometChatConversations, CometChatMessageList, CometChatMessageComposer, CometChatMessageHeader, CometChatUsers, CometChatGroups, UIKitSettings, CometChatThemeHelper, CometChatColorPalette, ConversationsBloc, MessageListBloc, CometChatTextBubble, CometChatImageBubble, CometChatMessageBubble, CometChatMentionsFormatter, SliverSpacing, ERR_ALREADY_LOGGED_IN, ERR_INVALID_REGION, authentication null. Also for adding chat to Flutter, customizing bubbles, theming, real-time messages. Use whenever user mentions CometChat or says "chat UI".

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the cometchat-flutter-v6 skill

What this skill tells your AI

The instructions your AI receives, as published by cometchat/cometchat-skills in skills/cometchat-flutter-v6/SKILL.md and read by ahel’s review.

Ground truth: cometchat_chat_uikit: ^6.0 — pub-cache source + ui-kit/flutter. Official docs: https://www.cometchat.com/docs/ui-kit/flutter/overview · Docs MCP: claude mcp add --transport http cometchat-docs https://www.cometchat.com/docs/mcp (or fetch the URL directly without MCP). Verify symbols against the installed package/source before relying on them.

CometChat Flutter UIKit v6 — Orchestrator

Entry point skill for the cometchat_chat_uikit package. Routes to feature skills based on context.

Project Detection

Confirm the project uses CometChat UIKit by checking pubspec.yaml for:

dependencies:
  cometchat_chat_uikit: ^6.0.1   # V6 GA — plain pub.dev (do NOT use a `hosted:` Cloudsmith stanza)

V6 GA lives on pub.dev, NOT Cloudsmith. Cloudsmith (dart.cloudsmith.io/cometchat/cometchat/) only hosts the pre-GA 6.0.0-beta* builds; a --hosted-url/hosted: Cloudsmith install of ^6.0.x fails with "version solving failed". Use plain pub.dev. (Cloudsmith is only for the legacy V5 packages — see cometchat-flutter-v5.) The GA range resolves 6.0.1/6.0.2/6.0.3.

If missing, install via:

dart pub add cometchat_chat_uikit:^6.0.1

Call functionality is built into cometchat_chat_uikit — no separate package needed. To use call-specific types, import the calls barrel:

import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';
import 'package:cometchat_chat_uikit/cometchat_calls_uikit.dart'; // For call types

Skill Routing

User mentionsRoute to skill
init, login, logout, UIKitSettings, setup, credentials, appId, regioncometchat-flutter-v6-core
theme, colors, dark mode, styling, CometChatColorPalette, CometChatSpacing, typography, Style classcometchat-flutter-v6-theming
conversations, conversation list, recent chats, ConversationsBloccometchat-flutter-v6-conversations
messages, message list, composer, header, keyboard, rich text, bubbles, send messagecometchat-flutter-v6-messages
users, groups, group members, contacts, user listcometchat-flutter-v6-users-groups
events, listeners, real-time, typing indicator, online status, receipts, SDK listenercometchat-flutter-v6-events

Architecture Overview

The UIKit follows Clean Architecture + BLoC:

{component}/
├── bloc/           # BLoC, Events, State (Equatable)
├── domain/         # Use Cases, Repository interfaces
├── data/           # Repository impl, DataSources
├── di/             # ServiceLocator (singleton)
├── widgets/        # UI components
└── {component}.dart # Barrel export

All components: conversations, message_list, message_composer, message_header, users, groups, group_members, search, threaded_header, message_information.

Package Structure

chat_uikit/lib/
├── cometchat_chat_uikit.dart    # Main barrel export (chat components)
├── cometchat_calls_uikit.dart   # Calls barrel export
├── chat_ui/src/                 # Chat components (conversations, messages, users, groups, etc.)
├── call_ui/src/                 # Call components (incoming, outgoing, ongoing, call_logs)
└── shared_ui/                   # Shared utilities (theme, events, formatters, models, views)

Rule: AUTH_CHECK_AFTER_INIT

After CometChatUIKit.init() completes (in its onSuccess), the static field CometChatUIKit.loggedInUser is already populated if a cached session exists. Use this synchronous check — do NOT call CometChat.getLoggedInUser() separately.

// ✅ CORRECT — synchronous check after init completes
CometChatUIKit.init(
  uiKitSettings: settings,
  onSuccess: (_) {
    final hasUser = CometChatUIKit.loggedInUser != null;
    // Route to home or login based on hasUser
  },
);

// ❌ WRONG — separate async getLoggedInUser call after init
CometChatUIKit.init(
  uiKitSettings: settings,
  onSuccess: (_) {
    CometChat.getLoggedInUser(
      onSuccess: (user) { ... },  // Unreliable when no session exists
      onError: (e) { ... },
    );
  },
);

The init() method internally calls getLoggedInUser() and sets CometChatUIKit.loggedInUser before firing onSuccess. Calling it again is redundant and the callback-based version can silently fail when no session exists (the SDK logs "Please log in to CometChat before calling this method" and neither callback fires consistently).

This also applies to login() and loginWithAuthToken() — all three populate CometChatUIKit.loggedInUser before calling onSuccess.

// ❌ ALSO WRONG — async UIKit getLoggedInUser after init (redundant native bridge round-trip)
CometChatUIKit.init(
  uiKitSettings: settings,
  onSuccess: (_) async {
    final user = await CometChatUIKit.getLoggedInUser(); // Unnecessary!
    if (user != null) { ... }
  },
);

// ❌ ALSO WRONG — raw SDK getLoggedInUser (bypasses UIKit, unreliable)
User? existingUser = await CometChat.getLoggedInUser();

Golden Path — Minimal Chat App

import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';

// 1. Init (once, at app startup)
final settings = (UIKitSettingsBuilder()
      ..appId = 'YOUR_APP_ID'
      ..region = 'us'
      ..authKey = 'YOUR_AUTH_KEY'
      ..subscriptionType = CometChatSubscriptionType.allUsers)
    .build();
await CometChatUIKit.init(uiKitSettings: settings);

// 2. Login
await CometChatUIKit.loginWithAuthToken('AUTH_TOKEN');

// 3. Show conversations
CometChatConversations(
  onItemTap: (conversation) {
    final user = conversation.conversationWith is User
        ? conversation.conversationWith as User : null;
    final group = conversation.conversationWith is Group
        ? conversation.conversationWith as Group : null;
    // Navigate to messages screen
  },
)

// 4. Messages screen — on ^6.0.1 use resizeToAvoidBottomInset: true (or omit it)
Scaffold(
  resizeToAvoidBottomInset: true, // ^6.0.1: composer clamps to viewInsets (ENG-34434); `false` is the pre-6.0.1 stopgap only. See cometchat-flutter-v6-core SCAFFOLD_NO_RESIZE.
  appBar: CometChatMessageHeader(
    user: user,
    group: group,
    onBack: () => Navigator.pop(context),
  ),
  body: Column(
    children: [
      Expanded(child: CometChatMessageList(user: user, group: group)),
      CometChatMessageComposer(user: user, group: group),
    ],
  ),
)

Complete App Scaffold (main.dart)

Full working app with init → auth guard → login → home → logout. Copy-paste ready.

import 'package:flutter/material.dart';
import 'package:cometchat_chat_uikit/cometchat_chat_uikit.dart';

const String appId = 'YOUR_APP_ID';
const String region = 'us';
const String authKey = 'YOUR_AUTH_KEY';

void main() => runApp(const MyApp());

class MyApp extends StatefulWidget {
  const MyApp({super.key});
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool _initializing = true;
  bool _loggedIn = false;

  @override
  void initState() {
    super.initState();
    _initCometChat();
  }

  void _initCometChat() {
    final settings = (UIKitSettingsBuilder()
          ..appId = appId
          ..region = region
          ..authKey = authKey
          ..subscriptionType = CometChatSubscriptionType.allUsers)
        .build();

    CometChatUIKit.init(
      uiKitSettings: settings,
      onSuccess: (_) {
        // CometChatUIKit.loggedInUser is already set if a cached session exists
        setState(() {
          _loggedIn = CometChatUIKit.loggedInUser != null;
          _initializing = false;
        });
      },
      onError: (e) {
        debugPrint('Init failed: ${e.message}');
        setState(() => _initializing = false);
      },
    );
  }

  void _onLoginSuccess() => setState(() => _loggedIn = true);

  void _onLogout() => setState(() => _loggedIn = false);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: _initializing
          ? const Scaffold(body: Center(child: CircularProgressIndicator()))
          : _loggedIn
              ? HomeScreen(onLogout: _onLogout)
              : LoginScreen(onLoginSuccess: _onLoginSuccess),
    );
  }
}

// --- Login Screen ---
class LoginScreen extends StatefulWidget {
  final VoidCallback onLoginSuccess;
  const LoginScreen({super.key, required this.onLoginSuccess});
  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final _uidController = TextEditingController();
  bool _loggingIn = false;
  String? _error;

  void _login() {
    final uid = _uidController.text.trim();
    if (uid.isEmpty) return;
    setState(() { _loggingIn = true; _error = null; });

    CometChatUIKit.login(uid,
      onSuccess: (_) {
        if (mounted) { widget.onLoginSuccess(); }
      },
      onError: (e) {
        if (mounted) { setState(() { _loggingIn = false; _error = e.message; }); }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TextField(
              controller: _uidController,
              decoration: const InputDecoration(labelText: 'User ID'),
            ),
            const SizedBox(height: 16),
            if (_error != null)
              Text(_error!, style: const TextStyle(color: Colors.red)),
            const SizedBox(height: 16),
            ElevatedButton(
              onPressed: _loggingIn ? null : _login,
              child: _loggingIn
                  ? const SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2))
                  : const Text('Login'),
            ),
          ],
        ),
      ),
    );
  }
}

// --- Home Screen (Conversations → Messages) ---
class HomeScreen extends StatelessWidget {
  final VoidCallback onLogout;
  const HomeScreen({super.key, required this.onLogout});

  void _logout(BuildContext context) {
    CometChatUIKit.logout(
      onSuccess: (_) => onLogout(),
      onError: (e) => debugPrint('Logout failed: ${e.message}'),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Conversations'),
        actions: [
          IconButton(icon: const Icon(Icons.logout), onPressed: () => _logout(context)),
        ],
      ),
      body: CometChatConversations(
        onItemTap: (conversation) {
          final user = conversation.conversationWith is User
              ? conversation.conversationWith as User : null;
          final group = conversation.conversationWith is Group
              ? conversation.conversationWith as Group : null;
          Navigator.push(context, MaterialPageRoute(
            builder: (_) => MessagesScreen(user: user, group: group),
          ));
        },
      ),
    );
  }
}

// --- Messages Screen ---
class MessagesScreen extends StatelessWidget {
  final User? user;
  final Group? group;
  const MessagesScreen({super.key, this.user, this.group});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      resizeToAvoidBottomInset: true, // ^6.0.1: composer clamps to viewInsets (ENG-34434); `false` is the pre-6.0.1 stopgap only
      appBar: CometChatMessageHeader(
        user: user,
        group: group,
        onBack: () => Navigator.pop(context),
      ),
      body: Column(
        children: [
          Expanded(child: CometChatMessageList(user: user, group: group)),
          CometChatMessageComposer(user: user, group: group),
        ],
      ),
    );
  }
}

Key points in this scaffold:

  • CometChatUIKit.loggedInUser is checked synchronously after init() — no separate getLoggedInUser() call
  • State is managed at the MyApp level so login/logout transitions are clean
  • LoginScreen uses CometChatUIKit.login(uid) with auth key (set in UIKitSettings)
  • MessagesScreen has resizeToAvoidBottomInset: true (or omits it — true is the default; the composer clamps to viewInsets on ^6.0.1 per ENG-34434). false was the pre-6.0.1 stopgap only.
  • Logout calls CometChatUIKit.logout() and resets state

Common Error Debugging

SymptomCauseFix
"Authentication null"CometChatUIKit.init() not calledCall init before login/components
"APP ID null"appId not set in UIKitSettingsBuilderSet ..appId = 'YOUR_APP_ID'
Double keyboard gap on ^6.0.1+Leftover pre-6.0.1 resizeToAvoidBottomInset: false workaroundSet it to true (or omit) — the composer clamps the keyboard internally on 6.0.1+ (ENG-34434); false is what now double-compensates. Upgrade the kit if you still see a gap with true.
No typing indicators / presencesubscriptionType not setSet ..subscriptionType = CometChatSubscriptionType.allUsers
Theme jank during keyboardTheme looked up in build()Cache in didChangeDependencies() with _themeInitialized flag
Listener leak / duplicate eventsListener not removed in dispose()Always remove with same ID used to register
"ERR_ALREADY_LOGGED_IN"Calling login when session existsCheck CometChatUIKit.loggedInUser != null first (synchronous static field — aligns with §85 rule)
Messages not updating in real-timeSDK listener not registeredBLoC registers automatically; check component is mounted
Stale user/group dataPassing widget params instead of mutable stateKeep mutable _user/_group in State, update from listeners
Region errorUppercase region stringUse lowercase: 'us', 'eu', 'in'
Android internal error on loginSDK internal failure — often auth key issue, beta SDK bug, or networkVerify credentials are correct. Try CometChat.login(uid, authKey) directly instead of CometChatUIKit.login(uid). Check CometChat dashboard for UID existence. If using beta SDK, try stable release.
Guard screen stuck on spinnerUsing CometChat.getLoggedInUser() callback API after initUse CometChatUIKit.loggedInUser synchronously after init() completes — see AUTH_CHECK_AFTER_INIT rule
Release build crash (ClassNotFoundException)Missing ProGuard keep rulesAdd -keep class com.cometchat.** { *; } to proguard-rules.pro
Android build fails (minSdk)minSdk too lowSet minSdk = 26 in android/app/build.gradle
Android build fails (support library)Missing JetifierAdd android.enableJetifier=true to gradle.properties

Autonomous Mode

  • If pubspec.yaml has cometchat_chat_uikit → proceed without asking
  • If credentials exist in code → reuse them, don't ask
  • If user says "messages screen" → generate Scaffold + Header + List + Composer with resizeToAvoidBottomInset: true (or omit it — true is correct on ^6.0.1+)
  • Always add subscriptionType to UIKitSettingsBuilder
  • Always use CometChatThemeHelper for colors, never hardcode

Android Build Requirements

These are required in your Android project or the build/release will fail:

gradle.properties

android.useAndroidX=true
android.enableJetifier=true

enableJetifier resolves old Android Support Library conflicts from transitive dependencies.

minSdk 26

In android/app/build.gradle (or .kts):

defaultConfig {
    minSdk = 26  // Required by cometchat_calls_sdk
}

ProGuard / R8 Keep Rules

Create android/app/proguard-rules.pro:

# CometChat — prevent R8 from stripping SDK classes
-keep class com.cometchat.** { *; }
-keep interface com.cometchat.** { *; }

# Suppress warnings for Calls SDK classes referenced cross-module
-dontwarn com.cometchat.calls.CometChatRTCView$CometChatRTCViewBuilder
-dontwarn com.cometchat.calls.CometChatRTCView
-dontwarn com.cometchat.calls.CometChatRTCViewListener
-dontwarn com.cometchat.calls.model.AnalyticsSettings
-dontwarn com.cometchat.calls.model.RTCCallback
-dontwarn com.cometchat.calls.model.RTCReceiver

Reference it in build.gradle:

buildTypes {
    release {
        isMinifyEnabled = true
        isShrinkResources = true
        proguardFiles(
            getDefaultProguardFile("proguard-android-optimize.txt"),
            "proguard-rules.pro"
        )
    }
}

Without these rules, release builds crash with ClassNotFoundException for CometChat classes.

Signals

GitHub stars
105
Forks
2
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
cometchat-flutter-v6
Source
github.com/cometchat/cometchat-skills