Skip to content

Commit

Permalink
Refactor MessagePreviewView to use peper data to be render
Browse files Browse the repository at this point in the history
  • Loading branch information
JcMinarro committed Dec 3, 2024
1 parent 3d8e236 commit ba34a9a
Show file tree
Hide file tree
Showing 16 changed files with 187 additions and 109 deletions.
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 @@ -559,6 +559,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,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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.feature.internal

import androidx.recyclerview.widget.DiffUtil
import io.getstream.chat.android.ui.common.model.MessageResult

internal object MessageResultDiffCallback : DiffUtil.ItemCallback<MessageResult>() {
override fun areItemsTheSame(
oldItem: MessageResult,
newItem: MessageResult,
): Boolean = oldItem.message.id == newItem.message.id

override fun areContentsTheSame(
oldItem: MessageResult,
newItem: MessageResult,
): Boolean = oldItem == newItem
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.ui.R
import io.getstream.chat.android.ui.common.model.MessageResult
import io.getstream.chat.android.ui.databinding.StreamUiMentionListViewBinding
import io.getstream.chat.android.ui.feature.mentions.list.internal.MentionListAdapter
import io.getstream.chat.android.ui.utils.extensions.createStreamThemeWrapper
Expand Down Expand Up @@ -85,7 +86,7 @@ public class MentionListView : ViewFlipper {
}
}

