Skip to content

Commit

Permalink
Add ReactionSorting (#5248)
Browse files Browse the repository at this point in the history
* Create new `ReactionGroup` class

* Add ReactionGroup to Message entity

* Create DB Entities

* Create DTOs for ReactionGroup

* Update CHANGELOG.md

* Sort reactions using ReactionGroups by FirstReactionAt

* Create a mother method to generate random ReactionGroup

* Create `ReactionSorting` interface and default implementations

* Use an injected `ReactionSorting` to sort reactions

* Create styles to inject a `ReactionSorting` to be used to sort reactions

* Update CHANGELOG.md

* fix api dump

---------

Co-authored-by: kanat <kijalbaev@gmail.com>
  • Loading branch information
JcMinarro and kanat committed Apr 30, 2024
1 parent cdc0331 commit 7a586a1
Show file tree
Hide file tree
Showing 22 changed files with 420 additions and 44 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Added `reason` and `custom` fields to flag message endpoint.[#5242](https://github.com/GetStream/stream-chat-android/pull/5242)
- Added `reason` and `custom` fields to flag user endpoint.[#5242](https://github.com/GetStream/stream-chat-android/pull/5242)
- Added `reactionGroups` field to `Message` entity. [#5247](https://github.com/GetStream/stream-chat-android/pull/5247)
- Added `ReactionSorting` interface to allow custom sorting of reactions. [#5248](https://github.com/GetStream/stream-chat-android/pull/5248)

### ⚠️ Changed

Expand Down Expand Up @@ -67,6 +68,7 @@

### ✅ Added
- Added a Button to jump to the first unread message in the channel. [#5236](https://github.com/GetStream/stream-chat-android/pull/5236)
- Added `ViewReactionsViewStyle.reactionSorting` field to customize the sorting of reactions. [#5248](https://github.com/GetStream/stream-chat-android/pull/5248)

### ⚠️ Changed

Expand All @@ -78,6 +80,7 @@

### ⬆️ Improved
- Channel List is not updated with new messages within a thread. [#5245](https://github.com/GetStream/stream-chat-android/pull/5245)
- MessageList accept `reactionSorting` parameter to customize the sorting of reactions. [#5248](https://github.com/GetStream/stream-chat-android/pull/5248)

### ✅ Added

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import io.getstream.chat.android.compose.viewmodel.messages.AttachmentsPickerVie
import io.getstream.chat.android.compose.viewmodel.messages.MessageComposerViewModel
import io.getstream.chat.android.compose.viewmodel.messages.MessageListViewModel
import io.getstream.chat.android.compose.viewmodel.messages.MessagesViewModelFactory
import io.getstream.chat.android.models.ReactionSortingByFirstReactionAt
import io.getstream.chat.android.ui.common.state.messages.MessageMode
import io.getstream.chat.android.ui.common.state.messages.Reply
import io.getstream.chat.android.ui.common.state.messages.list.DeletedMessageVisibility
Expand Down Expand Up @@ -172,6 +173,7 @@ class MessagesActivity : BaseConnectedActivity() {
.background(ChatTheme.colors.appBackground)
.fillMaxSize(),
viewModel = listViewModel,
reactionSorting = ReactionSortingByFirstReactionAt,
messagesLazyListState = if (listViewModel.isInThread) rememberMessageListState() else lazyListState,
onThreadClick = { message ->
composerViewModel.setMessageMode(MessageMode.MessageThread(message))
Expand Down
10 changes: 5 additions & 5 deletions stream-chat-android-compose/api/stream-chat-android-compose.api
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ public final class io/getstream/chat/android/compose/ui/composables/AudioWaveSee
}

public final class io/getstream/chat/android/compose/ui/messages/MessagesScreenKt {
public static final fun MessagesScreen (Lio/getstream/chat/android/compose/viewmodel/messages/MessagesViewModelFactory;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;ZZLio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lio/getstream/chat/android/compose/state/messages/attachments/StatefulStreamMediaRecorder;Landroidx/compose/runtime/Composer;II)V
public static final fun MessagesScreen (Lio/getstream/chat/android/compose/viewmodel/messages/MessagesViewModelFactory;ZLio/getstream/chat/android/models/ReactionSorting;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;ZZLio/getstream/chat/android/compose/ui/messages/list/ThreadMessagesStart;Lio/getstream/chat/android/compose/state/messages/attachments/StatefulStreamMediaRecorder;Landroidx/compose/runtime/Composer;III)V
}

public final class io/getstream/chat/android/compose/ui/messages/attachments/AttachmentsPickerKt {
Expand Down Expand Up @@ -1409,17 +1409,17 @@ public final class io/getstream/chat/android/compose/ui/messages/list/Composable
}

public final class io/getstream/chat/android/compose/ui/messages/list/MessageContainerKt {
public static final fun MessageContainer (Lio/getstream/chat/android/ui/common/state/messages/list/MessageListItemState;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/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;III)V
public static final fun MessageContainer (Lio/getstream/chat/android/ui/common/state/messages/list/MessageListItemState;Lio/getstream/chat/android/models/ReactionSorting;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/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;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/compose/ui/messages/list/MessageItemKt {
public static final field HighlightFadeOutDurationMillis I
public static final fun MessageItem (Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V
public static final fun MessageItem (Lio/getstream/chat/android/ui/common/state/messages/list/MessageItemState;Lio/getstream/chat/android/models/ReactionSorting;Lkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Lkotlin/jvm/functions/Function4;Landroidx/compose/runtime/Composer;III)V
}

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;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;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/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/Function2;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)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;Landroidx/compose/ui/Modifier;Landroidx/compose/foundation/layout/PaddingValues;Lio/getstream/chat/android/compose/ui/messages/list/MessagesLazyListState;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;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/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)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/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/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/Function2;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)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/messages/list/MessagesLazyListState;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function0;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/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Landroidx/compose/runtime/Composer;IIII)V
}

public final class io/getstream/chat/android/compose/ui/messages/list/MessagesKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ import io.getstream.chat.android.compose.viewmodel.messages.MessagesViewModelFac
import io.getstream.chat.android.models.Channel
import io.getstream.chat.android.models.LinkPreview
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.ReactionSorting
import io.getstream.chat.android.models.ReactionSortingByFirstReactionAt
import io.getstream.chat.android.ui.common.state.messages.Delete
import io.getstream.chat.android.ui.common.state.messages.Edit
import io.getstream.chat.android.ui.common.state.messages.Flag
Expand Down Expand Up @@ -102,6 +104,7 @@ import io.getstream.chat.android.ui.common.state.messages.updateMessage
* You can customize the behavior of the list through its parameters. For default behavior,
* simply create an instance and pass in just the channel ID and the context.
* @param showHeader If we're showing the header or not.
* @param reactionSorting The sorting type for reactions. Default is [ReactionSortingByFirstReactionAt].
* @param onBackPressed Handler for when the user taps on the Back button and/or the system
* back button.
* @param onHeaderTitleClick Handler for when the user taps on the header section.
Expand All @@ -117,6 +120,7 @@ import io.getstream.chat.android.ui.common.state.messages.updateMessage
public fun MessagesScreen(
viewModelFactory: MessagesViewModelFactory,
showHeader: Boolean = true,
reactionSorting: ReactionSorting = ReactionSortingByFirstReactionAt,
onBackPressed: () -> Unit = {},
onHeaderTitleClick: (channel: Channel) -> Unit = {},
onChannelAvatarClick: () -> Unit = {},
Expand Down Expand Up @@ -232,6 +236,7 @@ public fun MessagesScreen(
.background(ChatTheme.colors.appBackground)
.padding(it),
viewModel = listViewModel,
reactionSorting = reactionSorting,
messagesLazyListState = rememberMessageListState(parentMessageId = currentState.parentMessageId),
threadMessagesStart = threadMessagesStart,
onThreadClick = remember(composerViewModel, listViewModel) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import io.getstream.chat.android.compose.state.mediagallerypreview.MediaGalleryP
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.viewmodel.messages.MessagesViewModelFactory
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.ReactionSorting
import io.getstream.chat.android.ui.common.feature.messages.list.MessageListController
import io.getstream.chat.android.ui.common.state.messages.list.DateSeparatorItemState
import io.getstream.chat.android.ui.common.state.messages.list.EmptyThreadPlaceholderItemState
Expand All @@ -52,6 +53,7 @@ import io.getstream.chat.android.ui.common.state.messages.list.UnreadSeparatorIt
* Represents the message item container that allows us to customize each type of item in the MessageList.
*
* @param messageListItemState The state of the message list item.
* @param reactionSorting The sorting of reactions for the message.
* @param onLongItemClick Handler when the user long taps on an item.
* @param onReactionsClick Handler when the user taps on message reactions.
* @param onThreadClick Handler when the user taps on a thread within a message item.
Expand All @@ -70,6 +72,7 @@ import io.getstream.chat.android.ui.common.state.messages.list.UnreadSeparatorIt
@Composable
public fun MessageContainer(
messageListItemState: MessageListItemState,
reactionSorting: ReactionSorting,
onLongItemClick: (Message) -> Unit = {},
onReactionsClick: (Message) -> Unit = {},
onThreadClick: (Message) -> Unit = {},
Expand All @@ -91,6 +94,7 @@ public fun MessageContainer(
messageItemContent: @Composable (MessageItemState) -> Unit = {
DefaultMessageItem(
messageItem = it,
reactionSorting = reactionSorting,
onLongItemClick = onLongItemClick,
onReactionsClick = onReactionsClick,
onThreadClick = onThreadClick,
Expand Down Expand Up @@ -233,9 +237,11 @@ internal fun DefaultSystemMessageContent(systemMessageState: SystemMessageItemSt
* @param onQuotedMessageClick Handler for quoted message click action.
* @param onMediaGalleryPreviewResult Handler when the user receives a result from the Media Gallery Preview.
*/
@Suppress("LongParameterList")
@Composable
internal fun DefaultMessageItem(
messageItem: MessageItemState,
reactionSorting: ReactionSorting,
onLongItemClick: (Message) -> Unit,
onReactionsClick: (Message) -> Unit = {},
onThreadClick: (Message) -> Unit,
Expand All @@ -245,6 +251,7 @@ internal fun DefaultMessageItem(
) {
MessageItem(
messageItem = messageItem,
reactionSorting = reactionSorting,
onLongItemClick = onLongItemClick,
onReactionsClick = onReactionsClick,
onThreadClick = onThreadClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import io.getstream.chat.android.compose.ui.util.isEmojiOnlyWithoutBubble
import io.getstream.chat.android.compose.ui.util.isErrorOrFailed
import io.getstream.chat.android.compose.ui.util.isUploading
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.ReactionSorting
import io.getstream.chat.android.models.User
import io.getstream.chat.android.ui.common.state.messages.list.DeletedMessageVisibility
import io.getstream.chat.android.ui.common.state.messages.list.GiphyAction
Expand All @@ -93,6 +94,7 @@ import io.getstream.chat.android.ui.common.state.messages.list.MessagePosition
*
* @param messageItem The message item to show, which holds the message and the group position, if the message is in
* a group of messages from the same user.
* @param reactionSorting The sorting for the reactions, if we have any.
* @param onLongItemClick Handler when the user selects a message, on long tap.
* @param modifier Modifier for styling.
* @param onReactionsClick Handler when the user taps on message reactions.
Expand All @@ -116,6 +118,7 @@ import io.getstream.chat.android.ui.common.state.messages.list.MessagePosition
@Composable
public fun MessageItem(
messageItem: MessageItemState,
reactionSorting: ReactionSorting,
onLongItemClick: (Message) -> Unit,
modifier: Modifier = Modifier,
onReactionsClick: (Message) -> Unit = {},
Expand All @@ -129,6 +132,7 @@ public fun MessageItem(
headerContent: @Composable ColumnScope.(MessageItemState) -> Unit = {
DefaultMessageItemHeaderContent(
messageItem = it,
reactionSorting = reactionSorting,
onReactionsClick = onReactionsClick,
)
},
Expand Down Expand Up @@ -253,11 +257,14 @@ internal fun RowScope.DefaultMessageItemLeadingContent(
* By default, we show if the message is pinned and a list of reactions for the message.
*
* @param messageItem The message item to show the content for.
* @param reactionSorting The sorting for the reactions, if we have any.
* @param onReactionsClick Handler when the user taps on message reactions.
*/
@Suppress("LongMethod")
@Composable
internal fun DefaultMessageItemHeaderContent(
messageItem: MessageItemState,
reactionSorting: ReactionSorting,
onReactionsClick: (Message) -> Unit = {},
) {
val message = messageItem.message
Expand Down Expand Up @@ -297,13 +304,14 @@ internal fun DefaultMessageItemHeaderContent(

if (!message.isDeleted()) {
val ownReactions = message.ownReactions
val reactionCounts = message.reactionCounts.ifEmpty { return }
val reactionGroups = message.reactionGroups.ifEmpty { return }
val iconFactory = ChatTheme.reactionIconFactory
reactionCounts
reactionGroups
.filter { iconFactory.isReactionSupported(it.key) }
.takeIf { it.isNotEmpty() }
?.map { it.key }
?.map { type ->
?.toList()
?.sortedWith { o1, o2 -> reactionSorting.compare(o1.second, o2.second) }
?.map { (type, _) ->
val isSelected = ownReactions.any { it.type == type }
val reactionIcon = iconFactory.createReactionIcon(type)
ReactionOptionItemState(
Expand Down
Loading

0 comments on commit 7a586a1

Please sign in to comment.