Skip to content

Commit

Permalink
[AND-13] Add channel info when searching for messages (#5500)
Browse files Browse the repository at this point in the history
* Add channel property on `SearchResultItemState` class

* Build channel name with the channel entity

* Reder proper user avatar

* Refactor `MessagePreviewView` to use peper data to be render

* Fix checkstyle

* Update CHANGELOG.md
  • Loading branch information
JcMinarro authored Dec 12, 2024
1 parent 6b900b8 commit 2ebf4a9
Show file tree
Hide file tree
Showing 25 changed files with 280 additions and 147 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 @@
- Add support for moderation V2. Add `moderation` field in `Message` model to support the new version of moderation. [#5493](https://github.com/GetStream/stream-chat-android/pull/5493)

### ⚠️ Changed
- 🚨 Breaking change: ViewModels related with "searching messages" feature provide a `List<MessageResult>` instead of a `List<Message>`. [#5500](https://github.com/GetStream/stream-chat-android/pull/5500)

### ❌ Removed

Expand Down Expand Up @@ -83,8 +84,10 @@
- Add `ChatTheme.keyboardBehaviour` property to customize different keyboard behaviours. [#5506](https://github.com/GetStream/stream-chat-android/pull/5506)
- Add `MessageOptionItemVisibility.isBlockUserVisible` property to show/hide the block user option. [#5512](https://github.com/GetStream/stream-chat-android/pull/5512)
- Add `ChatTheme.channelOptionsTheme` property to customize the channel options. [#5513](https://github.com/GetStream/stream-chat-android/pull/5513)
- Add `SearchResultItemState.channel` property containing the cached info of the channel where the message was sent. [#5500](https://github.com/GetStream/stream-chat-android/pull/5500)

### ⚠️ Changed
- 🚨 Breaking change: The `SearchResultNameFormatter.formatMessageTitle` method receives a `SearchResultItemState` instead of a `Message`. [#5500](https://github.com/GetStream/stream-chat-android/pull/5500)

### ❌ Removed

Expand Down
12 changes: 6 additions & 6 deletions stream-chat-android-compose/api/stream-chat-android-compose.api
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,13 @@ public final class io/getstream/chat/android/compose/state/channels/list/ItemSta

public final class io/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState : io/getstream/chat/android/compose/state/channels/list/ItemState {
public static final field $stable I
public fun <init> (Lio/getstream/chat/android/models/Message;)V
public fun <init> (Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/Channel;)V
public final fun component1 ()Lio/getstream/chat/android/models/Message;
public final fun copy (Lio/getstream/chat/android/models/Message;)Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;
public static synthetic fun copy$default (Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;Lio/getstream/chat/android/models/Message;ILjava/lang/Object;)Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;
public final fun component2 ()Lio/getstream/chat/android/models/Channel;
public final fun copy (Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/Channel;)Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;
public static synthetic fun copy$default (Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/Channel;ILjava/lang/Object;)Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;
public fun equals (Ljava/lang/Object;)Z
public final fun getChannel ()Lio/getstream/chat/android/models/Channel;
public fun getKey ()Ljava/lang/String;
public final fun getMessage ()Lio/getstream/chat/android/models/Message;
public fun hashCode ()I
Expand Down Expand Up @@ -743,10 +745,8 @@ public final class io/getstream/chat/android/compose/ui/channels/list/Composable
public final class io/getstream/chat/android/compose/ui/channels/list/ComposableSingletons$SearchResultItemKt {
public static final field INSTANCE Lio/getstream/chat/android/compose/ui/channels/list/ComposableSingletons$SearchResultItemKt;
public static field lambda-1 Lkotlin/jvm/functions/Function4;
public static field lambda-2 Lkotlin/jvm/functions/Function4;
public fun <init> ()V
public final fun getLambda-1$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function4;
public final fun getLambda-2$stream_chat_android_compose_release ()Lkotlin/jvm/functions/Function4;
}

public final class io/getstream/chat/android/compose/ui/channels/list/SearchResultItemKt {
Expand Down Expand Up @@ -3420,7 +3420,7 @@ public final class io/getstream/chat/android/compose/ui/util/ReactionIconFactory

public abstract interface class io/getstream/chat/android/compose/ui/util/SearchResultNameFormatter {
public static final field Companion Lio/getstream/chat/android/compose/ui/util/SearchResultNameFormatter$Companion;
public abstract fun formatMessageTitle (Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/User;)Landroidx/compose/ui/text/AnnotatedString;
public abstract fun formatMessageTitle (Lio/getstream/chat/android/compose/state/channels/list/ItemState$SearchResultItemState;Lio/getstream/chat/android/models/User;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/text/AnnotatedString;
}

public final class io/getstream/chat/android/compose/ui/util/SearchResultNameFormatter$Companion {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,12 @@ public sealed class ItemState {
* Represents each search result item we show in the list of channels.
*
* @param message The message to show.
* @param channel The channel where the message was sent.
* It can be null if the channel was not found on the local cache.
*/
public data class SearchResultItemState(
val message: Message,
val channel: Channel?,
) : ItemState() {
override val key: String = message.id
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public fun SearchResultItem(
leadingContent: @Composable RowScope.(ItemState.SearchResultItemState) -> Unit = {
DefaultSearchResultItemLeadingContent(
searchResultItemState = it,
currentUser = currentUser,
)
},
centerContent: @Composable RowScope.(ItemState.SearchResultItemState) -> Unit = {
Expand Down Expand Up @@ -107,22 +108,33 @@ public fun SearchResultItem(
* the message.
*
* @param searchResultItemState The state of the search result item.
* @param currentUser The currently logged in user.
*/
@Composable
internal fun DefaultSearchResultItemLeadingContent(
searchResultItemState: ItemState.SearchResultItemState,
currentUser: User?,
) {
UserAvatar(
user = searchResultItemState.message.user,
modifier = Modifier
.padding(
start = ChatTheme.dimens.channelItemHorizontalPadding,
end = 4.dp,
top = ChatTheme.dimens.channelItemVerticalPadding,
bottom = ChatTheme.dimens.channelItemVerticalPadding,
(
searchResultItemState
.channel
?.takeIf { it.members.size == 2 }
?.let { it.members.firstOrNull { it.getUserId() != currentUser?.id }?.user }
?: searchResultItemState.message.user
)
.let { user ->
UserAvatar(
user = user,
modifier = Modifier
.padding(
start = ChatTheme.dimens.channelItemHorizontalPadding,
end = 4.dp,
top = ChatTheme.dimens.channelItemVerticalPadding,
bottom = ChatTheme.dimens.channelItemVerticalPadding,
)
.size(ChatTheme.dimens.channelAvatarSize),
)
.size(ChatTheme.dimens.channelAvatarSize),
)
}
}

/**
Expand All @@ -145,7 +157,7 @@ internal fun RowScope.DefaultSearchResultItemCenterContent(
verticalArrangement = Arrangement.Center,
) {
Text(
text = ChatTheme.searchResultNameFormatter.formatMessageTitle(searchResultItemState.message, currentUser),
text = ChatTheme.searchResultNameFormatter.formatMessageTitle(searchResultItemState, currentUser),
style = ChatTheme.typography.bodyBold,
fontSize = 16.sp,
maxLines = 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public fun PinnedMessageList(
state.results.isEmpty() && state.isLoading -> loadingContent()
state.results.isEmpty() && !state.isLoading -> emptyContent()
else -> PinnedMessages(
messages = state.results,
messages = state.results.map { it.message },
modifier = modifier,
itemContent = itemContent,
itemDivider = itemDivider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@

package io.getstream.chat.android.compose.ui.util

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.withStyle
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.state.channels.list.ItemState
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.models.User

/**
Expand All @@ -30,12 +34,16 @@ import io.getstream.chat.android.models.User
public fun interface SearchResultNameFormatter {

/**
* Generates a title text for the given message.
* Generates a title text for the given search result item.
*
* @param message The message whose data is used to generate the preview text.
* @return The formatted text representation for the given message.
* @param searchResultItem The search result item whose data is used to generate the preview text.
* @param currentUser The currently logged in user.
*/
public fun formatMessageTitle(message: Message, currentUser: User?): AnnotatedString
@Composable
public fun formatMessageTitle(
searchResultItem: ItemState.SearchResultItemState,
currentUser: User?,
): AnnotatedString

public companion object {
/**
Expand All @@ -52,19 +60,31 @@ public fun interface SearchResultNameFormatter {
}

private object DefaultSearchResultNameFormatter : SearchResultNameFormatter {
override fun formatMessageTitle(message: Message, currentUser: User?): AnnotatedString =
@Composable
override fun formatMessageTitle(
searchResultItem: ItemState.SearchResultItemState,
currentUser: User?,
): AnnotatedString =
buildAnnotatedString {
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(message.user.name)
}
message.channelInfo
?.takeIf { it.memberCount > 2 }
?.name
?.let {
append(" in ")
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(it)
}
if (searchResultItem.channel?.isOneToOne(currentUser) == true) {
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(searchResultItem.channel.getOtherUsers(currentUser).firstOrNull()?.name)
}
} else {
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(searchResultItem.message.user.name)
}
(
searchResultItem.channel
?.let { ChatTheme.channelNameFormatter.formatChannelName(it, currentUser) }
?: searchResultItem.message.channelInfo?.name
)
?.let { channelName ->
append(stringResource(R.string.stream_compose_in))
withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
append(channelName)
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,19 @@ public class ChannelListViewModel(
logger.d { "[observeSearchMessages] query: '$query'" }
searchMessageState.filterNotNull().collectLatest {
logger.v { "[observeSearchMessages] state: ${it.stringify()}" }
val channels = chatClient.repositoryFacade.selectChannels(it.messages.map { message -> message.cid })
channelsState = channelsState.copy(
searchQuery = searchQuery.value,
isLoading = it.isLoading,
isLoadingMore = it.isLoadingMore,
endOfChannels = !it.canLoadMore,
channelItems = it.messages.map(ItemState::SearchResultItemState),
channelItems = it.messages.map {
val channel = channels.firstOrNull { channel -> channel.cid == it.cid }
ItemState.SearchResultItemState(
message = it,
channel = channel,
)
},
)
}
}.onFailure {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@

<!-- Threads -->
<string name="stream_compose_thread_list_empty_title">No threads here yet...</string>
<string name="stream_compose_in">" in "</string>
<plurals name="stream_compose_thread_list_new_threads">
<item quantity="one">%d new thread</item>
<item quantity="other">%d new threads</item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,20 @@ public final class io/getstream/chat/android/ui/common/images/resizing/StreamCdn
public final fun defaultStreamCdnImageResizing ()Lio/getstream/chat/android/ui/common/images/resizing/StreamCdnImageResizing;
}

public final class io/getstream/chat/android/ui/common/model/MessageResult {
public static final field $stable I
public fun <init> (Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/Channel;)V
public final fun component1 ()Lio/getstream/chat/android/models/Message;
public final fun component2 ()Lio/getstream/chat/android/models/Channel;
public final fun copy (Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/Channel;)Lio/getstream/chat/android/ui/common/model/MessageResult;
public static synthetic fun copy$default (Lio/getstream/chat/android/ui/common/model/MessageResult;Lio/getstream/chat/android/models/Message;Lio/getstream/chat/android/models/Channel;ILjava/lang/Object;)Lio/getstream/chat/android/ui/common/model/MessageResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getChannel ()Lio/getstream/chat/android/models/Channel;
public final fun getMessage ()Lio/getstream/chat/android/models/Message;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class io/getstream/chat/android/ui/common/notifications/StreamCoilUserIconBuilder : io/getstream/chat/android/client/notifications/handler/UserIconBuilder {
public static final field $stable I
public fun <init> (Landroid/content/Context;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import io.getstream.chat.android.core.internal.InternalStreamChatApi
import io.getstream.chat.android.core.internal.coroutines.DispatcherProvider
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.querysort.QuerySortByField
import io.getstream.chat.android.ui.common.model.MessageResult
import io.getstream.chat.android.ui.common.state.pinned.PinnedMessageListState
import io.getstream.log.TaggedLogger
import io.getstream.log.taggedLogger
Expand Down Expand Up @@ -97,7 +98,7 @@ public class PinnedMessageListController(
_state.update { current ->
current.copy(
isLoading = true,
results = current.results + Message(),
results = current.results + MessageResult(Message(), null),
)
}
loadPinnedMessages()
Expand All @@ -118,7 +119,14 @@ public class PinnedMessageListController(
logger.d { "Loaded ${messages.size} pinned messages" }
_state.update { current ->
current.copy(
results = (current.results + messages).filter { it.id.isNotEmpty() },
results = (
current.results + messages.map { message ->
MessageResult(
message,
null,
)
}
).filter { it.message.id.isNotEmpty() },
isLoading = false,
canLoadMore = messages.size == QUERY_LIMIT,
nextDate = messages.lastOrNull()?.pinnedAt ?: nextDate,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2014-2024 Stream.io Inc. All rights reserved.
*
* Licensed under the Stream License;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://github.com/GetStream/stream-chat-android/blob/main/LICENSE
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package io.getstream.chat.android.ui.common.model

import io.getstream.chat.android.models.Channel
import io.getstream.chat.android.models.Message

public data class MessageResult(
val message: Message,
val channel: Channel?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

package io.getstream.chat.android.ui.common.state.pinned

import io.getstream.chat.android.models.Message
import io.getstream.chat.android.ui.common.model.MessageResult
import java.util.Date

/**
Expand All @@ -29,7 +29,7 @@ import java.util.Date
*/
public data class PinnedMessageListState(
val canLoadMore: Boolean,
val results: List<Message>,
val results: List<MessageResult>,
val isLoading: Boolean,
val nextDate: Date,
)
Loading

0 comments on commit 2ebf4a9

Please sign in to comment.