public fun showMessages(messages: List<Message>) {
public fun showMessages(messages: List<MessageResult>) {
val isEmpty = messages.isEmpty()

displayedChild = if (isEmpty) Flipper.EMPTY else Flipper.RESULTS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@
package io.getstream.chat.android.ui.feature.mentions.list.internal

import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.ui.ChatUI
import io.getstream.chat.android.ui.common.extensions.internal.context
import io.getstream.chat.android.ui.common.model.MessageResult
import io.getstream.chat.android.ui.databinding.StreamUiItemMentionListBinding
import io.getstream.chat.android.ui.feature.internal.MessageResultDiffCallback
import io.getstream.chat.android.ui.feature.mentions.list.MentionListView.MentionSelectedListener
import io.getstream.chat.android.ui.feature.mentions.list.internal.MentionListAdapter.MessagePreviewViewHolder
import io.getstream.chat.android.ui.feature.messages.preview.MessagePreviewStyle
import io.getstream.chat.android.ui.feature.messages.preview.internal.MessagePreviewView
import io.getstream.chat.android.ui.utils.extensions.asMention
import io.getstream.chat.android.ui.utils.extensions.streamThemeInflater

internal class MentionListAdapter : ListAdapter<Message, MessagePreviewViewHolder>(MessageDiffCallback) {
internal class MentionListAdapter : ListAdapter<MessageResult, MessagePreviewViewHolder>(MessageResultDiffCallback) {

private var mentionSelectedListener: MentionSelectedListener? = null

Expand Down Expand Up @@ -66,24 +64,9 @@ internal class MentionListAdapter : ListAdapter<Message, MessagePreviewViewHolde
}
}

internal fun bind(message: Message) {
this.message = message
view.setMessage(message, ChatUI.currentUserProvider.getCurrentUser()?.asMention(context))
}
}

private object MessageDiffCallback : DiffUtil.ItemCallback<Message>() {
override fun areItemsTheSame(oldItem: Message, newItem: Message): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: Message, newItem: Message): Boolean {
// Comparing only properties used by the ViewHolder
return oldItem.id == newItem.id &&
oldItem.createdAt == newItem.createdAt &&
oldItem.createdLocallyAt == newItem.createdLocallyAt &&
oldItem.text == newItem.text &&
oldItem.user == newItem.user
internal fun bind(messageResult: MessageResult) {
this.message = messageResult.message
view.renderMessageResult(messageResult)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ import io.getstream.chat.android.models.Message
import io.getstream.chat.android.ui.ChatUI
import io.getstream.chat.android.ui.R
import io.getstream.chat.android.ui.common.extensions.internal.singletonList
import io.getstream.chat.android.ui.common.model.MessageResult
import io.getstream.chat.android.ui.common.utils.extensions.isDirectMessaging
import io.getstream.chat.android.ui.databinding.StreamUiMessagePreviewItemBinding
import io.getstream.chat.android.ui.feature.messages.preview.MessagePreviewStyle
import io.getstream.chat.android.ui.font.setTextStyle
import io.getstream.chat.android.ui.utils.extensions.asMention
import io.getstream.chat.android.ui.utils.extensions.bold
import io.getstream.chat.android.ui.utils.extensions.createStreamThemeWrapper
import io.getstream.chat.android.ui.utils.extensions.getAttachmentsText
Expand Down Expand Up @@ -70,25 +73,52 @@ internal class MessagePreviewView : FrameLayout {
}
}

fun setMessage(message: Message, currentUserMention: String? = null) {
binding.userAvatarView.setUser(message.user)
binding.senderNameLabel.text = formatChannelName(message)
binding.messageLabel.text = formatMessagePreview(message, currentUserMention)
fun renderMessageResult(messageResult: MessageResult) {
renderMessage(messageResult.message)
renderChannel(messageResult)
}

private fun renderDate(message: Message) {
binding.messageTimeLabel.text = ChatUI.dateFormatter.formatDate(message.createdAt ?: message.createdLocallyAt)
}

private fun formatChannelName(message: Message): CharSequence {
val channel = message.channelInfo
return if (channel?.name != null && channel.memberCount > 2) {
Html.fromHtml(
context.getString(
R.string.stream_ui_message_preview_sender,
message.user.name,
channel.name,
),
)
private fun renderMessage(message: Message) {
renderDate(message)
binding.messageLabel.text = formatMessagePreview(
message,
ChatUI.currentUserProvider.getCurrentUser()?.asMention(context),
)
}

private fun renderChannel(messageResult: MessageResult) {
val isDirectMessaging = messageResult.channel?.isDirectMessaging() == true
val currentUser = ChatUI.currentUserProvider.getCurrentUser()
binding.userAvatarView.setUser(
messageResult
.channel
?.takeIf { isDirectMessaging }
?.let { it.members.firstOrNull { it.getUserId() != currentUser?.id }?.user }
?: messageResult.message.user,
)

binding.senderNameLabel.text = if (isDirectMessaging) {
messageResult.channel?.members?.first { it.getUserId() != currentUser?.id }?.user?.name?.bold()
} else {
message.user.name.bold()
(
messageResult.channel
?.let { ChatUI.channelNameFormatter.formatChannelName(it, currentUser) }
?: messageResult.message.channelInfo?.name
)
?.let {
Html.fromHtml(
context.getString(
R.string.stream_ui_message_preview_sender,
messageResult.message.user.name,
it,
),
)
}
?: messageResult.message.user.name.bold()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.ui.R
import io.getstream.chat.android.ui.common.model.MessageResult
import io.getstream.chat.android.ui.databinding.StreamUiPinnedMessageListViewBinding
import io.getstream.chat.android.ui.feature.pinned.list.internal.PinnedMessageListAdapter
import io.getstream.chat.android.ui.utils.extensions.createStreamThemeWrapper
Expand Down Expand Up @@ -90,12 +91,12 @@ public class PinnedMessageListView : ViewFlipper {
)
}

public fun showMessages(messages: List<Message>) {
val isEmpty = messages.isEmpty()
public fun showMessages(messageResults: List<MessageResult>) {
val isEmpty = messageResults.isEmpty()

displayedChild = if (isEmpty) Flipper.EMPTY else Flipper.RESULTS

adapter.submitList(messages)
adapter.submitList(messageResults)
scrollListener.enablePagination()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,18 @@
package io.getstream.chat.android.ui.feature.pinned.list.internal

import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.ui.ChatUI
import io.getstream.chat.android.ui.common.extensions.internal.context
import io.getstream.chat.android.ui.common.model.MessageResult
import io.getstream.chat.android.ui.databinding.StreamUiItemMentionListBinding
import io.getstream.chat.android.ui.databinding.StreamUiPinnedMessageListLoadingMoreViewBinding
import io.getstream.chat.android.ui.feature.internal.MessageResultDiffCallback
import io.getstream.chat.android.ui.feature.messages.preview.MessagePreviewStyle
import io.getstream.chat.android.ui.feature.pinned.list.PinnedMessageListView.PinnedMessageSelectedListener
import io.getstream.chat.android.ui.utils.extensions.asMention
import io.getstream.chat.android.ui.utils.extensions.streamThemeInflater

internal class PinnedMessageListAdapter : ListAdapter<Message, RecyclerView.ViewHolder>(MessageDiffCallback) {
internal class PinnedMessageListAdapter : ListAdapter<MessageResult, RecyclerView.ViewHolder>(MessageResultDiffCallback) {

private var pinnedMessageSelectedListener: PinnedMessageSelectedListener? = null

Expand Down Expand Up @@ -60,7 +58,7 @@ internal class PinnedMessageListAdapter : ListAdapter<Message, RecyclerView.View
}

override fun getItemViewType(position: Int): Int {
return if (getItem(position).id.isNotEmpty()) {
return if (getItem(position).message.id.isNotEmpty()) {
ITEM_MESSAGE
} else {
ITEM_LOADING_MORE
Expand All @@ -77,7 +75,7 @@ internal class PinnedMessageListAdapter : ListAdapter<Message, RecyclerView.View
}

inner class PinnedMessageLoadingMoreView(
private val binding: StreamUiPinnedMessageListLoadingMoreViewBinding,
binding: StreamUiPinnedMessageListLoadingMoreViewBinding,
) : RecyclerView.ViewHolder(binding.root)

inner class MessagePreviewViewHolder(
Expand All @@ -92,24 +90,9 @@ internal class PinnedMessageListAdapter : ListAdapter<Message, RecyclerView.View
}
}

internal fun bind(message: Message) {
this.message = message
binding.root.setMessage(message, ChatUI.currentUserProvider.getCurrentUser()?.asMention(context))
}
}

private object MessageDiffCallback : DiffUtil.ItemCallback<Message>() {
override fun areItemsTheSame(oldItem: Message, newItem: Message): Boolean {
return oldItem.id == newItem.id
}

override fun areContentsTheSame(oldItem: Message, newItem: Message): Boolean {
// Comparing only properties used by the ViewHolder
return oldItem.id == newItem.id &&
oldItem.createdAt == newItem.createdAt &&
oldItem.createdLocallyAt == newItem.createdLocallyAt &&
oldItem.text == newItem.text &&
oldItem.user == newItem.user
internal fun bind(messageResult: MessageResult) {
this.message = messageResult.message
binding.root.renderMessageResult(messageResult)
}
}
}
Loading

0 comments on commit ba34a9a

Please sign in to comment.