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
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.
Padding values to be applied to the message list surrounding the content inside.
State of the lazy list that represents the list of messages. Useful for controlling the scroll state and focused message offset.
Handler when the user taps on the message, while there's a thread going.
Handler for when the user long taps on a message and selects it.
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.
Handler when the user reaches the bottom.
Handler when the user clicks on a giphy action such as shuffle, send or cancel.
Handler for quoted message click action.
Handler when users avatar is clicked.
Handler for clicking on a link in the message.
onMediaGalleryPreviewResult
Handler when the user selects an option in the Media Gallery Preview screen.
Handler for pagination when the end of newest messages have been reached.
Handler when the user requests to scroll to the bottom of the messages list.
Composable that represents the loading content, when we're loading the initial data.
Composable that represents the empty content if there are no messages.
Composable that, by default, represents the helper content featuring scrolling behavior based on the list state.
Composable that represents the loading more content, when we're loading the next page.
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
The sorting of the reactions.
Padding values to be applied to the message list surrounding the content inside.
State of the lazy list that represents the list of messages. Useful for controlling the scroll state and focused message offset.
onMessagesPageStartReached
onLastVisibleMessageChanged
Handler that notifies us when the user scrolls and the last visible message changes.
Handler when the user scrolls to the bottom.
Handler for when the user taps on a message with an active thread.
Handler for when the user long taps on an item.
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.
Handler when the user clicks on a giphy action such as shuffle, send or cancel.
Handler for quoted message click action.
Handler for clicking on a link in the message.
Handler for pagination when the end of newest messages have been reached.
Handler when the user requests to scroll to the bottom of the messages list.
Composable that represents the loading content, when we're loading the initial data.
Composable that represents the empty content if there are no messages.
Composable that, by default, represents the helper content featuring scrolling behavior based on the list state.
Composable that represents the loading more content, when we're loading the next page.
Modifier for styling the item container.
Composable that represents each item in the list, that the user can override for custom UI and behavior.