MessageList

fun MessageList(viewModel: MessageListViewModel, reactionSorting: ReactionSorting = ReactionSortingByFirstReactionAt, modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues(vertical = 16.dp), messagesLazyListState: MessagesLazyListState = rememberMessageListState(parentMessageId = viewModel.currentMessagesState.parentMessageId), threadMessagesStart: ThreadMessagesStart = ThreadMessagesStart.BOTTOM, onThreadClick: (Message) -> Unit = { viewModel.openMessageThread(it) }, onLongItemClick: (Message) -> Unit = { viewModel.selectMessage(it) }, onReactionsClick: (Message) -> Unit = { viewModel.selectReactions(it) }, onMessagesPageStartReached: () -> Unit = { viewModel.loadOlderMessages() }, onLastVisibleMessageChanged: (Message) -> Unit = { viewModel.updateLastSeenMessage(it) }, onScrollToBottom: () -> Unit = { viewModel.clearNewMessageState() }, onGiphyActionClick: (GiphyAction) -> Unit = { viewModel.performGiphyAction(it) }, onPollUpdated: (Message, Poll) -> Unit = { message, poll -> val selectedPoll = viewModel.pollState.selectedPoll if (viewModel.isShowingPollOptionDetails && selectedPoll != null && selectedPoll.poll.id == poll.id ) { viewModel.updatePollState(poll, message, selectedPoll.pollSelectionType) } }, onCastVote: (Message, Poll, Option) -> Unit = { message, poll, option -> viewModel.castVote( message = message, poll = poll, option = option, ) }, onRemoveVote: (Message, Poll, Vote) -> Unit = { message, poll, vote -> viewModel.removeVote( message = message, poll = poll, vote = vote, ) }, selectPoll: (Message, Poll, PollSelectionType) -> Unit = { message, poll, selectionType -> viewModel.displayPollMoreOptions(selectedPoll = SelectedPoll(poll, message, selectionType)) }, onAddAnswer: (message: Message, poll: Poll, answer: String) -> Unit = { message, poll, answer -> viewModel.castAnswer(message, poll, answer) }, onClosePoll: (String) -> Unit = { pollId -> viewModel.closePoll(pollId = pollId) }, onAddPollOption: (poll: Poll, option: String) -> Unit = { poll, option -> viewModel.addPollOption(poll, option) }, onQuotedMessageClick: (Message) -> Unit = { message -> viewModel.scrollToMessage( messageId = message.id, parentMessageId = message.parentId, ) }, onUserAvatarClick: (User) -> Unit? = null, onMessageLinkClick: (Message, String) -> Unit? = null, onUserMentionClick: (User) -> Unit = {}, onMediaGalleryPreviewResult: (MediaGalleryPreviewResult?) -> Unit = { if (it?.resultType == MediaGalleryPreviewResultType.SHOW_IN_CHAT) { viewModel.scrollToMessage( messageId = it.messageId, parentMessageId = it.parentMessageId, ) } }, onMessagesPageEndReached: (String) -> Unit = { viewModel.onBottomEndRegionReached(it) }, onScrollToBottomClicked: (() -> Unit) -> Unit = { viewModel.scrollToBottom(scrollToBottom = it) }, loadingContent: @Composable () -> Unit = { DefaultMessageListLoadingIndicator(modifier) }, emptyContent: @Composable () -> Unit = { DefaultMessageListEmptyContent(modifier) }, helperContent: @Composable BoxScope.() -> Unit = { DefaultMessagesHelperContent( messagesState = viewModel.currentMessagesState, messagesLazyListState = messagesLazyListState, scrollToBottom = onScrollToBottomClicked, ) }, loadingMoreContent: @Composable () -> Unit = { DefaultMessagesLoadingMoreIndicator() }, itemContent: @Composable (MessageListItemState) -> Unit = { messageListItem -> DefaultMessageContainer( messageListItemState = messageListItem, reactionSorting = reactionSorting, onMediaGalleryPreviewResult = onMediaGalleryPreviewResult, onCastVote = onCastVote, onRemoveVote = onRemoveVote, selectPoll = selectPoll, onPollUpdated = onPollUpdated, onClosePoll = onClosePoll, onAddPollOption = onAddPollOption, onThreadClick = onThreadClick, onLongItemClick = onLongItemClick, onReactionsClick = onReactionsClick, onGiphyActionClick = onGiphyActionClick, onQuotedMessageClick = onQuotedMessageClick, onUserAvatarClick = onUserAvatarClick, onLinkClick = onMessageLinkClick, onUserMentionClick = onUserMentionClick, onAddAnswer = onAddAnswer, ) })

