diff --git a/sdk/ios/llms-ios-v4.mdx b/sdk/ios/llms-ios-v4.mdx new file mode 100644 index 000000000..e57f770b8 --- /dev/null +++ b/sdk/ios/llms-ios-v4.mdx @@ -0,0 +1,126 @@ +--- +title: "iOS Chat SDK v4 — LLM docs index" +description: "Machine-readable, iOS-SDK-v4-scoped index of every Chat SDK page as a clean .md twin. Built for AI coding agents; kept out of the human sidebar." +--- + +{/* + SCOPED LLM INDEX for the iOS Chat SDK v4. + - UNLISTED, NOT hidden: intentionally omitted from docs.json navigation so it never shows in + the human sidebar — but it IS built, served as a clean .md twin, and INDEXED for search + + AI assistants (so AI tools, and the skills pack via its docs-map, can discover and read it). + - We deliberately do NOT use `hidden: true`/`noindex` here: in Mintlify `hidden` auto-applies + noindex, which would drop this page from search AND the auto global llms.txt / AI context. + We want it discoverable, so it stays indexable. + - Scope is v4 ONLY. The 2.0/ and 3.0/ trees are deliberately excluded — linking them would + route agents at dead API surfaces. +*/} + +# iOS Chat SDK v4 — LLM docs index (Latest) + +> Headless Swift chat SDK. Package `CometChatSDK@4`. This page is an **iOS-SDK-v4-only** routing +> index for AI agents — a scoped alternative to the site-wide `/docs/llms.txt`. + +## How to use this index +Each link points to the docs page; **append `.md`** to its URL to fetch the clean Markdown twin. +Each page opens with an **"AI Integration Quick Reference"** block (package · import · key +methods) — read that FIRST, then the body for the full call. +- Convention: any docs page URL + `.md` → raw Markdown. +- Fallback: if a `.md` twin 404s, fetch the same URL **without** `.md` (HTML). +- Never answer a method signature from memory, and never read the framework binary's + `.swiftinterface` to decide *behaviour* — it proves a symbol exists, nothing more. + +## When to use this index +Two cases: +1. **Headless app** — no CometChat UI, you are building your own views on the SDK. +2. **UI Kit fallback** — the app uses the iOS UI Kit v5, but the feature you need ships **no UI + Kit component** (AI agents, campaigns, moderation, adding group members, transient messages, + low-level presence, webhooks). Check the kit first + ([iOS UI Kit v5 index](/ui-kit/ios/llms-ios-v5)); if there is no component, come here. + +## API facts an agent must not guess +- Callbacks use `.success` / `.onError` — **not** Swift's `Result.failure`. +- `CometChatException` does **not** conform to Swift's `Error`; read `errorDescription`, not + `localizedDescription`, and downcast with `error as? CometChatException`. +- Request objects use the **builder** pattern (`MessagesRequest.MessagesRequestBuilder`), and + listeners are registered per-class with a unique identifier you must later remove. +- In SwiftUI hosts, qualify SDK types (`CometChatSDK.User`, `CometChatSDK.Group`) — SwiftUI + declares its own `Group`. + +## Getting started +- [iOS SDK](/sdk/ios/overview) +- [Setup](/sdk/ios/setup) +- [Key Concepts](/sdk/ios/key-concepts) +- [Authentication](/sdk/ios/authentication-overview) +- [Changelog](/sdk/ios/changelog) +- [Upgrading From V3](/sdk/ios/upgrading-from-v3-to-v4) +- [Rate Limits](/sdk/ios/rate-limits) + +## Messaging +- [Send Messages](/sdk/ios/send-message) +- [Receive Messages](/sdk/ios/receive-message) +- [Edit Message](/sdk/ios/edit-message) +- [Delete Message](/sdk/ios/delete-message) +- [Flag Message](/sdk/ios/flag-message) +- [Message Filtering](/sdk/ios/additional-message-filtering) +- [Message Structure And Hierarchy](/sdk/ios/message-structure-and-hierarchy) +- [Threaded Messages](/sdk/ios/threaded-messages) +- [Transient Messages](/sdk/ios/transient-messages) +- [Upload Files & Send Attachments](/sdk/ios/upload-files) +- [Reactions](/sdk/ios/reactions) +- [Mentions](/sdk/ios/mentions) +- [Delivery & Read Receipts](/sdk/ios/delivery-read-receipts) +- [Typing Indicators](/sdk/ios/typing-indicators) + +## Conversations +- [Retrieve Conversations](/sdk/ios/retrieve-conversations) +- [Delete Conversation](/sdk/ios/delete-conversation) + +## Users +- [Users](/sdk/ios/users-overview) +- [User Management](/sdk/ios/user-management) +- [Retrieve Users](/sdk/ios/retrieve-users) +- [User Presence](/sdk/ios/user-presence) +- [Block Users](/sdk/ios/block-users) + +## Groups +- [Groups](/sdk/ios/groups-overview) +- [Create A Group](/sdk/ios/create-group) +- [Update A Group](/sdk/ios/update-group) +- [Delete A Group](/sdk/ios/delete-group) +- [Join A Group](/sdk/ios/join-group) +- [Leave A Group](/sdk/ios/leave-group) +- [Retrieve Groups](/sdk/ios/retrieve-groups) +- [Retrieve Group Members](/sdk/ios/retrieve-group-members) +- [Add Members To A Group](/sdk/ios/group-add-members) +- [Kick Member From A Group](/sdk/ios/group-kick-member) +- [Change Member Scope](/sdk/ios/group-change-member-scope) +- [Transfer Group Ownership](/sdk/ios/transfer-group-ownership) + +## Calling +- [Calling](/sdk/ios/calling-overview) + +## AI +- [AI](/sdk/ios/ai-user-copilot-overview) +- [AI Agents](/sdk/ios/ai-agents) +- [Bots](/sdk/ios/ai-chatbots-overview) +- [AI Moderation](/sdk/ios/ai-moderation) + +## Real-time, connection, and lifecycle +- [All Real Time Delegates (Listeners)](/sdk/ios/all-real-time-delegates-listeners) +- [Connection Status](/sdk/ios/connection-status) +- [Connection Behaviour](/sdk/ios/web-socket-connection-behaviour) +- [Managing Web Socket Connections Manually](/sdk/ios/managing-web-socket-connections-manually) + +## Push notifications +- [Prepare Your App For Background Updates](/sdk/ios/prepare-your-app-for-background-updates) +- [Launch Chat Window On Tap Of Push Notification](/sdk/ios/launch-chat-window-on-tap-of-push-notification) +- [Launch Call Screen On Tap Of Push Notification](/sdk/ios/launch-call-screen-on-tap-of-push-notification) +- [Marking Delivered From Push Notification](/sdk/ios/marking-delivered-with-push-notification) +- [Increment App Icon Badge Count](/sdk/ios/increment-app-icon-badge-count) +- [Remove Delivered Notifications](/sdk/ios/remove-delivered-notifications) + +## Platform extras +- [Extensions](/sdk/ios/extensions-overview) +- [Campaigns](/sdk/ios/campaigns) +- [Webhooks](/sdk/ios/webhooks-overview) +- [Publishing App On App Store](/sdk/ios/publishing-app-on-appstore) diff --git a/ui-kit/ios/ai-assistant-chat-history.mdx b/ui-kit/ios/ai-assistant-chat-history.mdx index a811738d7..66c7baac0 100644 --- a/ui-kit/ios/ai-assistant-chat-history.mdx +++ b/ui-kit/ios/ai-assistant-chat-history.mdx @@ -37,7 +37,7 @@ The `CometChatAIAssistanceChatHistory` component displays past conversations bet "sdkListeners": [], "compositionExample": { "description": "AIAssistanceChatHistory shows previous AI conversations for a user or group", - "components": ["CometChatAIAssistanceChatHistory", "CometChatMessages"], + "components": ["CometChatAIAssistanceChatHistory", "CometChatMessageList"], "flow": "User opens AI history → selects conversation → views full AI chat" } } @@ -258,7 +258,7 @@ class AIAssistantViewController: UIViewController { // MARK: - Actions private func startNewAIChat() { // Option 1: Open messages view for new AI chat - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user navigationController?.pushViewController(messagesVC, animated: true) @@ -284,7 +284,7 @@ class AIAssistantViewController: UIViewController { } private func continueChat(from message: BaseMessage) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user navigationController?.pushViewController(messagesVC, animated: true) } @@ -589,7 +589,7 @@ class MainTabBarController: UITabBarController { private func setupTabs() { // Chats Tab - let chatsVC = CometChatConversationsWithMessages() + let chatsVC = ChatListVC() // your own list + chat screen — see /ui-kit/ios/ios-tab-based-chat let chatsNav = UINavigationController(rootViewController: chatsVC) chatsNav.tabBarItem = UITabBarItem( title: "Chats", @@ -611,7 +611,7 @@ class MainTabBarController: UITabBarController { ) // Users Tab - let usersVC = CometChatUsersWithMessages() + let usersVC = ChatListVC() // your own list + chat screen — see /ui-kit/ios/ios-tab-based-chat let usersNav = UINavigationController(rootViewController: usersVC) usersNav.tabBarItem = UITabBarItem( title: "Users", @@ -623,7 +623,7 @@ class MainTabBarController: UITabBarController { } private func startNewAIChat() { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = currentUser if let nav = selectedViewController as? UINavigationController { @@ -683,7 +683,7 @@ class ProfileViewController: UIViewController { chatHistory.user = user chatHistory.onNewChatButtonClicked = { [weak self] selectedUser in - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = selectedUser self?.navigationController?.pushViewController(messagesVC, animated: true) } @@ -762,7 +762,7 @@ Show AI chat history when user taps a button in their profile: chatHistory.user = currentUser chatHistory.onNewChatButtonClicked = { [weak self] user in - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user self?.navigationController?.pushViewController(messagesVC, animated: true) } @@ -785,7 +785,7 @@ chatHistory.user = user chatHistory.onMessageClicked = { [weak self] message in // Open the messages view to continue the conversation - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = self?.user self?.navigationController?.pushViewController(messagesVC, animated: true) } @@ -846,7 +846,7 @@ class MainTabBarController: UITabBarController { aiHistory.user = currentUser aiHistory.onNewChatButtonClicked = { [weak self] user in - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user if let nav = self?.selectedViewController as? UINavigationController { nav.pushViewController(messagesVC, animated: true) diff --git a/ui-kit/ios/ai-features.mdx b/ui-kit/ios/ai-features.mdx index fbb20b85e..44e03fe80 100644 --- a/ui-kit/ios/ai-features.mdx +++ b/ui-kit/ios/ai-features.mdx @@ -9,7 +9,7 @@ description: "Complete guide to AI-powered chat features in iOS apps - conversat { "category": "ai", "features": [ - {"name": "aiAgentChat", "description": "Chat with AI-powered assistants", "component": "CometChatMessages", "enabledByDefault": false}, + {"name": "aiAgentChat", "description": "Chat with AI-powered assistants", "component": "CometChatMessageList", "enabledByDefault": false}, {"name": "chatHistory", "description": "Browse and resume previous AI sessions", "component": "CometChatAIAssistanceChatHistory", "enabledByDefault": false}, {"name": "streamingResponses", "description": "Real-time AI message streaming", "component": "CometChatMessageList", "enabledByDefault": false}, {"name": "suggestedMessages", "description": "AI-powered conversation starters and smart replies", "component": "CometChatMessageComposer", "enabledByDefault": false} @@ -18,7 +18,7 @@ description: "Complete guide to AI-powered chat features in iOS apps - conversat "location": "CometChat Dashboard → AI", "features": ["Conversation Starter", "Smart Replies", "Conversation Summary"] }, - "relatedComponents": ["CometChatMessages", "CometChatAIAssistanceChatHistory", "CometChatMessageList", "CometChatMessageComposer"] + "relatedComponents": ["CometChatMessageList", "CometChatAIAssistanceChatHistory", "CometChatMessageList", "CometChatMessageComposer"] } ``` @@ -80,7 +80,7 @@ When a user opens a new chat with no message history, AI suggests conversation o ### Implementation -Conversation starters appear automatically in `CometChatMessages`: +Conversation starters appear automatically in `CometChatMessageList`: @@ -94,7 +94,7 @@ class ChatViewController: UIViewController { func openChatWithUser(uid: String) { CometChat.getUser(UID: uid) { [weak self] user in DispatchQueue.main.async { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user // Conversation starters appear automatically @@ -142,7 +142,7 @@ import CometChatSDK class ChatViewController: UIViewController { func openChat(with user: CometChat.User) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user // Smart replies appear automatically in the composer @@ -186,7 +186,7 @@ import CometChatSDK class ChatViewController: UIViewController { func openChat(with user: CometChat.User) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user // Conversation summary option appears in composer action sheet @@ -400,7 +400,7 @@ class AIEnabledTabBarController: UITabBarController { private func setupTabs() { // Chats - AI features (starters, smart replies, summary) work automatically - let chatsVC = CometChatConversationsWithMessages() + let chatsVC = ChatListVC() // your own list + chat screen — see /ui-kit/ios/ios-tab-based-chat let chatsNav = UINavigationController(rootViewController: chatsVC) chatsNav.tabBarItem = UITabBarItem( title: "Chats", @@ -418,7 +418,7 @@ class AIEnabledTabBarController: UITabBarController { ) // Users - let usersVC = CometChatUsersWithMessages() + let usersVC = ChatListVC() // your own list + chat screen — see /ui-kit/ios/ios-tab-based-chat let usersNav = UINavigationController(rootViewController: usersVC) usersNav.tabBarItem = UITabBarItem( title: "Users", @@ -491,7 +491,7 @@ extension AIAssistantListViewController: UITableViewDelegate, UITableViewDataSou chatHistory.onNewChatButtonClicked = { [weak self] in // Start new AI chat - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user self?.navigationController?.pushViewController(messagesVC, animated: true) } diff --git a/ui-kit/ios/call-buttons.mdx b/ui-kit/ios/call-buttons.mdx index 39bd76112..83b796d1c 100644 --- a/ui-kit/ios/call-buttons.mdx +++ b/ui-kit/ios/call-buttons.mdx @@ -92,7 +92,7 @@ The `setOnVoiceCallClick` action is usually invoked when a voice call is initiat ```swift lines let cometChatCallButton = CometChatCallButtons(width: 24, height: 24) -.set(onVoiceCallClick: { user, group in +.onVoiceCallClick = { user, group in //Perform Your Action }) ``` @@ -109,7 +109,7 @@ The `setOnVideoCallClick` action is typically triggered when a video call is ini ```swift lines let cometChatCallButton = CometChatCallButtons(width: 24, height: 24) -.set(onVideoCallClick: { user, group in +.onVideoCallClick = { user, group in //Perform Your Action }) @@ -308,7 +308,7 @@ Below is a list of customizations along with corresponding code snippets | set(group:Group) | Sets the Group object for CometChatCallButtons. | `.set(group:Group)` | | set(outgoingCallConfiguration:) | Sets the configuration for outgoing calls. | `setOutgoingCallConfiguration(config)` | | set(customSoundForCalls:) | Sets a custom sound for incoming and outgoing calls. | `set(customSoundForCalls: URL)` | -| set(callSettingBuilder:) | Function to build call settings based on call type and participants. | `.set(callSettingBuilder { callType, participants in ... })` | +| set(callSettingsBuilder:) | Function to build call settings based on call type and participants. | `.set(callSettingBuilder { callType, participants in ... })` | ### Advanced @@ -516,7 +516,7 @@ Show confirmation before starting a call: ```swift lines let callButtons = CometChatCallButtons(width: 24, height: 24) callButtons.set(user: user) -callButtons.set(onVoiceCallClick: { [weak self] user, group in +callButtons.onVoiceCallClick = { [weak self] user, group in let alert = UIAlertController( title: "Start Voice Call", message: "Call \(user?.name ?? group?.name ?? "")?", @@ -546,7 +546,7 @@ callButtons.hideVoiceCallButton = true // Groups often use video calls callButtons.set(controller: self) // Custom call settings for group calls -callButtons.set(callSettingBuilder: { callType, participants in +callButtons.set(callSettingsBuilder: { callType, participants in return CallSettingsBuilder() .setDefaultLayout(true) .setShowRecordingButton(true) diff --git a/ui-kit/ios/call-features.mdx b/ui-kit/ios/call-features.mdx index 863aef8e3..890844cda 100644 --- a/ui-kit/ios/call-features.mdx +++ b/ui-kit/ios/call-features.mdx @@ -104,7 +104,7 @@ func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options conn -**That's it!** Call buttons now appear in `CometChatMessages` header automatically. +**That's it!** Call buttons appear in `CometChatMessageHeader` automatically. --- @@ -190,7 +190,7 @@ class MainTabBarController: UITabBarController { private func setupTabs() { // Chats Tab - with calling enabled - let chatsVC = CometChatConversationsWithMessages() + let chatsVC = ChatListVC() // your own list + chat screen — see /ui-kit/ios/ios-tab-based-chat let chatsNav = UINavigationController(rootViewController: chatsVC) chatsNav.tabBarItem = UITabBarItem( title: "Chats", @@ -211,7 +211,7 @@ class MainTabBarController: UITabBarController { ) // Users Tab - let usersVC = CometChatUsersWithMessages() + let usersVC = ChatListVC() // your own list + chat screen — see /ui-kit/ios/ios-tab-based-chat let usersNav = UINavigationController(rootViewController: usersVC) usersNav.tabBarItem = UITabBarItem( title: "Users", @@ -220,7 +220,7 @@ class MainTabBarController: UITabBarController { ) // Groups Tab - let groupsVC = CometChatGroupsWithMessages() + let groupsVC = ChatListVC() // your own list + chat screen — see /ui-kit/ios/ios-tab-based-chat let groupsNav = UINavigationController(rootViewController: groupsVC) groupsNav.tabBarItem = UITabBarItem( title: "Groups", @@ -253,7 +253,7 @@ class MainTabBarController: UITabBarController { // Fetch user and open chat CometChat.getUser(UID: uid) { [weak self] user in DispatchQueue.main.async { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.user = user if let nav = self?.selectedViewController as? UINavigationController { @@ -484,11 +484,11 @@ class ChatHeaderViewController: UIViewController { callButtons.user = user // Customize actions - callButtons.set(onVoiceCallClick: { user, group in + callButtons.onVoiceCallClick = { user, group in print("Voice call to: \(user?.name ?? group?.name ?? "")") }) - callButtons.set(onVideoCallClick: { user, group in + callButtons.onVideoCallClick = { user, group in print("Video call to: \(user?.name ?? group?.name ?? "")") }) @@ -581,8 +581,8 @@ let callButtons = CometChatCallButtons() callButtons.user = user // or callButtons.group = group // Callbacks -callButtons.set(onVoiceCallClick: { user, group in }) -callButtons.set(onVideoCallClick: { user, group in }) +callButtons.onVoiceCallClick = { user, group in }) +callButtons.onVideoCallClick = { user, group in }) callButtons.set(onError: { error in }) ``` @@ -595,7 +595,7 @@ let incomingCall = CometChatIncomingCall() incomingCall.set(call: call) incomingCall.set(onAcceptClick: { call in }) -incomingCall.set(onDeclineClick: { call in }) +incomingCall.set(onCancelClick: { call in }) ``` ### CometChatOutgoingCall diff --git a/ui-kit/ios/component-styling.mdx b/ui-kit/ios/component-styling.mdx index 2b372fb1a..847f8bf2b 100644 --- a/ui-kit/ios/component-styling.mdx +++ b/ui-kit/ios/component-styling.mdx @@ -369,7 +369,7 @@ CometChatSearch.style.listItemBackground = UIColor(hex: "#EDEAFA") import CometChatUIKitSwift // Date separator style -let dateStyle = CometChatDateStyle() +let dateStyle = DateStyle() dateStyle.textColor = UIColor(hex: "#8E8E93") dateStyle.textFont = UIFont.systemFont(ofSize: 12) diff --git a/ui-kit/ios/components-overview.mdx b/ui-kit/ios/components-overview.mdx index 06fa3c5b1..81689e84f 100644 --- a/ui-kit/ios/components-overview.mdx +++ b/ui-kit/ios/components-overview.mdx @@ -31,12 +31,12 @@ description: "Understand CometChat iOS UI Kit component types, base components, {"name": "CometChatMessageHeader", "purpose": "Chat header"}, {"name": "CometChatCallLogs", "purpose": "Call history"} ], - "compositeComponents": [ - {"name": "CometChatMessages", "contains": ["MessageHeader", "MessageList", "MessageComposer"]}, - {"name": "CometChatUsersWithMessages", "contains": ["Users", "Messages"]}, - {"name": "CometChatGroupsWithMessages", "contains": ["Groups", "Messages"]}, - {"name": "CometChatConversationsWithMessages", "contains": ["Conversations", "Messages"]} - ] + "composition": { + "note": "v5 ships NO composite/all-in-one component. The host composes the chat screen itself.", + "chatScreen": ["CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], + "listToChat": "CometChatConversations.set(onItemClick:) -> push your own messages view controller", + "recipe": "/ui-kit/ios/ios-conversation" + } } ``` @@ -123,34 +123,44 @@ messageList.set(user: user) --- -### Composite Components +### Composing a chat screen -Combine multiple components into complete features. +The UI Kit ships **no composite/all-in-one component** — you compose the chat screen yourself from +the three message components, and drive navigation from the list's `onItemClick`. This keeps your +navigation, layout, and presentation under your control. -| Component | Contains | +| You want | Compose | |-----------|----------| -| `CometChatMessages` | MessageHeader + MessageList + MessageComposer | -| `CometChatUsersWithMessages` | Users + Messages | -| `CometChatGroupsWithMessages` | Groups + Messages | -| `CometChatConversationsWithMessages` | Conversations + Messages | +| A chat screen | `CometChatMessageHeader` + `CometChatMessageList` + `CometChatMessageComposer` | +| Chat with user selection | `CometChatUsers` → push your chat screen | +| Chat with group selection | `CometChatGroups` → push your chat screen | +| Chat with recent conversations | `CometChatConversations` → push your chat screen | ```swift lines import CometChatUIKitSwift -// Complete chat experience in one component -let conversationsWithMessages = CometChatConversationsWithMessages() -navigationController?.pushViewController(conversationsWithMessages, animated: true) - -// Or just the messages view -let messages = CometChatMessages() -messages.user = user // or messages.group = group -navigationController?.pushViewController(messages, animated: true) +// Show recent conversations, then push YOUR chat screen on selection. +let conversations = CometChatConversations() +conversations.set(onItemClick: { [weak self] conversation, _ in + let messagesVC = MessagesVC() // your view controller — see the recipe below + messagesVC.user = conversation.conversationWith as? User + messagesVC.group = conversation.conversationWith as? Group + self?.navigationController?.pushViewController(messagesVC, animated: true) +}) +navigationController?.pushViewController(conversations, animated: true) ``` + + For the full `MessagesVC` — the three components laid out with safe-area constraints — follow + [Conversation List + Message View](/ui-kit/ios/ios-conversation). The same pattern with a users or + groups list is in [One-to-One / Group Chat](/ui-kit/ios/ios-one-to-one-chat), and inside a tab bar in + [Tab-Based Chat](/ui-kit/ios/ios-tab-based-chat). + + --- ## Actions @@ -291,61 +301,65 @@ class ChatManager { --- -## Configurations +## Configuring components -Customize nested components within composite components: +Because you compose the chat screen yourself, you configure **each component directly on its own +instance** — there is no configuration object to pass down through a parent. ```swift lines import CometChatUIKitSwift -// CometChatMessages contains: MessageHeader, MessageList, MessageComposer -// You can configure each one: - -let messages = CometChatMessages() -messages.user = user - -// Configure MessageHeader -let headerConfig = MessageHeaderConfiguration() -headerConfig.hideBackButton = false -headerConfig.set(subtitleView: { user, group in +// Header — set the target, then customize it directly +let messageHeader = CometChatMessageHeader() +messageHeader.set(user: user) +messageHeader.set(controller: self) +messageHeader.hideBackButton = false +messageHeader.set(subtitleView: { user, group in let label = UILabel() + label.font = UIFont.systemFont(ofSize: 13) + label.textColor = .secondaryLabel label.text = user?.status == .online ? "Online" : "Offline" - label.textColor = user?.status == .online ? .systemGreen : .gray return label }) -messages.set(messageHeaderConfiguration: headerConfig) - -// Configure MessageList -let listConfig = MessageListConfiguration() -listConfig.set(emptyStateText: "No messages yet") -listConfig.set(errorStateText: "Failed to load messages") -messages.set(messageListConfiguration: listConfig) - -// Configure MessageComposer -let composerConfig = MessageComposerConfiguration() -composerConfig.set(placeholderText: "Type a message...") -composerConfig.hideLiveReaction = true -messages.set(messageComposerConfiguration: composerConfig) + +// Message list — same target, its own empty/error views +let messageList = CometChatMessageList() +messageList.set(user: user) +messageList.set(controller: self) +messageList.set(emptyView: myEmptyView) +messageList.set(errorView: myErrorView) + +// Composer — same target +let composer = CometChatMessageComposer() +composer.set(user: user) +composer.set(controller: self) +composer.placeholderText = "Type a message..." ``` + + Pass the **same** `user` (or `group`) to all three components — that shared target is what keeps the + header, list, and composer on the same conversation. Component-specific configuration objects do exist + for nested sub-features (for example `ReactionsConfiguration`, `StickerKeyboardConfiguration`, + `IncomingCallConfiguration`); see each component's own page for its full API. + + --- ## Component Hierarchy ``` -CometChatConversationsWithMessages -├── CometChatConversations -│ ├── CometChatListItem -│ │ ├── CometChatAvatar -│ │ ├── CometChatBadge -│ │ ├── CometChatStatusIndicator -│ │ └── CometChatDate -│ └── CometChatListBase -└── CometChatMessages +YourNavigationController // yours +├── CometChatConversations // list screen +│ └── CometChatListItem +│ ├── CometChatAvatar +│ ├── CometChatBadge +│ ├── CometChatStatusIndicator +│ └── CometChatDate +└── MessagesVC // YOUR view controller, pushed on selection ├── CometChatMessageHeader │ ├── CometChatAvatar │ └── CometChatStatusIndicator @@ -358,6 +372,9 @@ CometChatConversationsWithMessages └── CometChatStickerKeyboard ``` +The two levels you own are the navigation controller and `MessagesVC`; everything below them is a +UI Kit component. + --- ## Quick Reference @@ -368,25 +385,30 @@ CometChatConversationsWithMessages |------|-----| | Display user avatar | `CometChatAvatar` (Base) | | Show list of users | `CometChatUsers` (Component) | -| Complete chat with user selection | `CometChatUsersWithMessages` (Composite) | +| Complete chat with user selection | `CometChatUsers` → push your chat screen ([recipe](/ui-kit/ios/ios-one-to-one-chat)) | +| Complete chat with recent conversations | `CometChatConversations` → push your chat screen ([recipe](/ui-kit/ios/ios-conversation)) | | Custom chat UI | Individual Components | -| Quick integration | Composite Components | ### Common Patterns ```swift lines -// Pattern 1: Quick integration with composite -let chat = CometChatConversationsWithMessages() -navigationController?.pushViewController(chat, animated: true) +// Pattern 1: Recent conversations -> your chat screen +let conversations = CometChatConversations() +conversations.set(onItemClick: { [weak self] conversation, _ in + let messagesVC = MessagesVC() + messagesVC.user = conversation.conversationWith as? User + messagesVC.group = conversation.conversationWith as? Group + self?.navigationController?.pushViewController(messagesVC, animated: true) +}) -// Pattern 2: Custom flow with components +// Pattern 2: User list -> your chat screen let users = CometChatUsers() -users.set(onItemClick: { user, _ in - let messages = CometChatMessages() - messages.user = user - self.navigationController?.pushViewController(messages, animated: true) +users.set(onItemClick: { [weak self] user, _ in + let messagesVC = MessagesVC() + messagesVC.user = user + self?.navigationController?.pushViewController(messagesVC, animated: true) }) // Pattern 3: Fully custom with base components diff --git a/ui-kit/ios/conversations.mdx b/ui-kit/ios/conversations.mdx index 7e15e8704..fc108b494 100644 --- a/ui-kit/ios/conversations.mdx +++ b/ui-kit/ios/conversations.mdx @@ -59,10 +59,10 @@ The `CometChatConversations` component displays a list of all conversations (one "leadingView": "(Conversation) -> UIView", "titleView": "(Conversation) -> UIView", "subtitleView": "(Conversation) -> UIView", - "tailView": "(Conversation) -> UIView", - "emptyStateView": "() -> UIView", - "errorStateView": "() -> UIView", - "loadingStateView": "() -> UIView" + "trailView": "(Conversation) -> UIView", + "emptyStateView": "UIView (assign a view; not a closure — inherited from CometChatListBase)", + "errorStateView": "UIView (assign a view; not a closure — inherited from CometChatListBase)", + "loadingView": "UIView (assign a view; not a closure)" }, "formatting": { "datePattern": "(Conversation) -> String", @@ -89,8 +89,8 @@ The `CometChatConversations` component displays a list of all conversations (one ], "compositionExample": { "description": "Conversations list navigating to Messages", - "components": ["CometChatConversations", "CometChatMessages"], - "flow": "User taps conversation → onItemClick fires → Navigate to CometChatMessages with user/group" + "components": ["CometChatConversations", "CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], + "flow": "User taps conversation → onItemClick fires → push YOUR chat screen (header + list + composer) with the user/group. v5 ships no composite component." }, "types": { "Conversation": { @@ -101,9 +101,10 @@ The `CometChatConversations` component displays a list of all conversations (one "unreadMessageCount": "Int" }, "ConversationType": { - "user": "One-on-one conversation", - "group": "Group conversation", - "both": "All conversation types" + "user": "One-on-one conversations only", + "group": "Group conversations only", + "none": "No type filter", + "_note": "Set with setConversationType(conversationType:), not set(conversationType:). Omit it entirely to get both 1:1s and groups." } } } @@ -120,7 +121,7 @@ The `CometChatConversations` component displays a list of all conversations (one ## Where It Fits -`CometChatConversations` serves as the main entry point for chat functionality. It displays all conversations and navigates to `CometChatMessages` when a conversation is selected. +`CometChatConversations` serves as the main entry point for chat functionality. It displays all conversations; on selection you push **your own** chat screen, composed from `CometChatMessageHeader` + `CometChatMessageList` + `CometChatMessageComposer` (see [Conversation List + Message View](/ui-kit/ios/ios-conversation)). The UI Kit ships no composite/all-in-one messages component. ```swift lines import UIKit @@ -148,13 +149,10 @@ class ChatListViewController: UIViewController { } private func openMessages(for conversation: Conversation) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation - if let user = conversation.conversationWith as? User { - messagesVC.set(user: user) - } else if let group = conversation.conversationWith as? Group { - messagesVC.set(group: group) - } + messagesVC.user = conversation.conversationWith as? User + messagesVC.group = conversation.conversationWith as? Group navigationController?.pushViewController(messagesVC, animated: true) } @@ -191,8 +189,8 @@ import CometChatUIKitSwift import CometChatSDK // Create a custom request builder +// Omit setConversationType to get BOTH 1:1s and groups — that is the default. let requestBuilder = ConversationRequest.ConversationRequestBuilder(limit: 30) - .set(conversationType: .both) let conversations = CometChatConversations(conversationRequestBuilder: requestBuilder) ``` @@ -201,8 +199,8 @@ let conversations = CometChatConversations(conversationRequestBuilder: requestBu | Recipe | Code | |--------|------| -| Show only one-on-one chats | `.set(conversationType: .user)` | -| Show only group chats | `.set(conversationType: .group)` | +| Show only one-on-one chats | `.setConversationType(conversationType: .user)` | +| Show only group chats | `.setConversationType(conversationType: .group)` | | Filter by tags | `.withTags(true).set(tags: ["support", "sales"])` | | Limit results | `ConversationRequestBuilder(limit: 20)` | | Include user/group tags | `.withUserAndGroupTags(true)` | @@ -226,13 +224,10 @@ let conversations = CometChatConversations() conversations.set(onItemClick: { [weak self] conversation, indexPath in guard let self = self else { return } - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation - if let user = conversation.conversationWith as? User { - messagesVC.set(user: user) - } else if let group = conversation.conversationWith as? Group { - messagesVC.set(group: group) - } + messagesVC.user = conversation.conversationWith as? User + messagesVC.group = conversation.conversationWith as? Group self.navigationController?.pushViewController(messagesVC, animated: true) }) @@ -959,11 +954,11 @@ import CometChatUIKitSwift let conversations = CometChatConversations() -// Create custom text formatters -let mentionFormatter = CometChatMentionTextFormatter() -let urlFormatter = CometChatURLTextFormatter() +// Mentions are formatted by CometChatMentionsFormatter, a CometChatTextFormatter subclass. +// Subclass CometChatTextFormatter yourself for any other formatting you need. +let mentionFormatter = CometChatMentionsFormatter() -conversations.set(textFormatters: [mentionFormatter, urlFormatter]) +conversations.set(textFormatters: [mentionFormatter]) ``` --- @@ -992,7 +987,7 @@ avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 8) avatarStyle.borderWidth = 1 avatarStyle.borderColor = UIColor.systemGray4 -conversations.set(avatarStyle: avatarStyle) +conversations.avatarStyle = avatarStyle ``` ### badgeStyle @@ -1015,7 +1010,7 @@ badgeStyle.textColor = UIColor.white badgeStyle.textFont = UIFont.systemFont(ofSize: 12, weight: .bold) badgeStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 10) -conversations.set(badgeStyle: badgeStyle) +conversations.badgeStyle = badgeStyle ``` ### conversationRequestBuilder @@ -1045,7 +1040,7 @@ let dateStyle = DateStyle() dateStyle.textColor = UIColor.secondaryLabel dateStyle.textFont = UIFont.systemFont(ofSize: 12) -conversations.set(dateStyle: dateStyle) +conversations.dateStyle = dateStyle ``` ### dateTimeFormatter @@ -1181,10 +1176,10 @@ import CometChatUIKitSwift let conversations = CometChatConversations() -conversations.set(onSearchClick: { [weak self] in +conversations.onSearchClick = { [weak self] in // Handle search button click self?.presentSearchViewController() -}) +} ``` ### privateGroupIcon @@ -1238,7 +1233,7 @@ receiptStyle.sentIconTint = UIColor.systemGray receiptStyle.deliveredIconTint = UIColor.systemGray receiptStyle.readIconTint = UIColor.systemBlue -conversations.set(receiptStyle: receiptStyle) +conversations.receiptStyle = receiptStyle ``` ### selectionMode @@ -1269,7 +1264,7 @@ statusIndicatorStyle.backgroundColor = UIColor.systemGreen statusIndicatorStyle.borderWidth = 2 statusIndicatorStyle.borderColor = UIColor.white -conversations.set(statusIndicatorStyle: statusIndicatorStyle) +conversations.statusIndicatorStyle = statusIndicatorStyle ``` ### textFormatters @@ -1299,7 +1294,7 @@ let typingIndicatorStyle = TypingIndicatorStyle() typingIndicatorStyle.textColor = UIColor.systemGray typingIndicatorStyle.textFont = UIFont.italicSystemFont(ofSize: 14) -conversations.set(typingIndicatorStyle: typingIndicatorStyle) +conversations.typingIndicatorStyle = typingIndicatorStyle ``` --- @@ -1448,13 +1443,10 @@ class MentionConfiguredViewController: UIViewController { } private func openMessages(for conversation: Conversation) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation - if let user = conversation.conversationWith as? User { - messagesVC.set(user: user) - } else if let group = conversation.conversationWith as? Group { - messagesVC.set(group: group) - } + messagesVC.user = conversation.conversationWith as? User + messagesVC.group = conversation.conversationWith as? Group navigationController?.pushViewController(messagesVC, animated: true) } @@ -1519,7 +1511,7 @@ class ConversationsContainerViewController: UINavigationController { // Navigate to messages on tap conversations.set(onItemClick: { [weak self] conversation, _ in - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation if let user = conversation.conversationWith as? User { messagesVC.set(user: user) @@ -1537,24 +1529,30 @@ class ConversationsContainerViewController: UINavigationController { ### Custom empty state with CTA +The empty state is a **`UIView` you assign**, not a closure — `emptyStateView` is inherited from +`CometChatListBase`. Build the view first, then set it (`set(emptyView:)` is the equivalent builder form). + ```swift lines let conversations = CometChatConversations() -conversations.set(emptyStateView: { - let emptyView = UIView() - - let label = UILabel() - label.text = "No conversations yet" - label.textAlignment = .center - label.textColor = .secondaryLabel - - let button = UIButton(type: .system) - button.setTitle("Start a conversation", for: .normal) - button.addTarget(self, action: #selector(startNewConversation), for: .touchUpInside) - - // Add subviews and constraints... - return emptyView -}) +let emptyView = UIView() + +let label = UILabel() +label.text = "No conversations yet" +label.textAlignment = .center +label.textColor = .secondaryLabel + +let button = UIButton(type: .system) +button.setTitle("Start a conversation", for: .normal) +button.addTarget(self, action: #selector(startNewConversation), for: .touchUpInside) + +// Add subviews and constraints to emptyView... + +conversations.emptyStateView = emptyView // or: conversations.set(emptyView: emptyView) + +// Want to keep the built-in empty state and just retitle it? +conversations.emptyStateTitleText = "No conversations yet" +conversations.emptyStateSubTitleText = "Start a chat to see it here" ``` ### Hide all chrome — minimal list @@ -1572,13 +1570,13 @@ conversations.hideDeleteConversationOption = true ```swift lines // Only user conversations let userOnlyBuilder = ConversationRequest.ConversationRequestBuilder(limit: 30) - .set(conversationType: .user) + .setConversationType(conversationType: .user) let conversations = CometChatConversations(conversationRequestBuilder: userOnlyBuilder) // Only group conversations let groupOnlyBuilder = ConversationRequest.ConversationRequestBuilder(limit: 30) - .set(conversationType: .group) + .setConversationType(conversationType: .group) let groupConversations = CometChatConversations(conversationRequestBuilder: groupOnlyBuilder) ``` diff --git a/ui-kit/ios/core-features.mdx b/ui-kit/ios/core-features.mdx index ae494ff0d..32f7b1fba 100644 --- a/ui-kit/ios/core-features.mdx +++ b/ui-kit/ios/core-features.mdx @@ -8,7 +8,7 @@ description: "Review CometChat iOS UI Kit core features for messaging, media sha { "category": "messaging", "features": [ - {"name": "instantMessaging", "description": "Send and receive text messages in real-time", "component": "CometChatMessages", "enabledByDefault": true}, + {"name": "instantMessaging", "description": "Send and receive text messages in real-time", "component": "CometChatMessageList", "enabledByDefault": true}, {"name": "mediaSharing", "description": "Share images, videos, audio files, and documents", "component": "CometChatMessageComposer", "enabledByDefault": true}, {"name": "readReceipts", "description": "Show when messages are delivered and read", "component": "CometChatMessageList", "enabledByDefault": true}, {"name": "typingIndicators", "description": "Show when users are typing in real-time", "component": "CometChatMessageHeader", "enabledByDefault": true}, @@ -19,7 +19,7 @@ description: "Review CometChat iOS UI Kit core features for messaging, media sha {"name": "groupChat", "description": "Create and manage group conversations", "component": "CometChatGroups", "enabledByDefault": true}, {"name": "search", "description": "Search across conversations and messages", "component": "CometChatSearch", "enabledByDefault": true} ], - "relatedComponents": ["CometChatMessages", "CometChatConversations", "CometChatMessageList", "CometChatMessageComposer"] + "relatedComponents": ["CometChatMessageList", "CometChatConversations", "CometChatMessageList", "CometChatMessageComposer"] } ``` @@ -45,7 +45,7 @@ class ChatViewController: UIViewController { super.viewDidLoad() // For one-on-one chat - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation // Set the user to chat with CometChat.getUser(UID: "cometchat-uid-1") { user in @@ -83,7 +83,7 @@ class MediaChatViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation // The message composer includes multi-attachment media sharing: // - Multi-select photos and videos from the library @@ -136,7 +136,7 @@ class ReceiptsViewController: UIViewController { super.viewDidLoad() // Read receipts are enabled by default - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation // To hide receipts: // messagesVC.hideReceipts = true @@ -188,7 +188,7 @@ class UnreadMessagesViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation // Enable starting from first unread message messagesVC.scrollToUnreadMessages = true @@ -238,7 +238,7 @@ class TypingIndicatorViewController: UIViewController { // - CometChatConversations (shows "typing..." in conversation list) // - CometChatMessageHeader (shows "typing..." below user name) - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation CometChat.getUser(UID: "cometchat-uid-1") { user in DispatchQueue.main.async { @@ -343,7 +343,7 @@ class ReactionsViewController: UIViewController { // Reactions are enabled by default // Users can long-press a message to add reactions - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation CometChat.getUser(UID: "cometchat-uid-1") { user in DispatchQueue.main.async { @@ -402,7 +402,7 @@ class MentionsViewController: UIViewController { // Mentions are enabled by default // Type @ in the composer to see mention suggestions - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation CometChat.getGroup(GUID: "group-123") { group in DispatchQueue.main.async { @@ -474,7 +474,7 @@ class ThreadedMessagesViewController: UIViewController { // Threaded messages are enabled by default // Users can tap "Reply in thread" on any message - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation CometChat.getUser(UID: "cometchat-uid-1") { user in DispatchQueue.main.async { @@ -504,14 +504,14 @@ class ThreadedMessagesViewController: UIViewController { // Create message list for thread replies let messageList = CometChatMessageList() messageList.set(user: user) - messageList.set(parentMessage: parentMessage) + messageList.set(parentMessageId: parentMessage.id) messageList.set(controller: threadVC) messageList.translatesAutoresizingMaskIntoConstraints = false // Create composer for thread replies let composer = CometChatMessageComposer() composer.set(user: user) - composer.set(parentMessage: parentMessage) + composer.set(parentMessageId: parentMessage.id) composer.set(controller: threadVC) composer.translatesAutoresizingMaskIntoConstraints = false @@ -593,7 +593,7 @@ class GroupChatViewController: UIViewController { // Open chat for a group func openGroupChat(group: Group) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(group: group) navigationController?.pushViewController(messagesVC, animated: true) } @@ -658,7 +658,7 @@ class QuotedReplyViewController: UIViewController { // Quoted reply is enabled by default // Users can swipe right on a message or tap "Reply" in message actions - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation CometChat.getUser(UID: "cometchat-uid-1") { user in DispatchQueue.main.async { @@ -740,7 +740,7 @@ class ModerationViewController: UIViewController { // Blocked messages are displayed appropriately // based on your moderation rules - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation CometChat.getUser(UID: "cometchat-uid-1") { user in DispatchQueue.main.async { @@ -779,7 +779,7 @@ class ReportMessageViewController: UIViewController { // Report message is available in message actions // Users can long-press a message and select "Report" - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation CometChat.getUser(UID: "cometchat-uid-1") { user in DispatchQueue.main.async { @@ -862,7 +862,7 @@ class MainTabBarController: UITabBarController { let conversationsNav = UINavigationController() let conversations = CometChatConversations() conversations.set(onItemClick: { [weak conversationsNav] conversation, _ in - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation if let user = conversation.conversationWith as? User { messagesVC.set(user: user) } else if let group = conversation.conversationWith as? Group { @@ -881,7 +881,7 @@ class MainTabBarController: UITabBarController { let usersNav = UINavigationController() let users = CometChatUsers() users.set(onItemClick: { [weak usersNav] user, _ in - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(user: user) usersNav?.pushViewController(messagesVC, animated: true) }) @@ -896,7 +896,7 @@ class MainTabBarController: UITabBarController { let groupsNav = UINavigationController() let groups = CometChatGroups() groups.set(onItemClick: { [weak groupsNav] group, _ in - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(group: group) groupsNav?.pushViewController(messagesVC, animated: true) }) diff --git a/ui-kit/ios/group-members.mdx b/ui-kit/ios/group-members.mdx index cc5e702f5..8fdb94de6 100644 --- a/ui-kit/ios/group-members.mdx +++ b/ui-kit/ios/group-members.mdx @@ -38,8 +38,7 @@ The `CometChatGroupMembers` component displays all members of a group with their "onItemClick": "(GroupMember, IndexPath) -> Void", "onItemLongClick": "(GroupMember, IndexPath) -> Void", "onBack": "() -> Void", - "onSelection": "([GroupMember]) -> Void", - "onSelectedItemProceed": "([GroupMember]) -> Void", + "onSelectedItemProceed": "([GroupMember]) -> Void (assignable property)", "onError": "(CometChatException) -> Void", "onEmpty": "() -> Void", "onLoad": "([GroupMember]) -> Void" @@ -68,7 +67,7 @@ The `CometChatGroupMembers` component displays all members of a group with their "titleView": "(GroupMember?) -> UIView", "subtitleView": "(GroupMember?) -> UIView", "trailView": "(GroupMember?) -> UIView", - "emptyStateView": "UIView", + "emptyStateView": "UIView (assign a view; inherited from CometChatListBase)", "errorStateView": "UIView", "loadingStateView": "UIView" } @@ -113,7 +112,7 @@ The `CometChatGroupMembers` component displays all members of a group with their ], "compositionExample": { "description": "GroupMembers is typically accessed from group details or settings", - "components": ["CometChatGroups", "CometChatGroupMembers", "CometChatMessages"], + "components": ["CometChatGroups", "CometChatGroupMembers", "CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], "flow": "User opens group → views members → taps member → starts direct chat" }, "types": { @@ -174,7 +173,7 @@ class GroupDetailViewController: UIViewController { } private func startDirectChat(with member: GroupMember) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(user: member) navigationController?.pushViewController(messagesVC, animated: true) } @@ -251,7 +250,7 @@ let groupMembers = CometChatGroupMembers(group: group) groupMembers.set(onItemClick: { [weak self] member, indexPath in guard let self = self else { return } - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(user: member) self.navigationController?.pushViewController(messagesVC, animated: true) }) @@ -310,7 +309,7 @@ import CometChatSDK let groupMembers = CometChatGroupMembers(group: group) groupMembers.selectionMode = .multiple -groupMembers.set(onSelection: { [weak self] selectedMembers in +groupMembers.onSelectedItemProceed = { [weak self] selectedMembers in print("Selected \(selectedMembers.count) members") }) ``` @@ -365,7 +364,7 @@ groupMembers.set(onLoad: { members in | `set(onItemClick:)` | Triggered when a member is tapped | Start direct chat | | `set(onItemLongClick:)` | Triggered on long press | Show options menu | | `set(onBack:)` | Triggered when back button is pressed | Custom navigation | -| `set(onSelection:)` | Triggered in selection mode | Multi-select members | +| `onSelectedItemProceed` | Fires when the user confirms a multi-selection | Multi-select members | | `set(onError:)` | Triggered when an error occurs | Show error alert | | `set(onEmpty:)` | Triggered when list is empty | Show empty state | | `set(onLoad:)` | Triggered when members load | Analytics tracking | @@ -917,7 +916,7 @@ groupMembers.set(options: { group, member in icon: UIImage(systemName: "message"), backgroundColor: .systemBlue, onClick: { member, group, section, option, controller in - let messages = CometChatMessages() + let messages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messages.set(user: member) controller.navigationController?.pushViewController(messages, animated: true) } @@ -1136,7 +1135,7 @@ import CometChatSDK let groupMembers = CometChatGroupMembers(group: group) groupMembers.selectionMode = .multiple -groupMembers.set(onSelectedItemProceed: { [weak self] selectedMembers in +groupMembers.onSelectedItemProceed = { [weak self] selectedMembers in print("Proceeding with \(selectedMembers.count) selected members") for member in selectedMembers { @@ -1178,7 +1177,7 @@ let messageOption = CometChatGroupMemberOption( icon: UIImage(systemName: "message"), backgroundColor: .systemBlue, onClick: { member, group, section, option, controller in - let messages = CometChatMessages() + let messages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messages.set(user: member) controller.navigationController?.pushViewController(messages, animated: true) } @@ -1223,16 +1222,19 @@ class GroupMembersViewController: UIViewController { action: #selector(addMemberTapped) ) - groupMembers.set(menus: [addButton]) + groupMembers.menus = [addButton] let navController = UINavigationController(rootViewController: groupMembers) present(navController, animated: true) } @objc func addMemberTapped() { - // Show add member screen - let addMembers = CometChatAddMembers(group: group) - navigationController?.pushViewController(addMembers, animated: true) + // The UI Kit ships no add-members component — build your own picker + // (CometChatUsers with selectionMode) and add via the SDK: + // CometChat.addMembersToGroup(guid:groupMembers:bannedUIDs:onSuccess:onError:) + // See /sdk/ios/group-add-members + let picker = AddMembersVC(group: group) // your own screen + navigationController?.pushViewController(picker, animated: true) } } ``` @@ -1268,12 +1270,12 @@ groupMembers.hideScopeChangeOption = true ```swift lines let groupMembers = CometChatGroupMembers(group: group) -groupMembers.set(emptyStateView: { - let label = UILabel() - label.text = "No members in this group" - label.textAlignment = .center - return label -}) +// emptyStateView is a UIView you assign (inherited from CometChatListBase). +let label = UILabel() +label.text = "No members in this group" +label.textAlignment = .center + +groupMembers.emptyStateView = emptyView // or: groupMembers.set(emptyView: emptyView) ``` ### Multi-select members @@ -1282,7 +1284,7 @@ groupMembers.set(emptyStateView: { let groupMembers = CometChatGroupMembers(group: group) groupMembers.selectionMode = .multiple -groupMembers.set(onSelection: { selectedMembers in +groupMembers.onSelectedItemProceed = { selectedMembers in print("Selected \(selectedMembers.count) members") // Kick selected members, change scope, etc. }) diff --git a/ui-kit/ios/groups.mdx b/ui-kit/ios/groups.mdx index 8be5fe225..7996b8a55 100644 --- a/ui-kit/ios/groups.mdx +++ b/ui-kit/ios/groups.mdx @@ -106,8 +106,8 @@ The `CometChatGroups` component displays a searchable list of all available grou ], "compositionExample": { "description": "Groups list for browsing and joining group conversations", - "components": ["CometChatGroups", "CometChatMessages"], - "flow": "User taps on a group → onItemClick fires → Navigate to CometChatMessages with selected group" + "components": ["CometChatGroups", "CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], + "flow": "User taps on a group → onItemClick fires → push your own chat screen with the selected group" }, "types": { "Group": { @@ -165,7 +165,7 @@ class GroupsViewController: UIViewController { } private func openGroupChat(_ group: Group) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(group: group) navigationController?.pushViewController(messagesVC, animated: true) } @@ -238,7 +238,7 @@ let groups = CometChatGroups() groups.set(onItemClick: { [weak self] group, indexPath in guard let self = self else { return } - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(group: group) self.navigationController?.pushViewController(messagesVC, animated: true) }) @@ -297,9 +297,9 @@ import CometChatSDK let groups = CometChatGroups() groups.selectionMode = .multiple -groups.set(onSelection: { [weak self] selectedGroups in +groups.onSelectedItemProceed = { [weak self] selectedGroups in print("Selected \(selectedGroups.count) groups") -}) +} ``` #### onSelectedItemProceed @@ -377,8 +377,7 @@ groups.set(onLoad: { groups in | `set(onItemClick:)` | Triggered when a group is tapped | Open group chat | | `set(onItemLongClick:)` | Triggered on long press | Show options menu | | `set(onBack:)` | Triggered when back button is pressed | Custom navigation | -| `set(onSelection:)` | Triggered in selection mode | Multi-select groups | -| `onSelectedItemProceed` | Triggered when selection is confirmed | Process selected groups | +| `onSelectedItemProceed` | Fires when the user confirms a multi-selection | Multi-select groups | | `set(onError:)` | Triggered when an error occurs | Show error alert | | `set(onEmpty:)` | Triggered when list is empty | Show empty state | | `set(onLoad:)` | Triggered when groups load | Analytics tracking | @@ -751,7 +750,7 @@ import CometChatSDK let groups = CometChatGroups() -groups.set(subtitleView: { group in +groups.set(subtitle: { group in let view = CustomSubtitleView(membersCount: group.membersCount) return view }) @@ -793,7 +792,7 @@ import CometChatSDK let groups = CometChatGroups() -groups.set(trailView: { group in +groups.set(trailingView: { group in let view = CustomTrailView() return view }) @@ -1115,7 +1114,7 @@ avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 8) avatarStyle.borderWidth = 1 avatarStyle.borderColor = UIColor.systemGray4 -groups.set(avatarStyle: avatarStyle) +groups.avatarStyle = avatarStyle ``` ### groupsRequestBuilder @@ -1276,7 +1275,7 @@ statusIndicatorStyle.backgroundColor = UIColor.systemGreen statusIndicatorStyle.borderWidth = 2 statusIndicatorStyle.borderColor = UIColor.white -groups.set(statusIndicatorStyle: statusIndicatorStyle) +groups.statusIndicatorStyle = statusIndicatorStyle ``` --- @@ -1319,19 +1318,19 @@ groups.set(groupsRequestBuilder: joinedBuilder) ```swift lines let groups = CometChatGroups() -groups.set(emptyStateView: { - let emptyView = UIView() - - let label = UILabel() - label.text = "No groups found" - label.textAlignment = .center - - let button = UIButton(type: .system) - button.setTitle("Create a group", for: .normal) - - // Add subviews and constraints... - return emptyView -}) +// emptyStateView is a UIView you assign (inherited from CometChatListBase). +let emptyView = UIView() + +let label = UILabel() +label.text = "No groups found" +label.textAlignment = .center + +let button = UIButton(type: .system) +button.setTitle("Create a group", for: .normal) + +// Add subviews and constraints... + +groups.emptyStateView = emptyView // or: groups.set(emptyView: emptyView) ``` ### Hide all chrome — minimal list @@ -1349,7 +1348,7 @@ groups.hideSectionHeader = true let groups = CometChatGroups() groups.selectionMode = .multiple -groups.set(onSelection: { selectedGroups in +groups.onSelectedItemProceed = { selectedGroups in print("Selected \(selectedGroups.count) groups") }) ``` diff --git a/ui-kit/ios/guide-ai-agent.mdx b/ui-kit/ios/guide-ai-agent.mdx index abfb9c12d..e4945490f 100644 --- a/ui-kit/ios/guide-ai-agent.mdx +++ b/ui-kit/ios/guide-ai-agent.mdx @@ -187,7 +187,7 @@ class ProductionAIAgentViewController: UIViewController { // If resuming from history, set parent message if let parentMessage = parentMessage { - messageList.set(parentMessage: parentMessage) + messageList.set(parentMessageId: parentMessage.id) } view.addSubview(messageList) @@ -205,7 +205,7 @@ class ProductionAIAgentViewController: UIViewController { // If resuming from history, set parent message if let parentMessage = parentMessage { - messageComposer.set(parentMessage: parentMessage) + messageComposer.set(parentMessageId: parentMessage.id) } view.addSubview(messageComposer) @@ -308,7 +308,7 @@ class ChatListViewController: UIViewController { self?.navigationController?.pushViewController(aiChatVC, animated: true) } else { // Regular user chat - let messages = CometChatMessages() + let messages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messages.set(user: user) self?.navigationController?.pushViewController(messages, animated: true) } @@ -326,7 +326,7 @@ class ChatListViewController: UIViewController { let aiChatVC = ProductionAIAgentViewController(user: user) navigationController?.pushViewController(aiChatVC, animated: true) } else { - let messages = CometChatMessages() + let messages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messages.set(user: user) navigationController?.pushViewController(messages, animated: true) } @@ -405,7 +405,7 @@ label.textAlignment = .center label.textColor = .secondaryLabel emptyView.addSubview(label) -messageList.set(emptyStateView: emptyView) +messageList.emptyStateView = emptyView ``` ### Streaming Speed diff --git a/ui-kit/ios/guide-block-unblock-user.mdx b/ui-kit/ios/guide-block-unblock-user.mdx index 191856c88..f59a01c68 100644 --- a/ui-kit/ios/guide-block-unblock-user.mdx +++ b/ui-kit/ios/guide-block-unblock-user.mdx @@ -54,7 +54,7 @@ class UserDetailsViewController: UIViewController { // Avatar let avatar = CometChatAvatar() - avatar.set(user: user) + avatar.setAvatar(avatarUrl: user.avatar, with: user.name) avatar.translatesAutoresizingMaskIntoConstraints = false view.addSubview(avatar) @@ -113,7 +113,7 @@ class UserDetailsViewController: UIViewController { @objc private func openChat() { guard let user = user else { return } - let messages = CometChatMessages() + let messages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messages.set(user: user) navigationController?.pushViewController(messages, animated: true) } @@ -314,7 +314,7 @@ class ProductionUserDetailsViewController: UIViewController { private func configureWithUser() { guard let user = user else { return } - avatar.set(user: user) + avatar.setAvatar(avatarUrl: user.avatar, with: user.name) nameLabel.text = user.name updateStatusLabel(user: user) } @@ -362,7 +362,7 @@ class ProductionUserDetailsViewController: UIViewController { return } - let messages = CometChatMessages() + let messages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messages.set(user: user) navigationController?.pushViewController(messages, animated: true) } @@ -657,7 +657,7 @@ avatar.set(style: avatarStyle) | Component | Purpose | |-----------|---------| | `CometChatAvatar` | Display user profile picture | -| `CometChatMessages` | Open chat interface | +| your own chat screen | Open chat interface | | `CometChat.blockUsers()` | Block users | | `CometChat.unblockUsers()` | Unblock users | | `CometChat.deleteConversation()` | Delete chat history | diff --git a/ui-kit/ios/guide-group-chat.mdx b/ui-kit/ios/guide-group-chat.mdx index 71f857fcd..68282b75c 100644 --- a/ui-kit/ios/guide-group-chat.mdx +++ b/ui-kit/ios/guide-group-chat.mdx @@ -31,7 +31,7 @@ Before implementing group details, ensure you have: |-----------|-------------| | `CometChatGroup` | Renders group avatar, name, and metadata | | `GroupActionView` | Custom view for action buttons (view/add/banned members) | -| `CometChatMessagesViewController` | Opens group chat interface when "Chat" is tapped | +| your own chat screen | Opens group chat interface when "Chat" is tapped | | `CometChat.joinGroup()` | Joins public or password-protected groups | | `CometChat.leaveGroup()` | Leaves the current group | | `CometChat.deleteGroup()` | Deletes and exits the group (owners only) | diff --git a/ui-kit/ios/guide-message-privately.mdx b/ui-kit/ios/guide-message-privately.mdx index c9aec2254..664e3c21f 100644 --- a/ui-kit/ios/guide-message-privately.mdx +++ b/ui-kit/ios/guide-message-privately.mdx @@ -26,10 +26,10 @@ Before implementing this feature, ensure you have: | `CometChatMessageOption` | Defines the **Message Privately** option in the context menu | | `MessageDataSource` | Supplies the `messagePrivatelyOption` in the options array | | `CometChatMessageListViewModel` | Manages UI state, including `hideMessagePrivatelyOption` | -| `CometChatMessages` | Entry point for rendering or pushing the private chat interface | +| your own chat screen | Entry point for rendering or pushing the private chat interface | | `CometChat.getUser(UID:onSuccess:onError:)` | Retrieves the `User` object for the selected message sender | | `CometChatUIEvents.openChat(user:group:)` | Opens the chat interface for a user or group | -| `UIViewController` (Navigation) | Pushes or presents the private chat screen (`CometChatMessages`) | +| `UIViewController` (Navigation) | Pushes or presents your own private chat screen | ## Integration Steps @@ -82,7 +82,7 @@ func startPrivateChatManual(with selectedMessage: BaseMessage) { DispatchQueue.main.async { // Navigate to the private chat screen - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(user: user) self?.navigationController?.pushViewController(messagesVC, animated: true) } @@ -105,7 +105,7 @@ This automates the transition from group context to private conversation. | 3 | User taps **Message Privately** | | 4 | App gets `User` from `message.sender` | | 5 | Opens chat via `CometChatUIEvents.openChat(user:group:)` | -| 6 | Pushes `CometChatMessages` onto the navigation stack | +| 6 | Pushes your own chat screen onto the navigation stack | ## Customization Options diff --git a/ui-kit/ios/llms-ios-v5.mdx b/ui-kit/ios/llms-ios-v5.mdx new file mode 100644 index 000000000..0afaf95f4 --- /dev/null +++ b/ui-kit/ios/llms-ios-v5.mdx @@ -0,0 +1,141 @@ +--- +title: "iOS UI Kit v5 — LLM docs index" +description: "Machine-readable, iOS-v5-scoped index of every UI Kit page as a clean .md twin. Built for AI coding agents; kept out of the human sidebar." +--- + +{/* + SCOPED LLM INDEX for the iOS v5 UI Kit. + - UNLISTED, NOT hidden: intentionally omitted from docs.json navigation so it never shows in + the human sidebar — but it IS built, served as a clean .md twin, and INDEXED for search + + AI assistants (so AI tools, and the skills pack via its docs-map, can discover and read it). + - We deliberately do NOT use `hidden: true`/`noindex` here: in Mintlify `hidden` auto-applies + noindex, which would drop this page from search AND the auto global llms.txt / AI context. + We want it discoverable, so it stays indexable. + - Scope is v5 ONLY. The v2/, v3/ and v4/ trees are deliberately excluded — linking them + would route agents at dead API surfaces. +*/} + +# iOS UI Kit v5 — LLM docs index (Latest) + +> Stateful, drop-in Swift/UIKit chat and calling UI. Package `CometChatUIKitSwift@5` + +> `CometChatSDK@4` + `CometChatCallsSDK@5`. This page is an **iOS-v5-only** routing index for AI +> agents — a scoped alternative to the site-wide `/docs/llms.txt`. + +## How to use this index +Each link points to the docs page; **append `.md`** to its URL to fetch the clean Markdown twin +(verbatim code + an "AI Integration Quick Reference" block with names, types, and defaults). Pick +the page for the intent, then read the API there. +- Convention: any docs page URL + `.md` → raw Markdown. +- Fallback: if a `.md` twin 404s, fetch the same URL **without** `.md` (HTML). Never read the + framework's `.swiftinterface` for behaviour, and never answer an API from memory. +- iOS specifics: components are `UIView`/`UIViewController` subclasses configured through + **chainable `set(...)` methods** (`set(user:)`, `set(onItemClick:)`), not React-style props. + Some surfaces are settable **properties** instead (`hideNavigationBar`, `style`) — check the + component page rather than assuming a setter exists. + +## Install facts an agent must not guess +- **SPM is the supported path.** CocoaPods distribution is winding down; `Podfile`/`.xcworkspace` + remain valid *detection* signals for an existing project, but new integration uses SPM. +- **All three packages are required, even for a chat-only app.** The UI Kit ships as a prebuilt + binary whose public `.swiftinterface` imports both `CometChatSDK` and `CometChatCallsSDK`, so + the module fails to resolve unless every one is declared and linked: + `cometchat-uikit-ios` · `chat-sdk-ios` · `calls-sdk-ios`. +- **Pin exact versions, not floors.** The UI Kit binary is compiled against one specific Chat SDK + version and SPM will not resolve that transitively; a floating `from:` can drift into a + mismatch on the next SDK publish. +- **Deployment target is iOS 15.1**, set by the package itself — not iOS 13. +- Credentials: `.xcconfig` → matching `$(VAR)` entries in **Info.plist** → read via + `Bundle.main.object(forInfoDictionaryKey:)`. The Info.plist step is mandatory and is the most + common cause of a nil App ID at runtime. + +## Hot path — usually no fetch needed +For a plain "add chat" the install, `init → login → render` ordering, and the core drop-in +composition are stable; a well-built agent skill bakes them. Fetch below only for exhaustive +APIs, long-tail components, theming tokens, or feature enablement. +- Setup: [iOS Integration](/ui-kit/ios/getting-started) · [Overview](/ui-kit/ios/overview) +- **There is no composite chat component.** No `CometChatMessages`, + `CometChatConversationsWithMessages`, `CometChatUsersWithMessages` or + `CometChatGroupsWithMessages` exists in v5 — those are v4. A message screen is **host-composed** + from header + list + composer inside your own view controller. See + [Conversation List + Message View](/ui-kit/ios/ios-conversation). +- Core drop-ins: [Conversations](/ui-kit/ios/conversations) · + [Message Header](/ui-kit/ios/message-header) · [Message List](/ui-kit/ios/message-list) · + [Message Composer](/ui-kit/ios/message-composer) +- In SwiftUI hosts, qualify the SDK types — `conversation.conversationWith as? CometChatSDK.User` + / `as? CometChatSDK.Group`. SwiftUI declares its own `Group`, so the bare cast is ambiguous and + will not compile. + +## Getting started / integration +- [CometChat UI Kit For iOS](/ui-kit/ios/overview) +- [iOS Integration](/ui-kit/ios/getting-started) +- [Components Overview](/ui-kit/ios/components-overview) +- [Core Features](/ui-kit/ios/core-features) +- [Methods](/ui-kit/ios/methods) +- [Events](/ui-kit/ios/events) +- [Upgrading from V4 to V5](/ui-kit/ios/upgrading-from-v4) +- [Troubleshooting](/ui-kit/ios/troubleshooting) + +## Task guides (recipes) +End-to-end, buildable walkthroughs. **Build FROM the guide** for a whole feature, then apply +component-level corrections from the component pages on top. +- [Overview](/ui-kit/ios/guide-overview) +- [Conversation List + Message View](/ui-kit/ios/ios-conversation) +- [One-to-One / Group Chat](/ui-kit/ios/ios-one-to-one-chat) +- [Tab-Based Chat](/ui-kit/ios/ios-tab-based-chat) +- [Create Conversation](/ui-kit/ios/guide-new-chat) +- [Group Details](/ui-kit/ios/guide-group-chat) +- [Transfer Group Ownership](/ui-kit/ios/guide-group-ownership) +- [Threaded Messages](/ui-kit/ios/guide-threaded-messages) +- [Message Privately](/ui-kit/ios/guide-message-privately) +- [Block/Unblock User](/ui-kit/ios/guide-block-unblock-user) +- [AI Agent Integration](/ui-kit/ios/guide-ai-agent) +- [Call Log Details](/ui-kit/ios/guide-call-log-details) + +## Components — lists +- [Conversations](/ui-kit/ios/conversations) +- [Users](/ui-kit/ios/users) +- [Groups](/ui-kit/ios/groups) +- [Group Members](/ui-kit/ios/group-members) +- [Search](/ui-kit/ios/search) +- [Notification Feed](/ui-kit/ios/notification-feed) + +## Components — messaging +- [Message Header](/ui-kit/ios/message-header) +- [Message List](/ui-kit/ios/message-list) +- [Message Composer](/ui-kit/ios/message-composer) +- [Compact Message Composer](/ui-kit/ios/compact-message-composer) +- [Message Template](/ui-kit/ios/message-template) +- [Threaded Messages Header](/ui-kit/ios/threaded-messages-header) +- [Mentions Formatter](/ui-kit/ios/mentions-formatter-guide) +- [ShortCut Formatter](/ui-kit/ios/shortcut-formatter-guide) + +## Calling +- [Calling Integration](/ui-kit/ios/calling-integration) +- [Calling Features](/ui-kit/ios/call-features) +- [Call Buttons](/ui-kit/ios/call-buttons) +- [Call Logs](/ui-kit/ios/call-logs) +- [Incoming Call](/ui-kit/ios/incoming-call) +- [Outgoing Call](/ui-kit/ios/outgoing-call) +- [Ongoing Call](/ui-kit/ios/ongoing-call) + +## AI +- [AI Features](/ui-kit/ios/ai-features) +- [AI Assistant Chat History](/ui-kit/ios/ai-assistant-chat-history) + +## Theming and styling +- [Introduction](/ui-kit/ios/theme-introduction) +- [Component Styling](/ui-kit/ios/component-styling) +- [Message Bubble Styling](/ui-kit/ios/message-bubble-styling) +- [Color Resources](/ui-kit/ios/color-resources) + +## Features and extras +- [Extensions](/ui-kit/ios/extensions) +- [Campaigns](/ui-kit/ios/campaigns) +- [Localize](/ui-kit/ios/localize) +- [Sound Manager](/ui-kit/ios/sound-manager) + +## When the UI Kit has no component +Some capabilities ship no UI Kit component — AI agents, campaigns, moderation, adding group +members, transient messages, low-level presence, webhooks. For those, **drop to the Chat SDK** and +call the method directly; it is already linked under the kit. Start at the scoped SDK index: +[iOS SDK v4 — LLM docs index](/sdk/ios/llms-ios-v4). diff --git a/ui-kit/ios/message-header.mdx b/ui-kit/ios/message-header.mdx index fa64f531b..2f3a34599 100644 --- a/ui-kit/ios/message-header.mdx +++ b/ui-kit/ios/message-header.mdx @@ -37,8 +37,8 @@ The `CometChatMessageHeader` component displays user or group details in the too "callbacks": { "onBack": "() -> Void", "onError": "(CometChatException) -> Void", - "onAiChatHistoryClicked": "() -> Void", - "onAiNewChatClicked": "() -> Void" + "onAiChatHistoryClicked": "(User) -> Void (assignable property)", + "onAiNewChatClicked": "(User) -> Void (assignable property)" }, "visibility": { "hideBackButton": { "type": "Bool", "default": false }, @@ -71,7 +71,7 @@ The `CometChatMessageHeader` component displays user or group details in the too "disconnect()": "Disconnects WebSocket connection" }, "menuCustomization": { - "set(options:)": "((User?, Group?) -> [CometChatMessageHeaderOption])? - Sets custom menu options" + "set(options:)": "[CometChatPopupMenu.MenuItem]? - Sets custom menu options" } }, "events": [], @@ -82,7 +82,7 @@ The `CometChatMessageHeader` component displays user or group details in the too "onTypingEnded" ], "compositionExample": { - "description": "MessageHeader is typically used within CometChatMessages at the top of the chat screen", + "description": "MessageHeader is typically used at the top of your own chat screen", "components": ["CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], "flow": "User views header → sees recipient info → taps back to return to conversations" }, @@ -101,7 +101,7 @@ The `CometChatMessageHeader` component displays user or group details in the too ## Where It Fits -`CometChatMessageHeader` displays the recipient's information at the top of the chat screen. It's typically used within `CometChatMessages` alongside `CometChatMessageList` and `CometChatMessageComposer`. +`CometChatMessageHeader` displays the recipient's information at the top of the chat screen. It's typically used in your own chat screen alongside `CometChatMessageList` and `CometChatMessageComposer`. ```swift lines import UIKit @@ -782,12 +782,12 @@ Sets custom menu options for the message header. These options appear in the hea ```swift lines @discardableResult -public func set(options: ((_ user: User?, _ group: Group?) -> [CometChatMessageHeaderOption])?) -> Self +public func set(options: [CometChatPopupMenu.MenuItem]?) -> CometChatMessageHeader ``` | Parameter | Type | Description | |-----------|------|-------------| -| `options` | `((User?, Group?) -> [CometChatMessageHeaderOption])?` | Closure that returns an array of menu options based on the current user or group | +| `options` | `[CometChatPopupMenu.MenuItem]?` | The menu items shown in the header overflow menu | ```swift lines import CometChatUIKitSwift @@ -795,33 +795,22 @@ import CometChatSDK let messageHeader = CometChatMessageHeader() -messageHeader.set(options: { user, group in - var options = [CometChatMessageHeaderOption]() - - // Add a custom "View Profile" option - let viewProfileOption = CometChatMessageHeaderOption( - id: "view_profile", - title: "View Profile", - icon: UIImage(systemName: "person.circle") - ) { user, group in - // Handle view profile action - print("View profile tapped") - } - options.append(viewProfileOption) - - // Add a custom "Mute Notifications" option - let muteOption = CometChatMessageHeaderOption( - id: "mute_notifications", - title: "Mute Notifications", - icon: UIImage(systemName: "bell.slash") - ) { user, group in - // Handle mute action - print("Mute notifications tapped") - } - options.append(muteOption) - - return options -}) +// On CometChatMessageHeader, `set(options:)` takes the ARRAY directly — it is not a closure. +// (Conversations, Users, Groups and Group Members each take a closure returning their own +// option type; the header does not. Passing a closure here will not compile.) +let viewProfileOption = CometChatPopupMenu.MenuItem( + title: "View Profile", + icon: UIImage(systemName: "person.circle") ?? UIImage(), + action: { [weak self] in self?.showProfile() } +) + +let muteOption = CometChatPopupMenu.MenuItem( + title: "Mute Notifications", + icon: UIImage(systemName: "bell.slash") ?? UIImage(), + action: { [weak self] in self?.toggleMute() } +) + +messageHeader.set(options: [viewProfileOption, muteOption]) ``` --- @@ -850,7 +839,7 @@ avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 20) avatarStyle.borderWidth = 2 avatarStyle.borderColor = UIColor.white -messageHeader.set(avatarStyle: avatarStyle) +messageHeader.avatarStyle = avatarStyle ``` ### dateTimeFormatter @@ -973,7 +962,7 @@ import CometChatUIKitSwift let messageHeader = CometChatMessageHeader() -messageHeader.set(onAiChatHistoryClicked: { [weak self] in +messageHeader.onAiChatHistoryClicked = { [weak self] user in // Handle AI chat history button click self?.presentAiChatHistory() }) @@ -993,7 +982,7 @@ import CometChatUIKitSwift let messageHeader = CometChatMessageHeader() -messageHeader.set(onAiNewChatClicked: { [weak self] in +messageHeader.onAiNewChatClicked = { [weak self] user in // Handle AI new chat button click self?.startNewAiChat() }) @@ -1019,7 +1008,7 @@ statusIndicatorStyle.borderWidth = 2 statusIndicatorStyle.borderColor = UIColor.white statusIndicatorStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 6) -messageHeader.set(statusIndicatorStyle: statusIndicatorStyle) +messageHeader.statusIndicatorStyle = statusIndicatorStyle ``` ### typingIndicatorStyle @@ -1040,7 +1029,7 @@ let typingIndicatorStyle = TypingIndicatorStyle() typingIndicatorStyle.textColor = UIColor.systemGray typingIndicatorStyle.textFont = UIFont.italicSystemFont(ofSize: 13) -messageHeader.set(typingIndicatorStyle: typingIndicatorStyle) +messageHeader.typingIndicatorStyle = typingIndicatorStyle ``` --- diff --git a/ui-kit/ios/message-list.mdx b/ui-kit/ios/message-list.mdx index 16ec1009b..5000303d0 100644 --- a/ui-kit/ios/message-list.mdx +++ b/ui-kit/ios/message-list.mdx @@ -97,7 +97,7 @@ The `CometChatMessageList` component displays a scrollable list of messages in a "onMessageReactionRemoved" ], "compositionExample": { - "description": "MessageList is typically used within CometChatMessages alongside MessageHeader and MessageComposer", + "description": "MessageList is typically used in your own chat screen alongside MessageHeader and MessageComposer", "components": ["CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], "flow": "User views messages → types in composer → sends message → MessageList updates" }, @@ -129,7 +129,7 @@ The `CometChatMessageList` component displays a scrollable list of messages in a ## Where It Fits -`CometChatMessageList` is the core component for displaying messages in a chat. It's typically used within `CometChatMessages` alongside `CometChatMessageHeader` and `CometChatMessageComposer`. +`CometChatMessageList` is the core component for displaying messages in a chat. It's typically used in your own chat screen alongside `CometChatMessageHeader` and `CometChatMessageComposer`. ```swift lines import UIKit @@ -166,10 +166,12 @@ class ChatViewController: UIViewController { } private func openThreadView(for message: BaseMessage) { - let threadMessages = CometChatMessages() - threadMessages.set(user: message.sender as? User) - threadMessages.set(parentMessage: message) - navigationController?.pushViewController(threadMessages, animated: true) + // A thread is its OWN screen, not the root conversation VC — see + // /ui-kit/ios/guide-threaded-messages, where ThreadedMessagesVC exposes + // `var parentMessage: BaseMessage?` as a property (there is no set(parentMessage:)). + let threadVC = ThreadedMessagesVC() + threadVC.parentMessage = message + navigationController?.pushViewController(threadVC, animated: true) } private func showReactionDetails(_ reactionCount: ReactionCount, for message: BaseMessage) { @@ -271,12 +273,12 @@ let messageList = CometChatMessageList() messageList.set(onThreadRepliesClick: { [weak self] message, template in guard let self = self else { return } - let threadMessages = CometChatMessages() - if let user = message.sender as? User { - threadMessages.set(user: user) - } - threadMessages.set(parentMessage: message) - self.navigationController?.pushViewController(threadMessages, animated: true) + // The thread gets its own VC — see /ui-kit/ios/guide-threaded-messages. + // `parentMessage` is a property on ThreadedMessagesVC, not a setter, and it carries + // the user/group context, so there is nothing else to pass in. + let threadVC = ThreadedMessagesVC() + threadVC.parentMessage = message + self.navigationController?.pushViewController(threadVC, animated: true) }) ``` @@ -791,7 +793,7 @@ import CometChatSDK let myCustomTextFormatter = MyCustomTextFormatter(trackingCharacter: "#") -let cometChatMessages = CometChatMessages() +let cometChatMessages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation .set(user: user) .set(textFormatter: [myCustomTextFormatter]) ``` @@ -2078,13 +2080,13 @@ messageList.disableSoundForMessages = true let messageList = CometChatMessageList() messageList.set(user: user) -messageList.set(emptyStateView: { - let label = UILabel() - label.text = "Start a conversation!" - label.textAlignment = .center - label.textColor = .secondaryLabel - return label -}) +// emptyStateView is a UIView you assign — build it first. +let label = UILabel() +label.text = "Start a conversation!" +label.textAlignment = .center +label.textColor = .secondaryLabel + +messageList.emptyStateView = label // or: messageList.set(emptyView: label) ``` ### Scroll to bottom on new messages diff --git a/ui-kit/ios/message-template.mdx b/ui-kit/ios/message-template.mdx index 6fff04600..d6c415f40 100644 --- a/ui-kit/ios/message-template.mdx +++ b/ui-kit/ios/message-template.mdx @@ -248,8 +248,8 @@ let messageTemplates: CometChatMessageTemplate = CometChatUIKit.getDataSource(). let messageListConfiguration = MessageListConfiguration() .set(templates: [messageTemplates]) -// Apply to CometChatMessages -let cometChatMessages = CometChatMessages() +// Apply to your chat screen's CometChatMessageList +let cometChatMessages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation .set(user: user) .set(messageListConfiguration: messageListConfiguration) ``` @@ -816,7 +816,7 @@ for (index, template) in allTemplates.enumerated() { allTemplates[index] = template } -let cometChatMessages = CometChatMessages() +let cometChatMessages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation cometChatMessages.set(templates: allTemplates) ``` @@ -992,7 +992,7 @@ for (index, template) in allTemplates.enumerated() { allTemplates[index] = template } -let cometChatMessages = CometChatMessages() +let cometChatMessages = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation cometChatMessages.set(templates: allTemplates) ``` diff --git a/ui-kit/ios/ongoing-call.mdx b/ui-kit/ios/ongoing-call.mdx index 0ce807c5e..bdabb6076 100644 --- a/ui-kit/ios/ongoing-call.mdx +++ b/ui-kit/ios/ongoing-call.mdx @@ -65,7 +65,7 @@ The `CometChatOngoingCall` component provides users with a dedicated interface f let sessionID = "your_session_id" let cometChatOngoingCall = CometChatOngoingCall() -cometChatOngoingCall.set(sessionID: sessionID) +cometChatOngoingCall.set(sessionId: sessionID) cometChatOngoingCall.modalPresentationStyle = .fullScreen self.present(cometChatOngoingCall, animated: true) ``` diff --git a/ui-kit/ios/search.mdx b/ui-kit/ios/search.mdx index d2c182ff6..abad28b51 100644 --- a/ui-kit/ios/search.mdx +++ b/ui-kit/ios/search.mdx @@ -26,22 +26,16 @@ The `CometChatSearch` component is a powerful and customizable search interface "data": { "user": { "type": "User?", "default": "nil", "note": "Limits search to specific user" }, "group": { "type": "Group?", "default": "nil", "note": "Limits search to specific group" }, - "conversationsRequestBuilder": { "type": "ConversationsRequest.ConversationsRequestBuilder", "default": "SDK default" }, - "messagesRequestBuilder": { "type": "MessagesRequest.MessageRequestBuilder", "default": "SDK default" } + "note": "No request builder. Scope results with set(searchIn:) and set(searchFilters:initialFilter:); scope to one conversation with user/group above." }, "callbacks": { - "onConversationClicked": "(Conversation, IndexPath) -> Void", - "onMessageClicked": "(BaseMessage) -> Void", - "onBack": "() -> Void", - "onError": "(CometChatException) -> Void", - "onEmpty": "() -> Void" + "onConversationClicked": "(Conversation, IndexPath) -> Void (assignable property)", + "onMessageClicked": "(BaseMessage) -> Void (assignable property)", + "note": "No onBack / onError / onEmpty. Failures and empty results are VIEWS: set(errorView:), set(emptyView:), plus errorStateTitleText / errorStateSubTitleText." }, "visibility": { - "hideNavigationBar": { "type": "Bool", "default": false }, - "hideBackButton": { "type": "Bool", "default": false }, "hideUserStatus": { "type": "Bool", "default": false }, - "hideGroupType": { "type": "Bool", "default": false }, - "hideReceipts": { "type": "Bool", "default": false } + "hideGroupType": { "type": "Bool", "default": false } }, "search": { "searchFilters": { "type": "[SearchFilter]", "default": "All available filters" }, @@ -54,12 +48,12 @@ The `CometChatSearch` component is a powerful and customizable search interface "titleViewForConversation": "(Conversation) -> UIView", "subtitleViewForConversation": "(Conversation) -> UIView", "tailViewForConversation": "(Conversation) -> UIView", - "listItemViewForMessage": "(BaseMessage) -> UIView", - "leadingViewForMessage": "(BaseMessage) -> UIView", - "titleViewForMessage": "(BaseMessage) -> UIView", - "subtitleViewForMessage": "(BaseMessage) -> UIView", - "trailingViewForMessage": "(BaseMessage) -> UIView", - "initialView": "UIView", + "listItemViewForMessage": "(BaseMessage) -> UIView (whole row — the ONLY message-level slot)", + "listItemViewForImage": "(MediaMessage) -> UIView", + "listItemViewForVideo": "(MediaMessage) -> UIView", + "listItemViewForAudio": "(MediaMessage) -> UIView", + "listItemViewForDocument": "(MediaMessage) -> UIView", + "listItemViewForLink": "(MediaMessage) -> UIView", "loadingView": "UIView", "emptyView": "UIView", "errorView": "UIView" @@ -69,7 +63,7 @@ The `CometChatSearch` component is a powerful and customizable search interface "sdkListeners": [], "compositionExample": { "description": "Search is typically accessed from conversation list or message header", - "components": ["CometChatConversations", "CometChatSearch", "CometChatMessages"], + "components": ["CometChatConversations", "CometChatSearch", "CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], "flow": "User taps search → enters query → taps result → navigates to conversation/message" } } @@ -164,7 +158,7 @@ search.onBack = { --- -#### 4. onError +#### 4. Error state Listens for any errors that occur in the Search component. This action doesn't change the component's behavior. @@ -174,9 +168,13 @@ Listens for any errors that occur in the Search component. This action doesn't c import CometChatUIKitSwift let search = CometChatSearch() -search.set(onError: { error in - print("Search error:", error.localizedDescription) -}) + +// CometChatSearch surfaces failures as an error STATE, not an onError callback. +// Supply your own view, or retitle the built-in one. +search.set(errorView: myErrorView) + +search.errorStateTitleText = "Couldn't search" +search.errorStateSubTitleText = "Check your connection and try again" ``` @@ -185,7 +183,7 @@ search.set(onError: { error in #### 5. onEmpty -Listens for the empty state of the Search component. This action doesn't change the component's behavior. +The empty state is a **view you supply**, not a callback — assign it with `set(emptyView:)`. @@ -193,9 +191,13 @@ Listens for the empty state of the Search component. This action doesn't change import CometChatUIKitSwift let search = CometChatSearch() -search.set(onEmpty: { - print("No results found") -}) + +let emptyView = UILabel() +emptyView.text = "No results found" +emptyView.textAlignment = .center +emptyView.textColor = .secondaryLabel + +search.set(emptyView: emptyView) ``` @@ -252,7 +254,8 @@ search.set(searchFilters: [.unread, .groups, .photos, .videos], initialFilter: . #### 1. ConversationsRequestBuilder -Set the `ConversationsRequestBuilder` in the Search Component to filter the search results. For more options, refer to [ConversationRequestBuilder](/sdk/ios/retrieve-conversations). +`CometChatSearch` does not take a request builder. Narrow the search with `set(searchIn:)` (which +result types to return) and `set(searchFilters:initialFilter:)` (which filter chips to offer). @@ -260,11 +263,13 @@ Set the `ConversationsRequestBuilder` in the Search Component to filter the sear import CometChatUIKitSwift import CometChatSDK -let convBuilder = ConversationsRequest.ConversationsRequestBuilder() - .set(limit: 20) - let search = CometChatSearch() -search.set(conversationsRequestBuilder: convBuilder) + +// Conversations only +search.set(searchIn: [.conversations]) + +// Offer conversation-relevant filter chips, opening on "Unread" +search.set(searchFilters: [.conversations, .unread, .groups], initialFilter: .unread) ``` @@ -273,7 +278,8 @@ search.set(conversationsRequestBuilder: convBuilder) #### 2. MessagesRequestBuilder -Set the `MessagesRequestBuilder` in the Search Component to filter the search results. For more options, refer to [MessagesRequestBuilder](/sdk/ios/additional-message-filtering). +There is no `MessagesRequestBuilder` on `CometChatSearch` either. Restrict to messages with +`set(searchIn:)`, and offer message-type filter chips with `set(searchFilters:initialFilter:)`. @@ -281,12 +287,13 @@ Set the `MessagesRequestBuilder` in the Search Component to filter the search re import CometChatUIKitSwift import CometChatSDK -let msgBuilder = MessagesRequest.MessageRequestBuilder() - .set(limit: 30) - .hide(deletedMessages: true) - let search = CometChatSearch() -search.set(messagesRequestBuilder: msgBuilder) + +// Messages only +search.set(searchIn: [.messages]) + +// Message-type filter chips +search.set(searchFilters: [.messages, .photos, .videos, .audio, .documents, .links]) ``` @@ -360,7 +367,6 @@ These are small functional customizations that allow you to fine-tune the overal | loadingView | Custom loader view | `search.set(loadingView: spinner)` | | emptyView | Custom empty result view | `search.set(emptyView: emptyView)` | | errorView | Custom error UI | `search.set(errorView: errorView)` | -| initialView | Custom view before search query is entered | `search.set(initialView: initialView)` | | disableTyping | Disable typing indicators | `search.disableTyping = true` | | disableSoundForMessages | Disable message sounds | `search.disableSoundForMessages = true` | | customSoundForMessages | Custom sound URL for messages | `search.customSoundForMessages = URL(string: "...")` | @@ -399,7 +405,7 @@ searchVC.set(listItemViewForConversation: { conversation in #### Message View Customization -With message item view functions, you can assign custom views to different types of messages in the search result. For more information, refer to the [itemView](/ui-kit/ios/message-list#itemview) prop of the `CometChatMessages` component. +With message item view functions, you can assign custom views to different types of messages in the search result. For more information, refer to the [itemView](/ui-kit/ios/message-list#itemview) prop of the `CometChatMessageList` component. Here's how you can override the default message item view with a custom one for text messages: @@ -589,16 +595,18 @@ searchVC.set(listItemViewForLink: { mediaMessage in -#### Message Granular View Customization +#### Granular View Customization -For more granular control over message search results, you can customize individual parts of the message item: +Granular per-part slots exist for **conversation** rows only, and they are assignable +properties rather than `set(...)` methods. For **message** rows the component exposes a single +whole-row slot, `set(listItemViewForMessage:)` (above). -| Function | Description | -|-----------------------------|----------------------------------------------------------| -| leadingViewForMessage | Replaces the message avatar / left section | -| titleViewForMessage | Replaces the message title text | -| subtitleViewForMessage | Replaces the message subtitle text | -| trailingViewForMessage | Replaces the message trailing section | +| Property | Applies to | Description | +|------------------------------|--------------|--------------------------------------------| +| `leadingViewForConversation` | conversation | Replaces the avatar / leading section | +| `titleViewForConversation` | conversation | Replaces the title text | +| `subtitleViewForConversation`| conversation | Replaces the subtitle text | +| `tailViewForConversation` | conversation | Replaces the trailing section | @@ -607,94 +615,38 @@ import CometChatUIKitSwift let searchVC = CometChatSearch() -// Custom leading view for messages (avatar area) -searchVC.set(leadingViewForMessage: { message in +// Granular slots apply to CONVERSATION rows and are assigned, not set(...) +searchVC.leadingViewForConversation = { conversation in let customView = UIView() customView.backgroundColor = .systemPurple customView.layer.cornerRadius = 24 - // Configure custom leading view return customView -}) +} -// Custom title view for messages -searchVC.set(titleViewForMessage: { message in +searchVC.titleViewForConversation = { conversation in let label = UILabel() - label.text = message.sender?.name ?? "Unknown" + label.text = (conversation.conversationWith as? User)?.name + ?? (conversation.conversationWith as? Group)?.name label.font = .boldSystemFont(ofSize: 16) return label -}) +} -// Custom subtitle view for messages -searchVC.set(subtitleViewForMessage: { message in +searchVC.subtitleViewForConversation = { conversation in let label = UILabel() - if let textMessage = message as? TextMessage { - label.text = textMessage.text - } else { - label.text = message.type - } + label.text = (conversation.lastMessage as? TextMessage)?.text label.textColor = .secondaryLabel return label -}) +} -// Custom trailing view for messages -searchVC.set(trailingViewForMessage: { message in +searchVC.tailViewForConversation = { conversation in let label = UILabel() - let date = Date(timeIntervalSince1970: TimeInterval(message.sentAt)) - let formatter = DateFormatter() - formatter.dateFormat = "HH:mm" - label.text = formatter.string(from: date) - label.font = .systemFont(ofSize: 12) - label.textColor = .tertiaryLabel + label.text = "\(conversation.unreadMessageCount)" return label -}) -``` - - - -#### Initial View - -Customize the view displayed before the user enters a search query using the `initialView` property. - - - -```swift lines -import CometChatUIKitSwift - -let searchVC = CometChatSearch() - -// Create a custom initial view -let initialView = UIView() -let imageView = UIImageView(image: UIImage(systemName: "magnifyingglass")) -imageView.tintColor = .systemGray -imageView.contentMode = .scaleAspectFit -imageView.translatesAutoresizingMaskIntoConstraints = false - -let label = UILabel() -label.text = "Search for conversations and messages" -label.textColor = .secondaryLabel -label.textAlignment = .center -label.translatesAutoresizingMaskIntoConstraints = false - -initialView.addSubview(imageView) -initialView.addSubview(label) - -NSLayoutConstraint.activate([ - imageView.centerXAnchor.constraint(equalTo: initialView.centerXAnchor), - imageView.centerYAnchor.constraint(equalTo: initialView.centerYAnchor, constant: -20), - imageView.widthAnchor.constraint(equalToConstant: 60), - imageView.heightAnchor.constraint(equalToConstant: 60), - label.topAnchor.constraint(equalTo: imageView.bottomAnchor, constant: 16), - label.leadingAnchor.constraint(equalTo: initialView.leadingAnchor, constant: 20), - label.trailingAnchor.constraint(equalTo: initialView.trailingAnchor, constant: -20) -]) - -searchVC.set(initialView: initialView) +} ``` ---- - #### Mention Configuration Configure how @all mentions appear in search results using the `setMentionAllLabel` method. @@ -767,7 +719,7 @@ Open the search screen from a conversations list: searchVC.onConversationClicked = { [weak self] conversation, indexPath in // Navigate to messages for the selected conversation - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation if let user = conversation.conversationWith as? User { messagesVC.user = user } else if let group = conversation.conversationWith as? Group { @@ -778,7 +730,7 @@ Open the search screen from a conversations list: searchVC.onMessageClicked = { [weak self] message in // Navigate to the message in context - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation if let user = message.sender { messagesVC.user = user } @@ -823,12 +775,8 @@ let searchVC = CometChatSearch() // Set available filters with photos as the initial selection searchVC.set(searchFilters: [.photos, .videos, .documents, .audio], initialFilter: .photos) -// Or programmatically filter messages -let msgBuilder = MessagesRequest.MessageRequestBuilder() - .set(categories: ["message"]) - .set(types: ["image", "video"]) - -searchVC.set(messagesRequestBuilder: msgBuilder) +// Or restrict which result types are searched at all +searchVC.set(searchIn: [.messages]) ``` diff --git a/ui-kit/ios/shortcut-formatter-guide.mdx b/ui-kit/ios/shortcut-formatter-guide.mdx index c9797c250..59ca9c05e 100644 --- a/ui-kit/ios/shortcut-formatter-guide.mdx +++ b/ui-kit/ios/shortcut-formatter-guide.mdx @@ -270,7 +270,7 @@ cometChatMessageComposer.set(textFormatter: [shortcutFormatter]) -Ensure to pass and present `cometChatConversationsWithMessages`. If a navigation controller is already in use, utilize the `pushViewController` function instead of directly presenting the view controller. +Ensure to pass and present your own chat list controller. If a navigation controller is already in use, utilize the `pushViewController` function instead of directly presenting the view controller. --- diff --git a/ui-kit/ios/threaded-messages-header.mdx b/ui-kit/ios/threaded-messages-header.mdx index 6dbdac5c1..04f8f51d8 100644 --- a/ui-kit/ios/threaded-messages-header.mdx +++ b/ui-kit/ios/threaded-messages-header.mdx @@ -351,7 +351,7 @@ func openThread(for parentMessage: BaseMessage) { if let user = parentMessage.sender { messageList.set(user: user) } - messageList.set(parentMessage: parentMessage) + messageList.set(parentMessageId: parentMessage.id) messageList.set(controller: threadVC) messageList.translatesAutoresizingMaskIntoConstraints = false @@ -360,7 +360,7 @@ func openThread(for parentMessage: BaseMessage) { if let user = parentMessage.sender { composer.set(user: user) } - composer.set(parentMessage: parentMessage) + composer.set(parentMessageId: parentMessage.id) composer.set(controller: threadVC) composer.translatesAutoresizingMaskIntoConstraints = false diff --git a/ui-kit/ios/users.mdx b/ui-kit/ios/users.mdx index 09e5103fb..d242f0bee 100644 --- a/ui-kit/ios/users.mdx +++ b/ui-kit/ios/users.mdx @@ -103,8 +103,8 @@ The `CometChatUsers` component displays a searchable list of all available users ], "compositionExample": { "description": "Users list for starting new conversations", - "components": ["CometChatUsers", "CometChatMessages"], - "flow": "User taps on a user → onItemClick fires → Navigate to CometChatMessages with selected user" + "components": ["CometChatUsers", "CometChatMessageHeader", "CometChatMessageList", "CometChatMessageComposer"], + "flow": "User taps on a user → onItemClick fires → push your own chat screen with the selected user" }, "types": { "User": { @@ -160,7 +160,7 @@ class UsersViewController: UIViewController { } private func startConversation(with user: User) { - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(user: user) navigationController?.pushViewController(messagesVC, animated: true) } @@ -236,7 +236,7 @@ let users = CometChatUsers() users.set(onItemClick: { [weak self] user, indexPath in guard let self = self else { return } - let messagesVC = CometChatMessages() + let messagesVC = MessagesVC() // your own VC — see /ui-kit/ios/ios-conversation messagesVC.set(user: user) self.navigationController?.pushViewController(messagesVC, animated: true) }) @@ -622,7 +622,7 @@ import CometChatSDK let users = CometChatUsers() -users.set(subtitleView: { user in +users.set(subtitle: { user in let view = CustomSubtitleView(lastActiveDate: "2 hours ago") return view }) @@ -664,7 +664,7 @@ import CometChatSDK let users = CometChatUsers() -users.set(trailView: { user in +users.set(trailingView: { user in let view = CustomTrailView() return view }) @@ -1165,7 +1165,7 @@ avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 8) avatarStyle.borderWidth = 1 avatarStyle.borderColor = UIColor.systemGray4 -users.set(avatarStyle: avatarStyle) +users.avatarStyle = avatarStyle ``` ### hideBackButton @@ -1333,7 +1333,7 @@ statusIndicatorStyle.backgroundColor = UIColor.systemGreen statusIndicatorStyle.borderWidth = 2 statusIndicatorStyle.borderColor = UIColor.white -users.set(statusIndicatorStyle: statusIndicatorStyle) +users.statusIndicatorStyle = statusIndicatorStyle ``` ### usersRequestBuilder @@ -1365,7 +1365,7 @@ let friendsBuilder = UsersRequest.UsersRequestBuilder(limit: 30) .friendsOnly(true) let users = CometChatUsers() -users.set(usersRequestBuilder: friendsBuilder) +users.set(userRequestBuilder: friendsBuilder) ``` ### Online users only @@ -1375,7 +1375,7 @@ let onlineBuilder = UsersRequest.UsersRequestBuilder(limit: 30) .set(status: .online) let users = CometChatUsers() -users.set(usersRequestBuilder: onlineBuilder) +users.set(userRequestBuilder: onlineBuilder) ``` ### Custom empty state with CTA @@ -1383,20 +1383,21 @@ users.set(usersRequestBuilder: onlineBuilder) ```swift lines let users = CometChatUsers() -users.set(emptyStateView: { - let emptyView = UIView() - - let label = UILabel() - label.text = "No users found" - label.textAlignment = .center - label.textColor = .secondaryLabel - - let button = UIButton(type: .system) - button.setTitle("Invite friends", for: .normal) - - // Add subviews and constraints... - return emptyView -}) +// emptyStateView is a UIView you assign (inherited from CometChatListBase) — +// build it first, then set it. set(emptyView:) is the equivalent builder form. +let emptyView = UIView() + +let label = UILabel() +label.text = "No users found" +label.textAlignment = .center +label.textColor = .secondaryLabel + +let button = UIButton(type: .system) +button.setTitle("Invite friends", for: .normal) + +// Add subviews and constraints to emptyView... + +users.emptyStateView = emptyView // or: users.set(emptyView: emptyView) ``` ### Hide all chrome — minimal list