Skip to content
Draft
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
131 changes: 101 additions & 30 deletions stream-chat-android-compose/api/stream-chat-android-compose.api

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import io.getstream.chat.android.compose.ui.util.passiveRipple
import io.getstream.chat.android.compose.ui.util.shouldBeDisplayedAsFullSizeAttachment
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.User
import io.getstream.chat.android.ui.common.feature.messages.composer.mention.Mention
import io.getstream.chat.android.ui.common.state.messages.list.GiphyAction
import io.getstream.chat.android.ui.common.utils.extensions.hasLink

Expand Down Expand Up @@ -95,6 +96,7 @@ public fun MessageContent(
messageAlignment: MessageAlignment = MessageAlignment.Start,
onLinkClick: ((Message, String) -> Unit)? = null,
onMediaGalleryPreviewResult: (MediaGalleryPreviewResult?) -> Unit = {},
onMentionClick: (Mention) -> Unit = {},
) {
when {
message.isGiphyEphemeral() -> ChatTheme.componentFactory.MessageGiphyContent(
Expand Down Expand Up @@ -123,6 +125,7 @@ public fun MessageContent(
onQuotedMessageClick = onQuotedMessageClick,
onLinkClick = onLinkClick,
onUserMentionClick = onUserMentionClick,
onMentionClick = onMentionClick,
),
)
}
Expand Down Expand Up @@ -180,6 +183,7 @@ internal fun DefaultMessageRegularContent(
onQuotedMessageClick: (Message) -> Unit,
onUserMentionClick: (User) -> Unit = {},
onLinkClick: ((Message, String) -> Unit)? = null,
onMentionClick: (Mention) -> Unit = {},
) {
val componentFactory = ChatTheme.componentFactory

Expand Down Expand Up @@ -270,6 +274,7 @@ internal fun DefaultMessageRegularContent(
onLongItemClick = onLongItemClick,
onLinkClick = onLinkClick,
onUserMentionClick = onUserMentionClick,
onMentionClick = onMentionClick,
),
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,19 @@ import androidx.compose.ui.util.fastForEach
import androidx.core.net.toUri
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.theme.MessageStyling
import io.getstream.chat.android.compose.ui.util.AnnotationTagChannelMention
import io.getstream.chat.android.compose.ui.util.AnnotationTagEmail
import io.getstream.chat.android.compose.ui.util.AnnotationTagMention
import io.getstream.chat.android.compose.ui.util.AnnotationTagGroupMention
import io.getstream.chat.android.compose.ui.util.AnnotationTagHereMention
import io.getstream.chat.android.compose.ui.util.AnnotationTagRoleMention
import io.getstream.chat.android.compose.ui.util.AnnotationTagUrl
import io.getstream.chat.android.compose.ui.util.AnnotationTagUserMention
import io.getstream.chat.android.compose.ui.util.isFewEmoji
import io.getstream.chat.android.compose.ui.util.isSingleEmoji
import io.getstream.chat.android.compose.ui.util.showOriginalTextAsState
import io.getstream.chat.android.models.Message
import io.getstream.chat.android.models.User
import io.getstream.chat.android.ui.common.feature.messages.composer.mention.Mention
import io.getstream.chat.android.ui.common.utils.extensions.getUserByNameOrId
import io.getstream.chat.android.ui.common.utils.extensions.isMine

Expand All @@ -81,6 +86,7 @@ public fun MessageText(
onLongItemClick: (Message) -> Unit,
onLinkClick: ((Message, String) -> Unit)? = null,
onUserMentionClick: (User) -> Unit = {},
onMentionClick: (Mention) -> Unit = {},
) {
val context = LocalContext.current

Expand All @@ -105,7 +111,7 @@ public fun MessageText(
}

val annotations = remember(styledText) {
styledText.getStringAnnotations(0, styledText.lastIndex)
styledText.getStringAnnotations(0, styledText.length)
}
if (annotations.fastAny(AnnotatedString.Range<String>::isInteractiveTag)) {
ClickableText(
Expand All @@ -122,6 +128,7 @@ public fun MessageText(
position = position,
message = message,
onLinkClick = onLinkClick,
onMentionClick = onMentionClick,
onUserMentionClick = onUserMentionClick,
fallback = { url ->
context.startActivity(Intent(Intent.ACTION_VIEW, url.toUri()))
Expand Down Expand Up @@ -228,8 +235,17 @@ private suspend fun AwaitPointerEventScope.consumeUntilUp() {
* Whether this annotation range carries one of the interactive tags handled by [MessageText]:
* URL, email, or mention.
*/
internal fun AnnotatedString.Range<String>.isInteractiveTag(): Boolean =
tag == AnnotationTagUrl || tag == AnnotationTagEmail || tag == AnnotationTagMention
internal fun AnnotatedString.Range<String>.isInteractiveTag(): Boolean = when (tag) {
AnnotationTagUrl,
AnnotationTagEmail,
AnnotationTagUserMention,
AnnotationTagChannelMention,
AnnotationTagHereMention,
AnnotationTagRoleMention,
AnnotationTagGroupMention,
-> true
else -> false
}

/**
* Whether any annotation in the list both has an interactive tag and covers [offset]. Uses
Expand All @@ -240,10 +256,10 @@ internal fun List<AnnotatedString.Range<String>>.hasInteractiveAt(offset: Int):

/**
* Resolves the interactive annotation at the given character [position] and dispatches the right
* handler. Mention annotations route to [onUserMentionClick] after resolving the username against
* [Message.mentionedUsers]; URL/email annotations route to [onLinkClick] when set, otherwise to
* [fallback]. Annotations with empty items, non-interactive tags, or no match at [position] are
* ignored.
* handler. Mention annotations route to [onMentionClick]; user mentions additionally fire
* [onUserMentionClick] for backward compatibility. URL/email annotations route to [onLinkClick]
* when set, otherwise to [fallback]. Annotations with empty items, non-interactive
* tags, or no match at [position] are ignored.
*/
@Suppress("LongParameterList")
internal fun handleAnnotationClick(
Expand All @@ -253,13 +269,23 @@ internal fun handleAnnotationClick(
onLinkClick: ((Message, String) -> Unit)?,
onUserMentionClick: (User) -> Unit,
fallback: (String) -> Unit,
onMentionClick: (Mention) -> Unit = {},
) {
val annotation = annotations.firstOrNull {
it.isInteractiveTag() && position in it.start until it.end
} ?: return
when (annotation.tag) {
AnnotationTagMention -> {
message.mentionedUsers.getUserByNameOrId(annotation.item)?.let(onUserMentionClick)
AnnotationTagUserMention -> {
val user = message.mentionedUsers.getUserByNameOrId(annotation.item) ?: return
onMentionClick(Mention.User(user))
onUserMentionClick(user)
}
AnnotationTagChannelMention -> onMentionClick(Mention.Channel)
AnnotationTagHereMention -> onMentionClick(Mention.Here)
AnnotationTagRoleMention -> onMentionClick(Mention.Role(annotation.item))
AnnotationTagGroupMention -> {
message.mentionedGroups.find { it.name == annotation.item }
?.let { onMentionClick(Mention.Group(it)) }
}
AnnotationTagUrl, AnnotationTagEmail -> {
val url = annotation.item
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ import io.getstream.chat.android.models.Option
import io.getstream.chat.android.models.Poll
import io.getstream.chat.android.models.User
import io.getstream.chat.android.models.Vote
import io.getstream.chat.android.ui.common.feature.messages.composer.mention.Mention
import io.getstream.chat.android.ui.common.feature.messages.translations.MessageOriginalTranslationsStore
import io.getstream.chat.android.ui.common.state.messages.list.GiphyAction
import io.getstream.chat.android.ui.common.state.messages.list.MessageFocused
Expand Down Expand Up @@ -170,6 +171,7 @@ public fun MessageContainer(
onUserMentionClick: (User) -> Unit = {},
onReply: (Message) -> Unit = {},
onMediaGalleryPreviewResult: (MediaGalleryPreviewResult?) -> Unit = {},
onMentionClick: (Mention) -> Unit = {},
) {
val message = messageItem.message
val focusState = messageItem.focusState
Expand Down Expand Up @@ -301,6 +303,7 @@ public fun MessageContainer(
onQuotedMessageClick = onQuotedMessageClick,
onLinkClick = onLinkClick,
onUserMentionClick = onUserMentionClick,
onMentionClick = onMentionClick,
onPollUpdated = onPollUpdated,
onCastVote = onCastVote,
onRemoveVote = onRemoveVote,
Expand Down Expand Up @@ -641,6 +644,7 @@ public fun DefaultMessageContent(
onAddAnswer: (message: Message, poll: Poll, answer: String) -> Unit,
onClosePoll: (String) -> Unit,
onAddPollOption: (poll: Poll, option: String) -> Unit,
onMentionClick: (Mention) -> Unit = {},
) {
val finalModifier = modifier.widthIn(max = 264.dp)
if (messageItem.message.isPoll() && !messageItem.message.isDeleted()) {
Expand Down Expand Up @@ -681,6 +685,7 @@ public fun DefaultMessageContent(
onQuotedMessageClick = onQuotedMessageClick,
onLinkClick = onLinkClick,
onUserMentionClick = onUserMentionClick,
onMentionClick = onMentionClick,
)
}
}
Expand Down Expand Up @@ -759,6 +764,7 @@ public fun RegularMessageContent(
onLinkClick: ((Message, String) -> Unit)? = null,
onUserMentionClick: (User) -> Unit = {},
onMediaGalleryPreviewResult: (MediaGalleryPreviewResult?) -> Unit = {},
onMentionClick: (Mention) -> Unit = {},
) {
val message = messageItem.message
val ownsMessage = messageItem.isMine
Expand All @@ -778,6 +784,7 @@ public fun RegularMessageContent(
onQuotedMessageClick = onQuotedMessageClick,
onLinkClick = onLinkClick,
onUserMentionClick = onUserMentionClick,
onMentionClick = onMentionClick,
)
}
if (!messageItem.isErrorOrFailed()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import io.getstream.chat.android.models.Poll
import io.getstream.chat.android.models.User
import io.getstream.chat.android.models.Vote
import io.getstream.chat.android.previewdata.PreviewUserData
import io.getstream.chat.android.ui.common.feature.messages.composer.mention.Mention
import io.getstream.chat.android.ui.common.state.messages.list.DateSeparatorItemState
import io.getstream.chat.android.ui.common.state.messages.list.EmptyThreadPlaceholderItemState
import io.getstream.chat.android.ui.common.state.messages.list.GiphyAction
Expand Down Expand Up @@ -133,6 +134,7 @@ public fun LazyItemScope.MessageItem(
onMediaGalleryPreviewResult: (MediaGalleryPreviewResult?) -> Unit = {},
onUserMentionClick: (User) -> Unit = {},
onReply: (Message) -> Unit = {},
onMentionClick: (Mention) -> Unit = {},
) {
with(ChatTheme.componentFactory) {
when (messageListItemState) {
Expand Down Expand Up @@ -188,6 +190,7 @@ public fun LazyItemScope.MessageItem(
onUserAvatarClick = onUserAvatarClick,
onMessageLinkClick = onLinkClick,
onUserMentionClick = onUserMentionClick,
onMentionClick = onMentionClick,
onAddAnswer = onAddAnswer,
onReply = onReply,
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import io.getstream.chat.android.models.Option
import io.getstream.chat.android.models.Poll
import io.getstream.chat.android.models.User
import io.getstream.chat.android.models.Vote
import io.getstream.chat.android.ui.common.feature.messages.composer.mention.Mention
import io.getstream.chat.android.ui.common.state.messages.list.GiphyAction
import io.getstream.chat.android.ui.common.state.messages.list.MessageListItemState
import io.getstream.chat.android.ui.common.state.messages.list.MessageListState
Expand Down Expand Up @@ -205,6 +206,7 @@ internal fun LazyItemScope.DefaultMessageItem(
onLinkClick: ((Message, String) -> Unit)? = null,
onUserMentionClick: (User) -> Unit = {},
onReply: (Message) -> Unit = {},
onMentionClick: (Mention) -> Unit = {},
) {
MessageItem(
messageListItemState = messageListItemState,
Expand All @@ -223,6 +225,7 @@ internal fun LazyItemScope.DefaultMessageItem(
onUserAvatarClick = onUserAvatarClick,
onLinkClick = onLinkClick,
onUserMentionClick = onUserMentionClick,
onMentionClick = onMentionClick,
onAddAnswer = onAddAnswer,
onReply = onReply,
)
Expand Down
Loading
Loading