Default MessageList component, that relies on MessageListViewModel to connect all the data handling operations. It also delegates events to the ViewModel to handle, like long item clicks and pagination.

Parameters

viewModel

The ViewModel that stores all the data and business logic required to show a list of messages. The user has to provide one in this case, as we require the channelId to start the operations.

reactionSorting

The sorting of the reactions. Default: ReactionSortingByFirstReactionAt.

modifier

Modifier for styling.

contentPadding

Padding values to be applied to the message list surrounding the content inside.

messagesLazyListState

State of the lazy list that represents the list of messages. Useful for controlling the scroll state and focused message offset.

threadMessagesStart

Thread messages start at the bottom or top of the screen. Default: ThreadMessagesStart.BOTTOM.

onThreadClick

Handler when the user taps on the message, while there's a thread going.

onLongItemClick

Handler for when the user long taps on a message and selects it.

onReactionsClick

Handler when the user taps on message reactions and selects them.

onMessagesPageStartReached

Handler for pagination when the end of the oldest messages has been reached.

onLastVisibleMessageChanged

Handler that notifies us when the user scrolls and the last visible message changes.

onScrollToBottom

Handler when the user reaches the bottom.

onGiphyActionClick

Handler when the user clicks on a giphy action such as shuffle, send or cancel.

onQuotedMessageClick

Handler for quoted message click action.

onUserAvatarClick

Handler when users avatar is clicked.

onMessageLinkClick

Handler for clicking on a link in the message.

onMediaGalleryPreviewResult

Handler when the user selects an option in the Media Gallery Preview screen.

onMessagesPageEndReached

Handler for pagination when the end of newest messages have been reached.

onScrollToBottomClicked

Handler when the user requests to scroll to the bottom of the messages list.

loadingContent

Composable that represents the loading content, when we're loading the initial data.

emptyContent

Composable that represents the empty content if there are no messages.

helperContent

Composable that, by default, represents the helper content featuring scrolling behavior based on the list state.

loadingMoreContent

Composable that represents the loading more content, when we're loading the next page.

itemContent

Composable that represents each item in a list. By default, we provide the MessageContainer which sets up different message types. Users can override this to provide fully custom UI and behavior.


