Imported from cometchat/cometchat-skills (
skills/cometchat-flutter-v6-migration/SKILL.md). Install upstream withnpx skills add cometchat/cometchat-skills --skill cometchat-flutter-v6-migration. Copyright stays with the author (MIT).
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 — v5 to v6 Migration
Complete guide for migrating a consumer app from UIKit v5 to v6.
What Changed
| Area | v5 | v6 |
|---|---|---|
| Packages | cometchat_chat_uikit + cometchat_calls_uikit (separate) |
cometchat_chat_uikit only (calls bundled) |
| State | GetX (Get.put, GetBuilder, Obx, .obs, RxBool) |
Plain StatefulWidget + setState() |
| Navigation | PageManager (GetxController singleton) |
Direct Navigator.push |
| Init | InitializeCometChat.init() + CometChatCallingExtension() + extensions + aiFeature |
Inline CometChatUIKit.init() + enableCalls: true + CallingConfiguration() |
| Calls SDK init | CometChatCallingExtension() in extensions list |
Automatic via ..enableCalls = true on UIKitSettingsBuilder (kit auto-invokes CallEventService internally on both fresh login and cached-session restore; no manual init required) |
| Screens | Separate controller + widget files per screen | Single file, state in StatefulWidget |
| Dashboard | MyHomePage/MyPageView with GetX PageManager |
HomeScreen with IndexedStack |
| Messages | MessagesSample + CometChatMessagesController |
MessagesScreen with listener mixins |
| Builder system | BuilderSettings, BuilderColor, BuilderTypography |
Removed — toggle features per-widget (e.g. disableReactions, hideReplyInThreadOption on CometChatMessageList) or via the relevant component's constructor params. There is no global ComponentToggles class. |
| Notifications | VoipNotificationHandler, APNSService |
VoipCallHandler, ApnsService |
| Extra deps | get, google_sign_in, firebase_auth, bugsee_flutter, shared_preferences, toast, mobile_scanner, app_badge_plus |
None of these |
| Localization | cc.Translations.delegate + GlobalMaterialLocalizations in MaterialApp |
Handled by UIKit internally |
| Call screen | callMain() entry point + CallApp + CallScreen widget |
CometChatOngoingCall widget for the in-call UI + the kit's IncomingCallOverlay (imperative singleton automatically invoked by CallEventService when enableCalls = true — do NOT mount it manually). No separate Dart entry point. |
| Android minSdk | 24 | 26 (required by cometchat_calls_sdk) |
Step 1: pubspec.yaml
# ❌ v5
dependencies:
cometchat_chat_uikit:
path: ../chat_uikit
cometchat_calls_uikit:
path: ../calls_uikit
get: ^4.6.5
google_sign_in: ^6.2.2
firebase_auth: ^5.3.4
bugsee_flutter: ^8.0.0
permission_handler: ^11.3.1
shared_preferences: ^2.2.1
toast: ^0.3.0
mobile_scanner: ^7.1.2
app_badge_plus: ^1.2.6
# ✅ v6 — GA is on pub.dev; use a plain dependency (NOT a Cloudsmith `hosted:` stanza,
# which only carries the pre-GA 6.0.0-beta* builds and fails version solving for ^6.0.x).
dependencies:
cometchat_chat_uikit: ^6.0.1 # resolves 6.0.1/6.0.2/6.0.3 from pub.dev
firebase_core: ^3.9.0
firebase_crashlytics: ^4.1.3
firebase_messaging: ^15.1.6
flutter_local_notifications: ^18.0.0
flutter_callkit_incoming: ^2.5.0
http: ^1.2.0
intl: ^0.20.2
Step 2: Fix All Imports
| v5 Import | v6 Import |
|---|---|
package:cometchat_calls_uikit/cometchat_calls_uikit.dart |
package:cometchat_chat_uikit/cometchat_calls_uikit.dart |
package:get/get.dart |
Remove entirely |
builder/builder_settings.dart |
Remove — toggle features per-widget instead (no global toggle class in v6) |
builder/builder_settings_helper.dart |
Remove |
utils/page_manager.dart |
Remove — use Navigator.push |
utils/initialize_cometchat.dart |
Remove — inline init |
utils/bool_singleton.dart |
Remove |
utils/text_constants.dart |
Remove |
prefs/shared_preferences.dart |
Remove |
Step 3: Rewrite Init
// ❌ v5 — helper class with CometChatCallingExtension + extensions + aiFeature
class InitializeCometChat {
static Future<bool> init() async {
final builder = UIKitSettingsBuilder()
..callingExtension = CometChatCallingExtension() // REMOVED in v6
..extensions = CometChatUIKitChatExtensions.getDefaultExtensions() // REMOVED
..aiFeature = CometChatUIKitChatAIFeatures.getDefaultAiFeatures(); // REMOVED
// ...
}
}
// ✅ v6 — inline, enableCalls + CallingConfiguration replace all three
final settings = (UIKitSettingsBuilder()
..subscriptionType = CometChatSubscriptionType.allUsers
..region = AppCredentials.region
..appId = AppCredentials.appId
..authKey = AppCredentials.authKey
..enableCalls = true
..callingConfiguration = CallingConfiguration())
.build();
CometChatUIKit.init(uiKitSettings: settings, onSuccess: (_) { ... });
Removed v5 UIKitSettingsBuilder properties
callingExtension→ replaced byenableCalls: trueextensions→ removed (extensions auto-registered in v6)aiFeature→ removed (AI features auto-registered in v6)
Calls SDK Init for Cached Sessions
With ..enableCalls = true on UIKitSettingsBuilder, the kit invokes CallEventService.instance.init(...) automatically for BOTH fresh logins AND cached-session restores (verified in cometchat_chat_uikit-6.0.1/lib/shared_ui/src/cometchat_ui_kit/cometchat_ui_kit.dart lines 170–179 — _initiateAfterLogin() is called from both CometChatUIKit.init cached-user branch and CometChatUIKit.login). No manual CallEventService.instance.init() call is required or recommended.
Step 4: Remove GetX
PageManager → Navigator.push
// ❌ v5
Get.put(PageManager());
Get.find<PageManager>().navigateToMessages(context: context, user: user);
// ✅ v6
Navigator.push(context, MaterialPageRoute(
builder: (_) => MessagesScreen(user: user),
));
GetBuilder → StatefulWidget with listener mixins
// ❌ v5
GetBuilder<CometChatMessagesController>(
init: messagesController,
tag: messagesController.tag,
builder: (controller) => Scaffold(/* ... */),
)
// ✅ v6
class _MessagesScreenState extends State<MessagesScreen>
with UserListener, CometChatUserEventListener,
GroupListener, CometChatGroupEventListener {
late User? _user;
late Group? _group;
// setState() instead of controller.update()
}
Rx variables → plain state
// ❌ v5
var isBlockLoading = false.obs;
// Usage: isBlockLoading.value = true;
// ✅ v6
bool _isUserBlocked = false;
// Usage: setState(() => _isUserBlocked = true);
Obx dialogs → StatefulBuilder
// ❌ v5 — Obx in dialog for loading indicator
Obx(() => isLoading.value ? CircularProgressIndicator() : Icon(Icons.check))
// ✅ v6 — StatefulBuilder in dialog
StatefulBuilder(builder: (context, setDialogState) {
return isLoading ? CircularProgressIndicator() : Icon(Icons.check);
})
Step 5: Removed v5 APIs
These v5 widget parameters/classes don't exist in v6:
| v5 API | Status in v6 |
|---|---|
CometChatCompactMessageComposer |
Removed — use CometChatMessageComposer |
CometChatAIAssistantChatHistory |
Removed |
CometChatMessageHeader options param |
Removed — use trailingView |
CometChatMessageList messageId param |
Removed — use goToMessageId |
CometChatMessageList hideFlagOption |
Removed |
CometChatMessageList generateConversationSummary |
Removed |
getDataSource() on message list |
Removed |
AssetConstants.conversationSummaryOutlined |
Removed |
CometChatBannedMembers (standalone widget) |
Not exported in v6 |
CometChatCallLogParticipants (standalone) |
Not exported in v6 |
CometChatCallLogRecordings (standalone) |
Not exported in v6 |
CometChatCallLogHistory (standalone) |
Not exported in v6 |
CometChatCallingExtension() |
Replaced by enableCalls: true + CallingConfiguration() |
CometChatUIKitChatExtensions.getDefaultExtensions() |
Removed — auto-registered |
CometChatUIKitChatAIFeatures.getDefaultAiFeatures() |
Removed — auto-registered |
CallSettingsBuilder |
Replaced by SessionSettingsBuilder |
FormatPatterns.stripFormatting() |
Removed |
CallStateController.instance |
Replaced by CallStateService.instance |
CallSettingsBuilder → SessionSettingsBuilder
// ❌ v5
CallSettingsBuilder()
..enableDefaultLayout = true
// ✅ v6
SessionSettingsBuilder()
..setLayout(LayoutType.tile)
..startVideoPaused(true) // for audio calls
..hideSwitchCameraButton(true)
..hideToggleVideoButton(true)
Step 6: Flatten Screen Structure
# ❌ v5 — controller + widget per screen
messages/
├── messages.dart # MessagesSample widget
└── messages_controller.dart # GetxController
group_info/
├── cometchat_group_info.dart
└── cometchat_group_info_controller.dart
# ✅ v6 — single file per screen
screens/
├── messages_screen.dart # Widget + state + listeners
├── group_info_screen.dart
├── home_screen.dart
└── ...
Class Rename Map
| v5 Class | v6 Class |
|---|---|
MyHomePage / MyPageView |
HomeScreen |
MessagesSample |
MessagesScreen |
GuardScreen |
GuardScreen (same name, rewritten) |
LoginSampleUsers |
LoginScreen |
Step 7: Update MaterialApp
// ❌ v5 — localization delegates, BuilderTypography, callMain entry point
MaterialApp(
supportedLocales: const [Locale('en'), Locale('ar'), ...],
localizationsDelegates: const [
cc.Translations.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
theme: ThemeData(
fontFamily: BuilderTypography.font,
extensions: [CometChatColorPalette(primary: BuilderColor.brandColor)],
),
navigatorKey: CallNavigationContext.navigatorKey,
)
// ✅ v6 — Material 3, no builder system, no localization delegates
MaterialApp(
debugShowCheckedModeBanner: false,
navigatorKey: LocalNotificationService.navigatorKey,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple, brightness: Brightness.dark),
useMaterial3: true,
brightness: Brightness.dark,
),
themeMode: ThemeMode.system,
)
Remove the callMain() entry point and CallApp/CallScreen widget entirely. V6 renders the in-call UI via the CometChatOngoingCall widget (placed in your widget tree once the call is active) and presents incoming calls via the IncomingCallOverlay widget. (The kit DOES expose CallScreenOverlay.show(...) — call_ui/src/ongoing_call/call_screen_overlay.dart — which it uses internally for the outgoing→in-call transition.)
Step 8: Update Notification Services
| v5 Class | v6 Class |
|---|---|
VoipNotificationHandler |
VoipCallHandler |
APNSService |
ApnsService |
FirebaseService |
FirebaseService (same) |
VoIP Cold Start
// ❌ v5 — handled in dashboard initState
VoipNotificationHandler.handleNativeCallIntent(context);
// ✅ v6 — init early in main(), markSdkReady after login
VoipCallHandler.instance.init(); // in main()
await VoipCallHandler.instance.markSdkReady(); // after login
Step 9: resizeToAvoidBottomInset
// ❌ v5 — SafeArea wrapping around the composer
Scaffold(body: SafeArea(child: Column(children: [messageList, composer])))
// ✅ v6 on ^6.0.1 — true (or omit; true is the default). The composer clamps
// the keyboard height to viewInsets (kit fix ENG-34434), so true does NOT
// double-compensate. (false was only the pre-6.0.1 workaround — if you still
// see a double keyboard gap, upgrade the kit.)
Scaffold(
resizeToAvoidBottomInset: true,
body: Column(children: [Expanded(child: messageList), composer]),
)
Step 10: Android Build
In android/app/build.gradle(.kts):
defaultConfig {
minSdk = 26 // Was 24 in v5, required by cometchat_calls_sdk in v6
}
In android/gradle.properties:
android.enableJetifier=true // Required for support library conflicts
Step 11: Delete v5 Files
builder/folder entirelyutils/page_manager.dart,initialize_cometchat.dart,bool_singleton.dart,text_constants.dartprefs/shared_preferences.dartservices/bugsee_services.dartqr_scanner/folderai_agents/foldercall_screen.dartdemo_meta_info_constants.dart(recreate minimal if needed)- All
*_controller.dartfiles auth/login_screen.dart(if it depended on google_sign_in/firebase_auth)
Gotchas
CometChatCallingExtension(),extensions, andaiFeatureon UIKitSettingsBuilder don't exist in v6. Extensions and AI features are auto-registered. OnlyenableCalls: true+CallingConfiguration()is needed.CallSettingsBuilderis renamed toSessionSettingsBuilderwith different API:.setLayout(LayoutType.tile)instead of..enableDefaultLayout = true.- v6
CometChatMessageListdoesn't havemessageIdparam — usegoToMessageIdinstead. CometChatBannedMembers,CometChatCallLogParticipants,CometChatCallLogRecordings,CometChatCallLogHistoryare not exported as standalone widgets in v6.- The
callMain()entry point pattern (separate Dart entry point for Android CallActivity) is gone. V6 renders the in-call UI via theCometChatOngoingCallwidget within your existing app navigator + theIncomingCallOverlaywidget for incoming-call UI. FormatPatterns.stripFormatting()doesn't exist in v6. UseMarkdownTextFormatterinstead.
Checklist
-
pubspec.yaml— removecometchat_calls_uikit,get, and all unused deps - All imports —
cometchat_calls_uikit→cometchat_chat_uikit/cometchat_calls_uikit.dart - All imports — remove
get/get.dart - Init — remove
CometChatCallingExtension,extensions,aiFeature; addenableCalls+CallingConfiguration - Add
CallEventService.instance.init()for cached sessions - Remove
PageManager— replace withNavigator.push - Remove all
GetBuilder/Obx/Get.put/Get.find - Remove all
*_controller.dartfiles - Flatten screens into
screens/folder - Remove
BuilderSettings— toggle features per-widget (e.g.disableReactions,hideReplyInThreadOption) on the relevant CometChat widget instead - Update
MaterialApp— remove localization delegates, removeBuilderTypography - Remove
callMain()entry point andCallScreenwidget -
CallSettingsBuilder→SessionSettingsBuilder -
resizeToAvoidBottomInset: true(or omitted) on Scaffolds with composer on^6.0.1— composer clamps toviewInsets(ENG-34434);falseis only the pre-6.0.1 stopgap - Android
minSdk= 26 - Android
enableJetifier = true - Delete all unused v5 files
- Test: init → login → conversations → messages → calls → logout → re-login