Skip to main content

Introduction

The ShortCutFormatter class extends the CometChatTextFormatter class to provide a mechanism for handling shortcuts within messages. This guide walks you through the process of using ShortCutFormatter to implement shortcut extensions in your CometChat application.

Setup

1. Create the ShortCutFormatter Class

Define the ShortCutFormatter class by extending the CometChatTextFormatter class:
class ShortcutFormatter: CometChatTextFormatter {
    
    // Store fetched shortcuts from the extension
    private var messageShortcuts: [String: String] = [:]
    
    // Store suggestion items for display
    private var shortcuts: [CometChatUIKitSwift.SuggestionItem] = []
}

2. Initialize with Tracking Character

Set the trackingCharacter to '!' in the initializer:
override init(trackingCharacter: Character) {
    super.init(trackingCharacter: "!")
}

3. Define the Regex Pattern

Set the regular expression for shortcut detection in the getRegex() method:
override func getRegex() -> String {
    return "(^|\\s)!\\w+"
}

4. Return the Tracking Character

Define the getTrackingCharacter() method to return '!' as the shortcut tracking character:
override func getTrackingCharacter() -> Character {
    return "!"
}

5. Implement the Search Method

Override the search() method to search for shortcuts based on the entered query:
override func search(string: String, suggestedItems: (([CometChatUIKitSwift.SuggestionItem]) -> ())? = nil) {
    
    // Fetch shortcuts from extension if not already cached
    if messageShortcuts.isEmpty {
        CometChat.callExtension(
            slug: "message-shortcuts",
            type: .get,
            endPoint: "v1/fetch",
            body: nil
        ) { [weak self] extensionResponseData in
            guard let self = self else { return }
            
            if let shortcutData = extensionResponseData?["shortcuts"] as? [String: String] {
                self.messageShortcuts = shortcutData
                
                // Filter shortcuts matching the search string
                let suggestedItemsList = self.messageShortcuts
                    .filter { $0.key.hasPrefix(string) }
                    .map { CometChatUIKitSwift.SuggestionItem(id: $0.key, name: $0.value, visibleText: $0.value) }
                
                suggestedItems?(suggestedItemsList)
            }
        } onError: { error in
            print("Error occurred while fetching shortcuts: \(error?.errorDescription ?? "Unknown error")")
        }
    } else {
        // Use cached shortcuts
        let suggestedItemsList = messageShortcuts
            .filter { $0.key.hasPrefix(string) }
            .map { CometChatUIKitSwift.SuggestionItem(id: $0.key, name: $0.value, visibleText: $0.value) }
        
        suggestedItems?(suggestedItemsList)
    }
}

6. Handle Message String Preparation

Implement the prepareMessageString() method to convert the base chat message into an attributed string for display:
override func prepareMessageString(
    baseMessage: BaseMessage,
    regexString: String,
    alignment: MessageBubbleAlignment = .left,
    formattingType: FormattingType
) -> NSAttributedString {
    let message = (baseMessage as? TextMessage)?.text ?? ""
    return NSAttributedString(string: message)
}

7. Handle Text Tap Events

Override the onTextTapped() method if you need to handle tap events on formatted text:
override func onTextTapped(baseMessage: BaseMessage, tappedText: String, controller: UIViewController?) {
    // Handle tap event on shortcut text
}

Complete Implementation

Here’s the complete ShortcutFormatter class:
import Foundation
import CometChatSDK
import CometChatUIKitSwift

class ShortcutFormatter: CometChatTextFormatter {
    
    // MARK: - Properties
    
    private var messageShortcuts: [String: String] = [:]
    private var shortcuts: [CometChatUIKitSwift.SuggestionItem] = []
    
    // MARK: - Initialization
    
    override init(trackingCharacter: Character) {
        super.init(trackingCharacter: "!")
    }
    
    // MARK: - Override Methods
    
    override func getRegex() -> String {
        return "(^|\\s)!\\w+"
    }
    
    override func getTrackingCharacter() -> Character {
        return "!"
    }
    
    override func search(string: String, suggestedItems: (([CometChatUIKitSwift.SuggestionItem]) -> ())? = nil) {
        
        if messageShortcuts.isEmpty {
            CometChat.callExtension(
                slug: "message-shortcuts",
                type: .get,
                endPoint: "v1/fetch",
                body: nil
            ) { [weak self] extensionResponseData in
                guard let self = self else { return }
                
                if let shortcutData = extensionResponseData?["shortcuts"] as? [String: String] {
                    self.messageShortcuts = shortcutData
                    
                    let suggestedItemsList = self.messageShortcuts
                        .filter { $0.key.hasPrefix(string) }
                        .map { CometChatUIKitSwift.SuggestionItem(id: $0.key, name: $0.value, visibleText: $0.value) }
                    
                    suggestedItems?(suggestedItemsList)
                }
            } onError: { error in
                print("Error occurred while fetching shortcuts: \(error?.errorDescription ?? "Unknown error")")
            }
        } else {
            let suggestedItemsList = messageShortcuts
                .filter { $0.key.hasPrefix(string) }
                .map { CometChatUIKitSwift.SuggestionItem(id: $0.key, name: $0.value, visibleText: $0.value) }
            
            suggestedItems?(suggestedItemsList)
        }
    }
    
    override func prepareMessageString(
        baseMessage: BaseMessage,
        regexString: String,
        alignment: MessageBubbleAlignment = .left,
        formattingType: FormattingType
    ) -> NSAttributedString {
        let message = (baseMessage as? TextMessage)?.text ?? ""
        return NSAttributedString(string: message)
    }
    
    override func onTextTapped(baseMessage: BaseMessage, tappedText: String, controller: UIViewController?) {
        // Handle tap event on shortcut text
    }
}

Usage

1. Initialize the Formatter

Create an instance of ShortCutFormatter:
let shortcutFormatter = ShortcutFormatter(trackingCharacter: "!")

2. Integrate with Message Composer

If you’re using the CometChatMessageComposer component, integrate the ShortCutFormatter to manage shortcut functionalities:
let shortcutFormatter = ShortcutFormatter(trackingCharacter: "!")

let cometChatMessageComposer = CometChatMessageComposer()
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.

Example