Skip to content

Commit

Permalink
Merge branch 'refs/heads/develop' into feature/threads_v2
Browse files Browse the repository at this point in the history
  • Loading branch information
PetarVelikov committed Oct 23, 2024
2 parents 27c308e + 773dbca commit ecbb061
Show file tree
Hide file tree
Showing 16 changed files with 112 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2934,6 +2934,7 @@ public final class io/getstream/chat/android/client/utils/internal/toggle/Toggle
}

public final class io/getstream/chat/android/client/utils/message/MessageUtils {
public static final fun belongsToThread (Lio/getstream/chat/android/models/Message;)Z
public static final fun hasAudioRecording (Lio/getstream/chat/android/models/Message;)Z
public static final fun isDeleted (Lio/getstream/chat/android/models/Message;)Z
public static final fun isEphemeral (Lio/getstream/chat/android/models/Message;)Z
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ public fun Message.isThreadStart(): Boolean = threadParticipants.isNotEmpty()
*/
public fun Message.isThreadReply(): Boolean = !parentId.isNullOrEmpty()

/**
* @return If the message belongs to a thread.
*/
public fun Message.belongsToThread(): Boolean = this.isThreadStart() || this.isThreadReply()

/**
* @return If the message contains quoted message.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import io.getstream.chat.android.client.utils.message.belongsToThread
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.state.DateFormatType
import io.getstream.chat.android.compose.ui.components.Timestamp
Expand All @@ -52,19 +53,21 @@ public fun MessageFooter(
messageItem: MessageItemState,
) {
val message = messageItem.message
val hasThread = message.threadParticipants.isNotEmpty()
val alignment = ChatTheme.messageAlignmentProvider.provideMessageAlignment(messageItem)

if (hasThread && !messageItem.isInThread) {
val replyCount = message.replyCount
if (message.belongsToThread() && !messageItem.isInThread) {
val threadFooterText = when (message.replyCount) {
0 -> LocalContext.current.resources.getString(R.string.stream_compose_thread_reply)
else -> LocalContext.current.resources.getQuantityString(
R.plurals.stream_compose_message_list_thread_footnote,
message.replyCount,
message.replyCount,
)
}
MessageThreadFooter(
participants = message.threadParticipants,
messageAlignment = alignment,
text = LocalContext.current.resources.getQuantityString(
R.plurals.stream_compose_message_list_thread_footnote,
replyCount,
replyCount,
),
text = threadFooterText,
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import io.getstream.chat.android.client.utils.message.belongsToThread
import io.getstream.chat.android.client.utils.message.isDeleted
import io.getstream.chat.android.client.utils.message.isGiphyEphemeral
import io.getstream.chat.android.client.utils.message.isPinned
import io.getstream.chat.android.client.utils.message.isPoll
import io.getstream.chat.android.client.utils.message.isThreadStart
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.state.mediagallerypreview.MediaGalleryPreviewResult
import io.getstream.chat.android.compose.state.reactionoptions.ReactionOptionItemState
Expand Down Expand Up @@ -196,7 +196,7 @@ public fun MessageItem(
Modifier.combinedClickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = { if (message.isThreadStart()) onThreadClick(message) },
onClick = { if (message.belongsToThread()) onThreadClick(message) },
onLongClick = { if (!message.isUploading()) onLongItemClick(message) },
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ public class MessageListViewModel(
*/
public fun openMessageThread(message: Message) {
viewModelScope.launch {
messageListController.enterThreadMode(message)
messageListController.openRelatedThread(message)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@
<string name="stream_compose_message_list_giphy_send">Send</string>
<string name="stream_compose_message_list_giphy_cancel">Cancel</string>
<string name="stream_compose_message_list_giphy_shuffle">Shuffle</string>
<plurals name="stream_compose_message_list_thread_footnote">
<item quantity="one">Thread Reply</item>
<item quantity="other">%d Thread Replies</item>
</plurals>
<plurals name="stream_compose_message_list_thread_separator">
<item quantity="one">%d Reply</item>
<item quantity="other">%d Replies</item>
Expand Down
8 changes: 5 additions & 3 deletions stream-chat-android-compose/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,11 @@
<string name="stream_compose_message_list_giphy_cancel">Cancel</string>
<string name="stream_compose_message_list_giphy_shuffle">Shuffle</string>
<string name="stream_compose_message_list_footnote_edited">Edited</string>
<plurals name="stream_compose_message_list_thread_footnote">
<item quantity="one">Thread Reply</item>
<item quantity="other">%d Thread Replies</item>
<string name="stream_compose_message_list_thread_footnote_thread_reply">Thread Reply</string>
<string name="stream_compose_message_list_thread_footnote_thread_replies">%d Thread Replies</string>
<plurals name="stream_compose_message_list_thread_footnote" translatable="false">
<item quantity="one">@string/stream_compose_message_list_thread_footnote_thread_reply</item>
<item quantity="other">@string/stream_compose_message_list_thread_footnote_thread_replies</item>
</plurals>
<plurals name="stream_compose_message_list_thread_separator">
<item quantity="one">%d Reply</item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ public final class io/getstream/chat/android/ui/common/feature/messages/list/Mes
public final fun muteUser (Ljava/lang/String;Ljava/lang/Integer;)V
public static synthetic fun muteUser$default (Lio/getstream/chat/android/ui/common/feature/messages/list/MessageListController;Ljava/lang/String;Ljava/lang/Integer;ILjava/lang/Object;)V
public final fun onCleared ()V
public final fun openRelatedThread (Lio/getstream/chat/android/models/Message;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun performGiphyAction (Lio/getstream/chat/android/ui/common/state/messages/list/GiphyAction;)V
public final fun performMessageAction (Lio/getstream/chat/android/ui/common/state/messages/MessageAction;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun pinMessage (Lio/getstream/chat/android/models/Message;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import io.getstream.chat.android.client.utils.message.isGiphy
import io.getstream.chat.android.client.utils.message.isModerationBounce
import io.getstream.chat.android.client.utils.message.isModerationError
import io.getstream.chat.android.client.utils.message.isSystem
import io.getstream.chat.android.client.utils.message.isThreadStart
import io.getstream.chat.android.core.internal.InternalStreamChatApi
import io.getstream.chat.android.core.internal.coroutines.DispatcherProvider
import io.getstream.chat.android.core.internal.exhaustive
Expand Down Expand Up @@ -1146,6 +1147,18 @@ public class MessageListController(
}
}

/**
* Open the thread for the given message.
* If the message is a thread start, it will open the thread.
* If the message is a reply, it will open the thread for the parent message.
*/
public suspend fun openRelatedThread(message: Message) {
when (message.isThreadStart()) {
true -> enterThreadMode(message)
else -> message.parentId?.let { enterThreadSequential(it) }
}
}

/**
* Changes the current [_mode] to be [MessageMode.MessageThread] and uses [ChatClient] to get the [ThreadState] for
* the current thread.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2225,6 +2225,7 @@ public final class io/getstream/chat/android/ui/feature/messages/list/MessageLis
public final fun setOnUserClickListener (Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnUserClickListener;)V
public final fun setOnUserReactionClickListener (Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnUserReactionClickListener;)V
public final fun setOnViewPollResultClickListener (Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OnViewPollResultClickListener;)V
public final fun setOpenThreadHandler (Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$OpenThreadHandler;)V
public final fun setOwnCapabilities (Ljava/util/Set;)V
public final fun setReactionViewClickListener (Lio/getstream/chat/android/ui/feature/messages/list/MessageListView$ReactionViewClickListener;)V
public final fun setReactionsEnabled (Z)V
Expand Down Expand Up @@ -2476,6 +2477,10 @@ public abstract interface class io/getstream/chat/android/ui/feature/messages/li
public abstract fun onViewPollResultClick (Lio/getstream/chat/android/models/Poll;)Z
}

public abstract interface class io/getstream/chat/android/ui/feature/messages/list/MessageListView$OpenThreadHandler {
public abstract fun onOpenThread (Lio/getstream/chat/android/models/Message;)V
}

public abstract interface class io/getstream/chat/android/ui/feature/messages/list/MessageListView$ReactionViewClickListener {
public abstract fun onReactionViewClick (Lio/getstream/chat/android/models/Message;)V
}
Expand Down Expand Up @@ -4553,6 +4558,17 @@ public final class io/getstream/chat/android/ui/viewmodel/messages/MessageListVi
public fun toString ()Ljava/lang/String;
}

public final class io/getstream/chat/android/ui/viewmodel/messages/MessageListViewModel$Event$OpenThread : io/getstream/chat/android/ui/viewmodel/messages/MessageListViewModel$Event {
public fun <init> (Lio/getstream/chat/android/models/Message;)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/ui/viewmodel/messages/MessageListViewModel$Event$OpenThread;
public static synthetic fun copy$default (Lio/getstream/chat/android/ui/viewmodel/messages/MessageListViewModel$Event$OpenThread;Lio/getstream/chat/android/models/Message;ILjava/lang/Object;)Lio/getstream/chat/android/ui/viewmodel/messages/MessageListViewModel$Event$OpenThread;
public fun equals (Ljava/lang/Object;)Z
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/viewmodel/messages/MessageListViewModel$Event$PinMessage : io/getstream/chat/android/ui/viewmodel/messages/MessageListViewModel$Event {
public fun <init> (Lio/getstream/chat/android/models/Message;)V
public final fun component1 ()Lio/getstream/chat/android/models/Message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import io.getstream.chat.android.client.ChatClient
import io.getstream.chat.android.client.utils.attachment.isGiphy
import io.getstream.chat.android.client.utils.attachment.isImage
import io.getstream.chat.android.client.utils.attachment.isVideo
import io.getstream.chat.android.client.utils.message.belongsToThread
import io.getstream.chat.android.client.utils.message.isModerationError
import io.getstream.chat.android.client.utils.message.isThreadReply
import io.getstream.chat.android.core.ExperimentalStreamChatApi
Expand Down Expand Up @@ -197,6 +198,9 @@ public class MessageListView : ConstraintLayout {
private var threadStartHandler = ThreadStartHandler {
throw IllegalStateException("onStartThreadHandler must be set.")
}
private var openThreadHandler = OpenThreadHandler {
throw IllegalStateException("onStartThreadHandler must be set.")
}
private var replyMessageClickListener = OnReplyMessageClickListener {
// no-op
false
Expand Down Expand Up @@ -341,8 +345,8 @@ public class MessageListView : ConstraintLayout {
val replyTo = message.replyTo

when {
message.replyCount > 0 -> {
threadStartHandler.onStartThread(message)
message.belongsToThread() -> {
openThreadHandler.onOpenThread(message)
true
}

Expand Down Expand Up @@ -452,12 +456,8 @@ public class MessageListView : ConstraintLayout {

private val defaultThreadClickListener =
OnThreadClickListener { message ->
if (message.replyCount > 0) {
threadStartHandler.onStartThread(message)
true
} else {
false
}
message.belongsToThread()
.also { if (it) openThreadHandler.onOpenThread(message) }
}

private val attachmentGalleryDestination =
Expand Down Expand Up @@ -1856,6 +1856,15 @@ public class MessageListView : ConstraintLayout {
this.threadStartHandler = threadStartHandler
}

/**
* Sets the handler used when opening a thread.
*
* @param openThreadHandler The handler to use.
*/
public fun setOpenThreadHandler(openThreadHandler: OpenThreadHandler) {
this.openThreadHandler = openThreadHandler
}

/**
* Sets the handler used when the message is going to be flagged.
*
Expand Down Expand Up @@ -2462,6 +2471,10 @@ public class MessageListView : ConstraintLayout {
public fun onStartThread(message: Message)
}

public fun interface OpenThreadHandler {
public fun onOpenThread(message: Message)
}

public fun interface GiphySendHandler {
public fun onSendGiphy(action: GiphyAction)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,14 @@ internal class FootnoteView : LinearLayoutCompat {
root.isVisible = true
threadsOrnamentLeft.isVisible = !isMine
threadsOrnamentRight.isVisible = isMine

threadRepliesButton.text =
resources.getQuantityString(R.plurals.stream_ui_message_list_thread_reply, replyCount, replyCount)
threadRepliesButton.text = when (replyCount) {
0 -> resources.getString(R.string.stream_ui_message_list_thread_footnote_thread_reply)
else -> resources.getQuantityString(
R.plurals.stream_ui_message_list_thread_footnote,
replyCount,
replyCount,
)
}
threadRepliesButton.setTextStyle(style.textStyleThreadCounter)
}
setupUserAvatars(isMine, threadParticipants)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.view.isVisible
import io.getstream.chat.android.client.utils.message.belongsToThread
import io.getstream.chat.android.client.utils.message.isDeleted
import io.getstream.chat.android.client.utils.message.isEphemeral
import io.getstream.chat.android.client.utils.message.isGiphy
Expand Down Expand Up @@ -243,11 +244,10 @@ internal class FootnoteDecorator(
anchorView: View,
data: MessageListItem.MessageItem,
) {
val isSimpleFootnoteMode = data.message.replyCount == 0 || data.isThreadMode
if (isSimpleFootnoteMode) {
setupSimpleFootnoteWithRootConstraints(footnoteView, root, anchorView, data)
} else {
setupThreadFootnote(footnoteView, root, threadGuideline, data)
val isThreadFootnote = data.message.belongsToThread() && !data.isThreadMode
when (isThreadFootnote) {
true -> setupThreadFootnote(footnoteView, root, threadGuideline, data)
false -> setupSimpleFootnoteWithRootConstraints(footnoteView, root, anchorView, data)
}
footnoteView.applyGravity(data.isMine)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ public class MessageListViewModel(
is Event.BottomEndRegionReached -> onBottomEndRegionReached(event.messageId)
is Event.LastMessageRead -> messageListController.markLastMessageRead()
is Event.ThreadModeEntered -> onThreadModeEntered(event.parentMessage)
is Event.OpenThread -> onOpenThread(event.message)
is Event.BackButtonPressed -> onBackButtonPressed()
is Event.MarkAsUnreadMessage -> messageListController.markUnread(event.message)
is Event.DeleteMessage -> messageListController.deleteMessage(event.message, event.hard)
Expand Down Expand Up @@ -411,6 +412,17 @@ public class MessageListViewModel(
}
}

/**
* Handles an event to open a thread.
*
* @param message The message to open the thread for.
*/
private fun onOpenThread(message: Message) {
viewModelScope.launch {
messageListController.openRelatedThread(message)
}
}

/**
* Handles reacting to messages while taking into account if unique reactions are enforced.
*
Expand Down Expand Up @@ -527,6 +539,11 @@ public class MessageListViewModel(
*/
public data class ThreadModeEntered(val parentMessage: Message) : Event()

/**
* When the user
*/
public data class OpenThread(val message: Message) : Event()

/**
* When the user deletes a message.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public fun MessageListViewModel.bindView(
view.setLastMessageReadHandler { onEvent(LastMessageRead) }
view.setMessageDeleteHandler { onEvent(DeleteMessage(it, hard = false)) }
view.setThreadStartHandler { onEvent(ThreadModeEntered(it)) }
view.setOpenThreadHandler { onEvent(MessageListViewModel.Event.OpenThread(it)) }
view.setMessageFlagHandler {
onEvent(
FlagMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
<string name="stream_ui_message_list_attachment_upload_progress">%1$s / %2$s</string>
<string name="stream_ui_message_list_pinned_message">Pinned by %s</string>
<string name="stream_ui_message_list_pinned_message_you">You</string>
<plurals name="stream_ui_message_list_thread_reply">
<item quantity="one">Thread Reply</item>
<item quantity="other">%d Thread Replies</item>
<string name="stream_ui_message_list_thread_footnote_thread_reply">Thread reply</string>
<string name="stream_ui_message_list_thread_footnote_thread_replies">%d Thread Replies</string>
<plurals name="stream_ui_message_list_thread_footnote">
<item quantity="one">@string/stream_ui_message_list_thread_footnote_thread_reply</item>
<item quantity="other">@string/stream_ui_message_list_thread_footnote_thread_replies</item>
</plurals>
<plurals name="stream_ui_message_list_thread_separator">
<item quantity="one">%d Reply</item>
Expand Down

0 comments on commit ecbb061

Please sign in to comment.