diff --git a/CHANGELOG.md b/CHANGELOG.md index 85a8c6f39b0..acacff44c01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -98,6 +98,7 @@ - Introduce display configurations for user presence. [#5601](https://github.com/GetStream/stream-chat-android/pull/5601) ### ✅ Added +- Add customizable `verticalArrangement` to `MessagesScreen`, `MessageList` and `Messages`. [#5618](https://github.com/GetStream/stream-chat-android/pull/5618) ### ⚠️ Changed - 🚨 Breaking change: Change `@Composable public fun MessageContainer` function to `@Composable public fun LazyItemScope.MessageContainer`. [#5593](https://github.com/GetStream/stream-chat-android/pull/5593) diff --git a/stream-chat-android-ai-assistant/api/stream-chat-android-ai-assistant.api b/stream-chat-android-ai-assistant/api/stream-chat-android-ai-assistant.api index fa97bc9ee0b..b9440a2fff9 100644 --- a/stream-chat-android-ai-assistant/api/stream-chat-android-ai-assistant.api +++ b/stream-chat-android-ai-assistant/api/stream-chat-android-ai-assistant.api @@ -3,7 +3,7 @@ public final class io/getstream/chat/android/ai/assistant/AiMessageTextKt { } public final class io/getstream/chat/android/ai/assistant/AiMessagesScreenKt { - public static final fun AiMessagesScreen (Lio/getstream/chat/android/compose/viewmodel/messages/MessagesViewModelFactory;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ZLio/getstream/chat/android/ai/assistant/TypingState;Lio/getstream/chat/android/models/ReactionSorting;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ZZLio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V + public static final fun AiMessagesScreen (Lio/getstream/chat/android/compose/viewmodel/messages/MessagesViewModelFactory;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ZLio/getstream/chat/android/ai/assistant/TypingState;Lio/getstream/chat/android/models/ReactionSorting;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;ZZLandroidx/compose/foundation/layout/Arrangement$Vertical;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V } public final class io/getstream/chat/android/ai/assistant/AiRegularMessageContentKt { diff --git a/stream-chat-android-ai-assistant/build.gradle.kts b/stream-chat-android-ai-assistant/build.gradle.kts index fbff07633ec..b22a33c4510 100644 --- a/stream-chat-android-ai-assistant/build.gradle.kts +++ b/stream-chat-android-ai-assistant/build.gradle.kts @@ -15,6 +15,7 @@ rootProject.extra.apply { apply(from = "$rootDir/scripts/publish-module.gradle") apply(from = "$rootDir/scripts/android.gradle") +apply(from = "$rootDir/scripts/detekt-compose.gradle") android { namespace = "io.getstream.chat.android.ai.assistant" diff --git a/stream-chat-android-ai-assistant/src/main/kotlin/io/getstream/chat/android/ai/assistant/AiMessagesScreen.kt b/stream-chat-android-ai-assistant/src/main/kotlin/io/getstream/chat/android/ai/assistant/AiMessagesScreen.kt index aea446a61a3..232eee9a849 100644 --- a/stream-chat-android-ai-assistant/src/main/kotlin/io/getstream/chat/android/ai/assistant/AiMessagesScreen.kt +++ b/stream-chat-android-ai-assistant/src/main/kotlin/io/getstream/chat/android/ai/assistant/AiMessagesScreen.kt @@ -19,6 +19,7 @@ package io.getstream.chat.android.ai.assistant import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.gestures.scrollBy +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column @@ -98,11 +99,14 @@ import io.getstream.chat.android.ui.common.state.messages.Reply * @param skipPushNotification If new messages should skip triggering a push notification when sent. False by default. * @param skipEnrichUrl If new messages being sent, or existing ones being updated should skip enriching the URL. * If URL is not enriched, it will not be displayed as a link attachment. False by default. + * @param verticalArrangement Vertical arrangement of the regular message list. + * Default: [Arrangement.Top]. * @param threadMessagesStart Thread messages start at the bottom or top of the screen. + * Default: [ThreadMessagesStart.BOTTOM]. * @param topBarContent custom top bar content to be displayed on top of the messages list. * @param bottomBarContent custom bottom bar content to be displayed at the bottom of the messages list. - * Default: [ThreadMessagesStart.BOTTOM]. */ +@Suppress("LongMethod") @Composable public fun AiMessagesScreen( viewModelFactory: MessagesViewModelFactory, @@ -120,6 +124,7 @@ public fun AiMessagesScreen( onUserAvatarClick: (User) -> Unit = {}, skipPushNotification: Boolean = false, skipEnrichUrl: Boolean = false, + verticalArrangement: Arrangement.Vertical = Arrangement.Top, threadMessagesStart: ThreadMessagesStart = ThreadMessagesStart.BOTTOM, aiStartButton: @Composable BoxScope.() -> Unit = { DefaultAiStartButton( @@ -234,6 +239,7 @@ public fun AiMessagesScreen( viewModel = listViewModel, reactionSorting = reactionSorting, messagesLazyListState = state, + verticalArrangement = verticalArrangement, threadMessagesStart = threadMessagesStart, onThreadClick = remember(composerViewModel, listViewModel) { { diff --git a/stream-chat-android-compose/api/stream-chat-android-compose.api b/stream-chat-android-compose/api/stream-chat-android-compose.api index 26457173332..971145c9b04 100644 --- a/stream-chat-android-compose/api/stream-chat-android-compose.api +++ b/stream-chat-android-compose/api/stream-chat-android-compose.api @@ -1535,7 +1535,7 @@ public final class io/getstream/chat/android/compose/ui/messages/MessagesScreenK public static final fun MessageDialogs (Lio/getstream/chat/android/compose/viewmodel/messages/MessageListViewModel;Landroidx/compose/runtime/Composer;I)V public static final fun MessageMenus (Landroidx/compose/foundation/layout/BoxScope;Lio/getstream/chat/android/compose/viewmodel/messages/MessageListViewModel;Lio/getstream/chat/android/compose/viewmodel/messages/MessageComposerViewModel;ZZLandroidx/compose/runtime/Composer;I)V public static final fun MessageModerationDialog (Lio/getstream/chat/android/compose/viewmodel/messages/MessageListViewModel;Lio/getstream/chat/android/compose/viewmodel/messages/MessageComposerViewModel;ZZLandroidx/compose/runtime/Composer;I)V - public static final fun MessagesScreen (Lio/getstream/chat/android/compose/viewmodel/messages/MessagesViewModelFactory;ZLio/getstream/chat/android/compose/ui/components/messages/factory/MessageContentFactory;Lio/getstream/chat/android/models/ReactionSorting;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZZZLio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;III)V + public static final fun MessagesScreen (Lio/getstream/chat/android/compose/viewmodel/messages/MessagesViewModelFactory;ZLio/getstream/chat/android/compose/ui/components/messages/factory/MessageContentFactory;Lio/getstream/chat/android/models/ReactionSorting;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ZZZLandroidx/compose/foundation/layout/Arrangement$Vertical;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;III)V public static final fun PollDialogs (Lio/getstream/chat/android/compose/viewmodel/messages/MessageListViewModel;ZLandroidx/compose/runtime/Composer;I)V } @@ -1955,12 +1955,12 @@ public final class io/getstream/chat/android/compose/ui/messages/list/MessageIte } public final class io/getstream/chat/android/compose/ui/messages/list/MessageListKt { - public static final fun MessageList (Lio/getstream/chat/android/compose/viewmodel/messages/MessageListViewModel;Lio/getstream/chat/android/models/ReactionSorting;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lio/getstream/chat/android/compose/ui/components/messages/factory/MessageContentFactory;Lio/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;IIIIII)V - public static final fun MessageList (Lio/getstream/chat/android/ui/common/state/messages/list/MessageListState;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lio/getstream/chat/android/models/ReactionSorting;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lio/getstream/chat/android/compose/ui/components/messages/factory/MessageContentFactory;Lio/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;IIIIII)V + public static final fun MessageList (Lio/getstream/chat/android/compose/viewmodel/messages/MessageListViewModel;Lio/getstream/chat/android/models/ReactionSorting;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lio/getstream/chat/android/compose/ui/components/messages/factory/MessageContentFactory;Lio/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState;Landroidx/compose/foundation/layout/Arrangement$Vertical;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;IIIIII)V + public static final fun MessageList (Lio/getstream/chat/android/ui/common/state/messages/list/MessageListState;Landroidx/compose/foundation/layout/Arrangement$Vertical;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lio/getstream/chat/android/models/ReactionSorting;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lio/getstream/chat/android/compose/ui/components/messages/factory/MessageContentFactory;Lio/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;IIIIII)V } public final class io/getstream/chat/android/compose/ui/messages/list/MessagesKt { - public static final fun Messages (Lio/getstream/chat/android/ui/common/state/messages/list/MessageListState;Lio/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V + public static final fun Messages (Lio/getstream/chat/android/ui/common/state/messages/list/MessageListState;Lio/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState;Landroidx/compose/foundation/layout/Arrangement$Vertical;Lio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V } public final class io/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState { diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/MessagesScreen.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/MessagesScreen.kt index e224fa83537..c026cd67b67 100644 --- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/MessagesScreen.kt +++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/MessagesScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.WindowInsets @@ -125,10 +126,12 @@ import io.getstream.chat.android.ui.common.state.messages.updateMessage * @param skipEnrichUrl If new messages being sent, or existing ones being updated should skip enriching the URL. * If URL is not enriched, it will not be displayed as a link attachment. False by default. * @param showAnonymousAvatar If the user avatar should be shown on comments for polls with anonymous voting visibility. + * @param verticalArrangement Vertical arrangement of the regular message list. + * Default: [Arrangement.Top]. * @param threadMessagesStart Thread messages start at the bottom or top of the screen. + * Default: [ThreadMessagesStart.BOTTOM]. * @param topBarContent custom top bar content to be displayed on top of the messages list. * @param bottomBarContent custom bottom bar content to be displayed at the bottom of the messages list. - * Default: [ThreadMessagesStart.BOTTOM]. */ @Suppress("LongMethod") @Composable @@ -147,6 +150,7 @@ public fun MessagesScreen( skipPushNotification: Boolean = false, skipEnrichUrl: Boolean = false, showAnonymousAvatar: Boolean = false, + verticalArrangement: Arrangement.Vertical = Arrangement.Top, threadMessagesStart: ThreadMessagesStart = ThreadMessagesStart.BOTTOM, topBarContent: @Composable (BackAction) -> Unit = { DefaultTopBarContent( @@ -234,6 +238,7 @@ public fun MessagesScreen( messageContentFactory = messageContentFactory, reactionSorting = reactionSorting, messagesLazyListState = rememberMessageListState(parentMessageId = currentState.parentMessageId), + verticalArrangement = verticalArrangement, threadMessagesStart = threadMessagesStart, onThreadClick = remember(composerViewModel, listViewModel) { { diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageList.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageList.kt index c21f09bcad6..2e827f67d47 100644 --- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageList.kt +++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/MessageList.kt @@ -17,6 +17,7 @@ package io.getstream.chat.android.compose.ui.messages.list import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.PaddingValues @@ -62,6 +63,8 @@ import io.getstream.chat.android.ui.common.state.messages.poll.SelectedPoll * @param contentPadding Padding values to be applied to the message list surrounding the content inside. * @param messagesLazyListState State of the lazy list that represents the list of messages. Useful for controlling the * scroll state and focused message offset. + * @param verticalArrangement Vertical arrangement of the regular message list. + * Default: [Arrangement.Top]. * @param threadMessagesStart Thread messages start at the bottom or top of the screen. * Default: [ThreadMessagesStart.BOTTOM]. * @param onThreadClick Handler when the user taps on the message, while there's a thread going. @@ -96,6 +99,7 @@ public fun MessageList( messageContentFactory: MessageContentFactory = ChatTheme.messageContentFactory, messagesLazyListState: MessagesLazyListState = rememberMessageListState(parentMessageId = viewModel.currentMessagesState.parentMessageId), + verticalArrangement: Arrangement.Vertical = Arrangement.Top, threadMessagesStart: ThreadMessagesStart = ThreadMessagesStart.BOTTOM, onThreadClick: (Message) -> Unit = { viewModel.openMessageThread(it) }, onLongItemClick: (Message) -> Unit = { viewModel.selectMessage(it) }, @@ -210,6 +214,7 @@ public fun MessageList( currentState = viewModel.currentMessagesState, messagesLazyListState = messagesLazyListState, onMessagesPageStartReached = onMessagesPageStartReached, + verticalArrangement = verticalArrangement, threadMessagesStart = threadMessagesStart, onLastVisibleMessageChanged = onLastVisibleMessageChanged, onLongItemClick = onLongItemClick, @@ -330,6 +335,8 @@ internal fun DefaultMessageListEmptyContent(modifier: Modifier) { * users to connect the UI to their own data providers, as it relies on pure state. * * @param currentState The state of the component, represented by [MessageListState]. + * @param verticalArrangement Vertical arrangement of the regular message list. + * Default: [Arrangement.Top]. * @param threadMessagesStart Thread messages start at the bottom or top of the screen. * Default: [ThreadMessagesStart.BOTTOM]. * @param reactionSorting The sorting of the reactions. @@ -362,6 +369,7 @@ internal fun DefaultMessageListEmptyContent(modifier: Modifier) { @Composable public fun MessageList( currentState: MessageListState, + verticalArrangement: Arrangement.Vertical = Arrangement.Top, threadMessagesStart: ThreadMessagesStart = ThreadMessagesStart.BOTTOM, reactionSorting: ReactionSorting, modifier: Modifier = Modifier, @@ -473,6 +481,7 @@ public fun MessageList( messagesState = currentState, messagesLazyListState = messagesLazyListState, onMessagesStartReached = onMessagesPageStartReached, + verticalArrangement = verticalArrangement, threadMessagesStart = threadMessagesStart, onLastVisibleMessageChanged = onLastVisibleMessageChanged, onScrolledToBottom = onScrolledToBottom, diff --git a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/Messages.kt b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/Messages.kt index aa4beeefe9c..6bf91d5c434 100644 --- a/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/Messages.kt +++ b/stream-chat-android-compose/src/main/java/io/getstream/chat/android/compose/ui/messages/list/Messages.kt @@ -65,6 +65,8 @@ import kotlin.math.abs * and if we've reached the end of the list. * @param messagesLazyListState State of the lazy list that represents the list of messages. Useful for controlling the * scroll state and focused message offset. + * @param verticalArrangement Vertical arrangement of the regular message list. + * Default: [Arrangement.Top]. * @param threadMessagesStart Thread messages start at the bottom or top of the screen. * Default: [ThreadMessagesStart.BOTTOM]. * @param onMessagesStartReached Handler for pagination, when the user reaches the start of messages. @@ -86,6 +88,7 @@ import kotlin.math.abs public fun Messages( messagesState: MessageListState, messagesLazyListState: MessagesLazyListState, + verticalArrangement: Arrangement.Vertical = Arrangement.Top, threadMessagesStart: ThreadMessagesStart = ThreadMessagesStart.BOTTOM, onMessagesStartReached: () -> Unit, onLastVisibleMessageChanged: (Message) -> Unit, @@ -141,7 +144,7 @@ public fun Messages( }, state = lazyListState, horizontalAlignment = Alignment.Start, - verticalArrangement = threadMessagesStart.from(messagesState), + verticalArrangement = calculateVerticalArrangement(messagesState, verticalArrangement, threadMessagesStart), reverseLayout = true, contentPadding = contentPadding, ) { @@ -218,17 +221,26 @@ public fun Messages( * vertical arrangement of the messages based on the current state. * * @param messagesState A [MessageListState] instance that represents the current state of the messages. + * @param messagesVerticalArrangement Indicator from where the regular messages should start. + * @param threadMessagesStart Indicator from where the thread messages should start. * @return An [Arrangement.Vertical] instance that represents the vertical arrangement on the current * [MessageListState]. */ -private fun ThreadMessagesStart.from(messagesState: MessageListState): Arrangement.Vertical = - when (messagesState.parentMessageId) { - null -> Arrangement.Top - else -> when (this) { +private fun calculateVerticalArrangement( + messagesState: MessageListState, + messagesVerticalArrangement: Arrangement.Vertical, + threadMessagesStart: ThreadMessagesStart, +): Arrangement.Vertical { + val isInThread = messagesState.parentMessageId != null + return if (isInThread) { + when (threadMessagesStart) { ThreadMessagesStart.BOTTOM -> Arrangement.Bottom ThreadMessagesStart.TOP -> Arrangement.Top } + } else { + messagesVerticalArrangement } +} /** * Used to hoist state in a way that defers reads to a lambda, diff --git a/stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/messages/MessageListTest.kt b/stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/messages/MessageListTest.kt index 792a870945c..86c74330b9a 100644 --- a/stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/messages/MessageListTest.kt +++ b/stream-chat-android-compose/src/test/kotlin/io/getstream/chat/android/compose/ui/messages/MessageListTest.kt @@ -16,6 +16,7 @@ package io.getstream.chat.android.compose.ui.messages +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -69,6 +70,26 @@ internal class MessageListTest : SnapshotTest { } } + @Test + fun `loaded top aligned messages`() { + snapshotWithDarkMode { + MessageList( + messageListState = TwoMessagesListState, + verticalArrangement = Arrangement.Top, + ) + } + } + + @Test + fun `loaded bottom aligned messages`() { + snapshotWithDarkMode { + MessageList( + messageListState = TwoMessagesListState, + verticalArrangement = Arrangement.Bottom, + ) + } + } + @Test fun `loaded messages`() { snapshot { @@ -206,14 +227,31 @@ private val LoadedMessageListState = MessageListState( ), ) +private val TwoMessagesListState = MessageListState( + messageItems = listOf( + MessageItemState( + message = PreviewMessageData.message3, + isMine = true, + showMessageFooter = true, + ), + MessageItemState( + message = PreviewMessageData.message5, + isMine = false, + showMessageFooter = true, + ), + ), +) + @Composable private fun MessageList( messagesLazyListState: MessagesLazyListState = rememberMessagesLazyListState(), + verticalArrangement: Arrangement.Vertical = Arrangement.Top, messageListState: MessageListState, ) { MessageList( messagesLazyListState = messagesLazyListState, currentState = messageListState, reactionSorting = ReactionSortingByCount, + verticalArrangement = verticalArrangement, ) } diff --git a/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_loaded_bottom_aligned_messages.png b/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_loaded_bottom_aligned_messages.png new file mode 100644 index 00000000000..0ffd46327b2 Binary files /dev/null and b/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_loaded_bottom_aligned_messages.png differ diff --git a/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_loaded_top_aligned_messages.png b/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_loaded_top_aligned_messages.png new file mode 100644 index 00000000000..06f4b22eede Binary files /dev/null and b/stream-chat-android-compose/src/test/snapshots/images/io.getstream.chat.android.compose.ui.messages_MessageListTest_loaded_top_aligned_messages.png differ