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..6d0f85a73 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,7 +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` | Fires when the user confirms a multi-selection | Multi-select groups | | `onSelectedItemProceed` | Triggered when selection is confirmed | Process selected groups | | `set(onError:)` | Triggered when an error occurs | Show error alert | | `set(onEmpty:)` | Triggered when list is empty | Show empty state | @@ -751,7 +751,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 +793,7 @@ import CometChatSDK let groups = CometChatGroups() -groups.set(trailView: { group in +groups.set(trailingView: { group in let view = CustomTrailView() return view }) @@ -1115,7 +1115,7 @@ avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 8) avatarStyle.borderWidth = 1 avatarStyle.borderColor = UIColor.systemGray4 -groups.set(avatarStyle: avatarStyle) +groups.avatarStyle = avatarStyle ``` ### groupsRequestBuilder @@ -1276,7 +1276,7 @@ statusIndicatorStyle.backgroundColor = UIColor.systemGreen statusIndicatorStyle.borderWidth = 2 statusIndicatorStyle.borderColor = UIColor.white -groups.set(statusIndicatorStyle: statusIndicatorStyle) +groups.statusIndicatorStyle = statusIndicatorStyle ``` --- @@ -1319,19 +1319,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 +1349,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/message-header.mdx b/ui-kit/ios/message-header.mdx index fa64f531b..04cd482f4 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 @@ -796,30 +796,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", + // set(options:) takes [CometChatPopupMenu.MenuItem] — init is (title:icon:action:) + var options = [CometChatPopupMenu.MenuItem]() + + let viewProfileOption = CometChatPopupMenu.MenuItem( 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", + icon: UIImage(systemName: "person.circle") ?? UIImage(), + action: { [weak self] in self?.showProfile() } + ) + + let muteOption = CometChatPopupMenu.MenuItem( title: "Mute Notifications", - icon: UIImage(systemName: "bell.slash") - ) { user, group in - // Handle mute action - print("Mute notifications tapped") - } - options.append(muteOption) - + icon: UIImage(systemName: "bell.slash") ?? UIImage(), + action: { [weak self] in self?.toggleMute() } + ) + + options.append(contentsOf: [viewProfileOption, muteOption]) return options }) ``` @@ -850,7 +842,7 @@ avatarStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 20) avatarStyle.borderWidth = 2 avatarStyle.borderColor = UIColor.white -messageHeader.set(avatarStyle: avatarStyle) +messageHeader.avatarStyle = avatarStyle ``` ### dateTimeFormatter @@ -973,7 +965,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 +985,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 +1011,7 @@ statusIndicatorStyle.borderWidth = 2 statusIndicatorStyle.borderColor = UIColor.white statusIndicatorStyle.cornerRadius = CometChatCornerStyle(cornerRadius: 6) -messageHeader.set(statusIndicatorStyle: statusIndicatorStyle) +messageHeader.statusIndicatorStyle = statusIndicatorStyle ``` ### typingIndicatorStyle @@ -1040,7 +1032,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..a48dbf8e2 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,7 +166,7 @@ class ChatViewController: UIViewController { } private func openThreadView(for message: BaseMessage) { - let threadMessages = CometChatMessages() + let threadMessages = MessagesVC() // your own VC — see /ui-kit/ios/guide-threaded-messages threadMessages.set(user: message.sender as? User) threadMessages.set(parentMessage: message) navigationController?.pushViewController(threadMessages, animated: true) @@ -271,7 +271,7 @@ let messageList = CometChatMessageList() messageList.set(onThreadRepliesClick: { [weak self] message, template in guard let self = self else { return } - let threadMessages = CometChatMessages() + let threadMessages = MessagesVC() // your own VC — see /ui-kit/ios/guide-threaded-messages if let user = message.sender as? User { threadMessages.set(user: user) } @@ -791,7 +791,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 +2078,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