Draft Messages

The SwiftUI SDK provides a way to create and manage draft messages.

Drafts are disabled by default. In order to enable this feature, you need to enable the draftMessagesEnabled flag when initializing Utils.

let utils = Utils(
    messageListConfig: MessageListConfig(draftMessagesEnabled: true)
)
let streamChat = StreamChat(chatClient: chatClient, utils: utils)

Drafts on SwiftUI are available since version 4.75.0.

Draft messages are synchronized across devices and work seamlessly offline as well.

Basic Usage

When draft messages are enabled, the logic of saving and deleting drafts will be handled automatically by the SDK. When a user starts typing a message and then navigates away from the conversation, the message content is automatically saved as a draft, for both Channels and Threads.

When the user returns to the conversation, the draft message will be loaded automatically into the composer. If the user clears the composer content or publishes the message, the draft will be deleted.

The draft messages user flow is described in the following diagram:

flowchart LR
    A[User Action]
    A -->|Leave Channel| F[Update Channel Draft]
    A -->|Leave Thread| E[Update Thread Draft]
    A -->|Clear Composer Content| D[Delete Draft]
    A -->|Publish Message| D[Delete Draft]

Customization

By default, the only additional UI added to the SDK when drafts are enabled is a preview of the draft message in the channel list and thread list. When a draft is saved, the draft message is shown in the channel list and thread list until the message is published or deleted.

The channel draft preview is displayed in the ChatChannelListItem when thechannel.draftMessage exists, and the thread draft preview is displayed in the ChatThreadListItem when the thread.parentMessage.draftReply exists.

You can customize the drafts preview by swapping the ChatChannelListItem and ChatThreadListItem components through the ViewFactory.makeChannelListItem() and the ViewFactory.makeThreadListItem() methods, respectively.

Draft List Query

At the moment, the SDK does not provide a default UI component to render the list of drafts from the current user. However, you can easily build your own component by using the ChatClient.shared.currentUserController() to fetch the drafts.

The current user controller has a loadDraftMessages() method that is responsible to query the drafts. It accepts a query: DraftListQuery parameter that allows you to customize the query.

The DraftListQuery has the following properties:

  • pagination: The initial pagination information. By default is Pagination(pageSize: 25, offset: 0)
  • sorting: The sorting criteria for the drafts. By default is [.init(key: .createdAt, isAscending: false)]

Fetching Drafts

Below is an example on how to fetch the drafts with the default query:

// Load the draft messages for the current user
let currentUserController = chatClient.currentUserController()
currentUserController.loadDraftMessages { result in
    switch result {
    case .success(let drafts):
        print("Draft messages loaded: \(drafts)")
    case .failure(let error):
        print("Failed to load draft messages: \(error)")
    }
}

Pagination

In case the currentUserController.hasLoadedAllDrafts is false, you can load the next page of drafts by calling currentUserController.loadMoreDraftMessages(). This method has an optional completion handler that will be called when the page finishes loading.

currentUserController.loadMoreDraftMessages { result in
    switch result {
    case .success(let drafts):
        print("Draft messages loaded: \(drafts)")
    case .failure(let error):
        print("Failed to load more draft messages: \(error)")
    }
}

Delegate

Whenever the drafts are updated or deleted, the CurrentChatUserControllerDelegate will be notified in the following function:

func currentUserController(
    _ controller: CurrentChatUserController,
    didChangeDraftMessages draftMessages: [DraftMessage]
)

To see a full drafts list example implementation, you can check our Demo App example here. It is in UIKit, but should give you an idea on how to implement the same logic in SwiftUI.

Draft Events

By default, the SDK will react whenever a draft is updated or deleted. But, in case your app needs additional logic, these are the available draft events:

  • DraftUpdatedEvent: Triggered when a draft is updated.
  • DraftDeletedEvent: Triggered when a draft is deleted.

© Getstream.io, Inc. All Rights Reserved.