Skip to main content

Overview

The CometChatSearch component is a powerful and customizable search interface that allows users to search across conversations and messages in real time. It supports a wide variety of filters, scopes, and customization options. CometChatSearch helps users find messages, conversations, media, and more through an intuitive and filterable search experience. It can be embedded in multiple contexts — as part of the conversation list, message header, or as a full-screen search experience.

Usage

Integration

CometChatSearch, as a composite Component, offers flexible integration options, allowing it to be launched directly via button clicks or any user-triggered action. The following code snippet exemplifies how you can seamlessly integrate the CometChatSearch component into your application.
let search = CometChatSearch()
self.navigationController?.pushViewController(search, animated: true)

Actions

1. onConversationClicked

onConversationClicked is triggered when you click on a Conversation from the search result. The onConversationClicked action doesn’t have a predefined behavior. You can override this action using the following code snippet.
search.onConversationClicked = { conversation in
    print("Conversation clicked:", conversation.conversationId)
}

2. onMessageClicked

onMessageClicked is triggered when you click on a Message from the search result. The onMessageClicked action doesn’t have a predefined behavior. You can override this action using the following code snippet.
search.onMessageClicked = { message in
    print("Message clicked:", message.id)
}

3. onBack

‘onBack’ is triggered when you click on the back button of the search component.
search.onBack = {
    self.navigationController?.popViewController(animated: true)
}

4. onError

This action doesn’t change the behavior of the component but rather listens for any errors that occur in the Search component.
search.set(onError: { error in
    print("Search error:", error.localizedDescription)
})

5. onEmpty

This action doesn’t change the behavior of the component but rather listens for the empty state of the Search component.
search.set(onEmpty: {
    print("No results found")
})

Filters

1. ConversationsRequestBuilder

You can set the ConversationsRequestBuilder in the Search Component to filter the search result. You can modify the builder as per your specific requirements with multiple options available to know more refer to ConversationRequestBuilder.
let convBuilder = ConversationsRequest.ConversationsRequestBuilder()
    .set(limit:20)

search.set(conversationsRequestBuilder: convBuilder)


2. MessagesRequestBuilder

You can set the MessagesRequestBuilder in the Search Component to filter the search result. You can modify the builder as per your specific requirements with multiple options available to know more refer to MessagesRequestBuilder.
let msgBuilder = MessagesRequest.MessageRequestBuilder()
    .set(limit: 30)
    .hide(deletedMessages: true)

search.set(messagesRequestBuilder: msgBuilder)


Events

Events are emitted by a Component. By using event you can extend existing functionality. Being global events, they can be applied in multiple locations and are capable of being added or removed. The CometChatSearch component does not produce any events.

Customization

To fit your app’s design requirements, you can customize the appearance of the CometChatSearch component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs.

Style

Using Style you can customize the look and feel of the component in your app, These parameters typically control elements such as the color, size, shape, and fonts used within the component.

// component level styling
let style = SearchStyle()
style.backgroundColor = UIColor(hex: "#EDEAFA")
style.listItemBackground = UIColor(hex: "#EDEAFA")
style.listItemTitleFont = UIFont(name: "TimesNewRomanPS-Regular", size: 16)
style.titleFont = UIFont(name: "TimesNewRomanPS-Bold", size: 12)
style.searchBarPlaceholderTextFont = UIFont(name: "TimesNewRomanPS-Regular", size: 12)
            
let searchVC = CometChatSearch()
searchVC.style = style
self?.navigationController?.pushViewController(searchVC, animated: true)
            
            
// global level styling
CometChatSearch.style.backgroundColor = UIColor(hex: "#EDEAFA")
CometChatSearch.style.listItemBackground = UIColor(hex: "#EDEAFA")
CometChatSearch.style.listItemTitleFont = UIFont(name: "TimesNewRomanPS-Regular", size: 16)
CometChatSearch.style.titleFont = UIFont(name: "TimesNewRomanPS-Bold", size: 12)
CometChatSearch.style.searchBarPlaceholderTextFont = UIFont(name: "TimesNewRomanPS-Regular", size: 12)

Functionality

