import StreamChat
import StreamChatUI
import UIKit
final class YTMessageLayoutOptionsResolver: ChatMessageLayoutOptionsResolver {
override func optionsForMessage(
at indexPath: IndexPath,
in channel: ChatChannel,
with messages: AnyRandomAccessCollection<ChatMessage>,
appearance: Appearance
) -> ChatMessageLayoutOptions {
var options = super.optionsForMessage(at: indexPath, in: channel, with: messages, appearance: appearance)
// Remove the message options that are not needed in our case
options.remove([
.flipped,
.bubble,
.timestamp,
.avatar,
.avatarSizePadding,
.authorName,
.threadInfo,
.reactions,
.onlyVisibleForYouIndicator,
.errorIndicator
])
// Always show the avatar, timestamp and author name for each message
options.insert([.avatar, .timestamp, .authorName])
return options
}
}
ChatMessageLayoutOptionsResolver
The ChatMessageLayoutOptionsResolver
object is responsible for assigning layout options to a message in a specific position inside a list. Layout options are stored in the ChatMessageLayoutOptions
struct type.
Layout options are used by the message view to determining how the message should be rendered (for example render the message with its reactions, message is leading a group of messages, …).
The SDK comes with a built-in resolver which follows the layout rules set by Stream Chat design, this can be customized by writing your own resolver.
Customization
You can change how your messages are rendered by the message view component by selecting your own set of layout options. For instance, StreamChat groups messages by user and shows the avatar and user name at the end of the group. If in your application you want the avatar to be repeated for all messages (like YouTube does) you need to implement your own ChatMessageLayoutOptionsResolver
class and register it.
You can swap the built-in resolver with your own by setting Components.default.channelContentView
to your own view type.
Components.default.messageLayoutOptionsResolver = YTMessageLayoutOptionsResolver()
You can find more information on how the components configuration works here.
ChatMessageLayoutOptions
Describes the layout for a message based on its content and position in the message list. Views rendering a message should use this struct to determine how a message should be rendered.
Properties
rawValue
public let rawValue: Int
flipped
If set all the content will have trailing alignment. By default, the message sent by the current user is flipped.
static let flipped
bubble
If set the message content will be wrapped into a bubble.
static let bubble
continuousBubble
If set the message bubble will not have a tail
(rendered by default as a non rounded corner)
static let continuousBubble
avatarSizePadding
If set the message content will have an offset (from the trailing
edge if flipped
is set otherwise from leading
)
equal to the avatar size.
static let avatarSizePadding
avatar
If set the message author avatar will be shown.
static let avatar
timestamp
If set the message timestamp will be shown.
static let timestamp
authorName
If set the message author name will be shown in metadata.
static let authorName
text
If set the message text content will be shown.
static let text
quotedMessage
If set the message quoted by the current message will be shown.
static let quotedMessage
threadInfo
If set the message thread replies information will be shown.
static let threadInfo
errorIndicator
If set the error indicator will be shown.
static let errorIndicator
reactions
If set the reactions added to the message will be shown.
static let reactions
onlyVisibleForYouIndicator
If set the indicator saying that the message is visible for current user only will be shown.
static let onlyVisibleForYouIndicator
centered
If set all the content will have centered alignment. By default, the system messages are centered.
static let centered
flipped
and centered
are mutually exclusive. Only one of these two should be used at a time.
If both are specified in the options, centered
is prioritized
description
Returns all options the current option set consists of separated by -
character.
public var description: String
Examples
Left-aligning All Messages
By default Stream Chat aligns messages from other users on the left and messages from other users on the right, you can left-align all messages by creating your custom left-aligned MessageLayoutOptionsResolver
like this:
class LeftAlignedMessageLayoutOptionsResolver: ChatMessageLayoutOptionsResolver {
override func optionsForMessage(at indexPath: IndexPath, in channel: ChatChannel, with messages: AnyRandomAccessCollection<ChatMessage>, appearance: Appearance) -> ChatMessageLayoutOptions {
// Get options for the message at given indexpath to change it.
var options = super.optionsForMessage(at: indexPath, in: channel, with: messages, appearance: appearance)
// First it's needed to disable the flipping of sides when messages is sent from current user
options.remove(.flipped)
// After that we need to ensure that for current user there will be avatar included in the message.
options.insert(.avatar)
// If you want, you can include the author name for the message as well.
options.insert(.authorName)
return options
}
}
Components.default.messageLayoutOptionsResolver = LeftAlignedMessageLayoutOptionsResolver()
Default alignment | Left-side alignment |
---|---|
Hiding Message Bubble
If you need to hide the bubbles, consider implementing a custom subclass of MessageLayoutOptionsResolver
and then remove the bubble
option.
class NoBubblesMessageLayoutOptionsResolver: ChatMessageLayoutOptionsResolver {
override func optionsForMessage(at indexPath: IndexPath, in channel: ChatChannel, with messages: AnyRandomAccessCollection<ChatMessage>, appearance: Appearance) -> ChatMessageLayoutOptions {
// Get options for the message at given indexPath to change it.
var options = super.optionsForMessage(at: indexPath, in: channel, with: messages, appearance: appearance)
options.remove(.bubble)
return options
}
}
Components.default.messageLayoutOptionsResolver = NoBubblesMessageLayoutOptionsResolver()
visible bubbles | hidden bubbles |
---|---|
Disabling Message Groups
The default behaviour of ChatMessageLayoutOptionsResolver
is to check whether messages are grouped or not.
The isLastInSequence
property enables this operation when grouping messages.
class NotGroupedMessageLayoutOptionsResolver: ChatMessageLayoutOptionsResolver {
override func optionsForMessage(at indexPath: IndexPath, in channel: ChatChannel, with messages: AnyRandomAccessCollection<ChatMessage>, appearance: Appearance) -> ChatMessageLayoutOptions {
// Get options for the message at given indexPath to change it.
var options = super.optionsForMessage(at: indexPath, in: channel, with: messages, appearance: appearance)
options.insert(.continuousBubble)
options.insert(.timestamp)
options.insert(.avatar)
let messageIndex = messages.index(messages.startIndex, offsetBy: indexPath.item)
let message = messages[messageIndex]
// Let's add authorName to the message when it's not send by current user.
if !message.isSentByCurrentUser && !channel.isDirectMessageChannel {
options.insert(.authorName)
}
return options
}
}
Components.default.messageLayoutOptionsResolver = NotGroupedMessageLayoutOptionsResolver()
Message grouped | Messages separated |
---|---|