fun MessageList(currentState: MessageListState, threadMessagesStart: ThreadMessagesStart = ThreadMessagesStart.BOTTOM, reactionSorting: ReactionSorting, modifier: Modifier = Modifier, contentPadding: PaddingValues = PaddingValues(vertical = 16.dp), messagesLazyListState: MessagesLazyListState = rememberMessageListState(parentMessageId = currentState.parentMessageId), onMessagesPageStartReached: () -> Unit = {}, onLastVisibleMessageChanged: (Message) -> Unit = {}, onScrolledToBottom: () -> Unit = {}, onPollUpdated: (Message, Poll) -> Unit = { _, _ -> }, onCastVote: (Message, Poll, Option) -> Unit = { _, _, _ -> }, onRemoveVote: (Message, Poll, Vote) -> Unit = { _, _, _ -> }, selectPoll: (Message, Poll, PollSelectionType) -> Unit = { _, _, _ -> }, onAddAnswer: (message: Message, poll: Poll, answer: String) -> Unit = { _, _, _ -> }, onClosePoll: (String) -> Unit = { _ -> }, onAddPollOption: (poll: Poll, option: String) -> Unit = { _, _ -> }, onThreadClick: (Message) -> Unit = {}, onLongItemClick: (Message) -> Unit = {}, onReactionsClick: (Message) -> Unit = {}, onMediaGalleryPreviewResult: (MediaGalleryPreviewResult?) -> Unit = {}, onGiphyActionClick: (GiphyAction) -> Unit = {}, onQuotedMessageClick: (Message) -> Unit = {}, onMessagesPageEndReached: (String) -> Unit = {}, onScrollToBottom: (() -> Unit) -> Unit = {}, onUserAvatarClick: (User) -> Unit? = null, onMessageLinkClick: (Message, String) -> Unit? = null, onUserMentionClick: (User) -> Unit = { _ -> }, loadingContent: @Composable () -> Unit = { DefaultMessageListLoadingIndicator(modifier) }, emptyContent: @Composable () -> Unit = { DefaultMessageListEmptyContent(modifier) }, helperContent: @Composable BoxScope.() -> Unit = { DefaultMessagesHelperContent( messagesState = currentState, messagesLazyListState = messagesLazyListState, scrollToBottom = onScrollToBottom, ) }, loadingMoreContent: @Composable () -> Unit = { DefaultMessagesLoadingMoreIndicator() }, itemModifier: (index: Int, item: MessageListItemState) -> Modifier = { _, _ -> Modifier }, itemContent: @Composable (MessageListItemState) -> Unit = { DefaultMessageContainer( messageListItemState = it, reactionSorting = reactionSorting, onPollUpdated = onPollUpdated, onCastVote = onCastVote, onRemoveVote = onRemoveVote, selectPoll = selectPoll, onClosePoll = onClosePoll, onAddPollOption = onAddPollOption, onLongItemClick = onLongItemClick, onThreadClick = onThreadClick, onReactionsClick = onReactionsClick, onGiphyActionClick = onGiphyActionClick, onMediaGalleryPreviewResult = onMediaGalleryPreviewResult, onQuotedMessageClick = onQuotedMessageClick, onUserAvatarClick = onUserAvatarClick, onLinkClick = onMessageLinkClick, onUserMentionClick = onUserMentionClick, onAddAnswer = onAddAnswer, ) })

Clean representation of the MessageList that is decoupled from ViewModels. This components allows users to connect the UI to their own data providers, as it relies on pure state.

Parameters

currentState

The state of the component, represented by MessageListState.

threadMessagesStart

Thread messages start at the bottom or top of the screen. Default: ThreadMessagesStart.BOTTOM.

reactionSorting

The sorting of the reactions.

modifier

Modifier for styling.

contentPadding

Padding values to be applied to the message list surrounding the content inside.

messagesLazyListState

State of the lazy list that represents the list of messages. Useful for controlling the scroll state and focused message offset.

onMessagesPageStartReached

Handler for pagination.

onLastVisibleMessageChanged

Handler that notifies us when the user scrolls and the last visible message changes.

onScrolledToBottom

Handler when the user scrolls to the bottom.

onThreadClick

Handler for when the user taps on a message with an active thread.

onLongItemClick

Handler for when the user long taps on an item.

onReactionsClick

Handler when the user taps on message reactions and selects them.

onMediaGalleryPreviewResult

Handler when the user selects an option in the Media Gallery Preview screen.

onGiphyActionClick

Handler when the user clicks on a giphy action such as shuffle, send or cancel.

onQuotedMessageClick

Handler for quoted message click action.

onMessageLinkClick

Handler for clicking on a link in the message.

onMessagesPageEndReached

Handler for pagination when the end of newest messages have been reached.

onScrollToBottom

Handler when the user requests to scroll to the bottom of the messages list.

loadingContent

Composable that represents the loading content, when we're loading the initial data.

emptyContent

Composable that represents the empty content if there are no messages.

helperContent

Composable that, by default, represents the helper content featuring scrolling behavior based on the list state.

loadingMoreContent

Composable that represents the loading more content, when we're loading the next page.

itemModifier

Modifier for styling the item container.

itemContent

Composable that represents each item in the list, that the user can override for custom UI and behavior.