These are a set of small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can toggle the visibility of UI elements. Below is a list of customizations along with corresponding code snippets
PropertyDescriptionExample
userRestrict search to a specific user chatsearch.user = user
groupRestrict search to a groupsearch.group = group
hideUserStatusHide online/offline indicatorsearch.hideUserStatus = true
hideGroupTypeHide group type iconsearch.hideGroupType = true
searchFiltersFilters like “Messages”, “Media”search.set(searchFilters: [SearchFilter] = [.unread, .groups, .photos])
initialSearchFilterDefault tab/filtersearch.initialSearchFilter = .messages
searchInRestrict search: messages / conversations / both`search.set(searchIn: [SearchScope] = [.messages])
loadingStateViewCustom loadersearch.set(loadingStateView: spinner)
emptyStateViewCustom empty result viewsearch.set(emptyStateView: emptyView)
errorStateViewCustom error UIsearch.set(errorStateView: errorView)

Advanced

For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your views, layouts, and UI elements and then incorporate those into the component.

conversationListItemView

With this function, you can assign a custom list item view to an conversation in the search result. For more information, refer to the itemView prop of the CometChatConversations component.

conversationLeadingView

With this function, you can assign a custom leading view of an conversation in the search result. For more information, refer to the leadingView prop of the CometChatConversations component.

conversationTitleView

With this function, you can assign a custom title view to an conversation in the search result. For more information, refer to the titleView prop of the CometChatConversations component.

conversationSubtitleView

With this function, you can assign a custom subtitle view to an conversation in the search result. For more information, refer to the subtitleView prop of the CometChatConversations component.

conversationTrailingView

With this function, you can assign a custom trailing view to an conversation in the search result. For more information, refer to the trailingView prop of the CometChatConversations component.

messageListItemView

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 prop of the CometChatMessages component. Here’s how you can override the default message item view with a custom one for text messages:
let searchVC = CometChatSearch()
searchVC.set(listItemViewForMessage: { message in
    return SearchMessageItemView()
})
It should look like this in the app:
  • code for custom view:
class SearchMessageItemView: UIView {

    private let containerView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(red: 0.95, green: 0.93, blue: 0.98, alpha: 1.0) // light purple
        return view
    }()
    
    private let senderLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 16)
        label.textColor = UIColor(red: 0.37, green: 0.22, blue: 0.73, alpha: 1.0) // purple
        return label
    }()
    
    private let messageLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 16)
        label.textColor = UIColor.darkGray
        label.numberOfLines = 1
        label.lineBreakMode = .byTruncatingTail
        return label
    }()
    
    private let bottomLine: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(red: 0.37, green: 0.22, blue: 0.73, alpha: 1.0) // purple border
        return view
    }()
    
    private let stack: UIStackView = {
        let stack = UIStackView()
        stack.axis = .horizontal
        stack.spacing = 4
        stack.alignment = .center
        return stack
    }()
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupUI()
    }
    
    private func setupUI() {
        addSubview(containerView)
        containerView.translatesAutoresizingMaskIntoConstraints = false
        
        containerView.addSubview(stack)
        stack.translatesAutoresizingMaskIntoConstraints = false
        
        containerView.addSubview(bottomLine)
        bottomLine.translatesAutoresizingMaskIntoConstraints = false
        
        stack.addArrangedSubview(senderLabel)
        stack.addArrangedSubview(messageLabel)

        NSLayoutConstraint.activate([
            containerView.topAnchor.constraint(equalTo: topAnchor),
            containerView.leadingAnchor.constraint(equalTo: leadingAnchor),
            containerView.trailingAnchor.constraint(equalTo: trailingAnchor),
            containerView.bottomAnchor.constraint(equalTo: bottomAnchor),
            
            stack.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 12),
            stack.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 12),
            stack.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -12),
            
            bottomLine.heightAnchor.constraint(equalToConstant: 2),
            bottomLine.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            bottomLine.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            bottomLine.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
        ])
    }
    
    /// Configure view with sender + message (with bold keyword)
    func configure(sender: String, message: String, boldKeyword: String?) {
        
        senderLabel.text = sender + ":"
        
        if let keyword = boldKeyword, message.contains(keyword) {
            let attributed = NSMutableAttributedString(string: message)
            let range = (message as NSString).range(of: keyword)
            attributed.addAttribute(.font,
                                    value: UIFont.boldSystemFont(ofSize: 16),
                                    range: range)
            messageLabel.attributedText = attributed
        } else {
            messageLabel.text = message
        }
    }
}

Bellow is the list of message item view functions available for customization:
FunctionMessage Type
listItemViewForImageImage Message
listItemViewForVideoVideo Message
listItemViewForAudioAudio Message
listItemViewForDocumentDocument Message
listItemViewForLinkLink Message

DateTime Formatters

1. setDateTimeFormatter

By providing a custom implementation of the DateTimeFormatterCallback, you can configure how time and date values are displayed. This ensures consistent formatting for labels such as “Today”, “Yesterday”, “X minutes ago”, and more.
let searchVC = CometChatSearch() 
searchVC.dateTimeFormatter.today = { timestamp in
    return "Today • \(formattedTime(timestamp))"
}

searchVC.dateTimeFormatter.otherDay = { timestamp in
    let df = DateFormatter()
    df.dateFormat = "dd MMM yyyy"
    return df.string(from: Date(timeIntervalSince1970: timestamp))
}


Text Formatters

setTextFormatters

This method enables developers to define and apply text formatters that dynamically modify or transform message content before rendering it in the UI. Text formatters can be used for purposes such as:
  • Automatically converting URLs into clickable links
  • Applying Markdown or rich text styling
  • Replacing certain words or patterns with emojis or predefined text
  • Censoring specific words for moderation
By utilizing this method, developers can enhance readability, usability, and compliance with content guidelines. MentionsFormatter Guide