Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AND-13] Add channel info when searching for messages #5500

Merged
merged 8 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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 }
VelikovPetar marked this conversation as resolved.
Show resolved Hide resolved
?.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
Loading