From ae87815dca5ecbde01b626b2e2d85f4e37442275 Mon Sep 17 00:00:00 2001 From: Infi Date: Fri, 1 Dec 2023 15:52:45 +0100 Subject: [PATCH] feat: mention user on username tap Signed-off-by: Infi --- .../revolt/api/internals/MessageProcessor.kt | 22 +++++++++++++++++++ .../chat/revolt/components/chat/Message.kt | 15 +++++++++++-- .../chat/views/channel/ChannelScreen.kt | 5 +++++ .../views/channel/ChannelScreenViewModel.kt | 3 ++- 4 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/chat/revolt/api/internals/MessageProcessor.kt diff --git a/app/src/main/java/chat/revolt/api/internals/MessageProcessor.kt b/app/src/main/java/chat/revolt/api/internals/MessageProcessor.kt new file mode 100644 index 00000000..36cb909d --- /dev/null +++ b/app/src/main/java/chat/revolt/api/internals/MessageProcessor.kt @@ -0,0 +1,22 @@ +package chat.revolt.api.internals + +import chat.revolt.api.RevoltAPI + +object MessageProcessor { + private val MentionRegex = Regex("@((?:\\p{L}|[\\d_.-])+)#([0-9]{4})", RegexOption.IGNORE_CASE) + + fun processOutgoing(content: String): String { + val mentions = MentionRegex.findAll(content).map { it.value }.toList() + + return mentions.fold(content) { acc, mention -> + val (username, discriminator) = MentionRegex.matchEntire(mention)?.destructured + ?: return@fold acc + + val user = + RevoltAPI.userCache.values.find { it.username == username && it.discriminator == discriminator } + + val userId = user?.id ?: return@fold acc + acc.replace(mention, "<@$userId>") + } + } +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/components/chat/Message.kt b/app/src/main/java/chat/revolt/components/chat/Message.kt index fca45a6b..f3315164 100644 --- a/app/src/main/java/chat/revolt/components/chat/Message.kt +++ b/app/src/main/java/chat/revolt/components/chat/Message.kt @@ -64,11 +64,11 @@ import chat.revolt.api.internals.WebCompat import chat.revolt.api.internals.solidColor import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl import chat.revolt.api.schemas.AutumnResource -import chat.revolt.api.schemas.Message as MessageSchema import chat.revolt.api.schemas.User import chat.revolt.components.generic.UserAvatar import chat.revolt.components.generic.UserAvatarWidthPlaceholder import chat.revolt.internals.markdown.LongClickableSpan +import chat.revolt.api.schemas.Message as MessageSchema @Composable fun authorColour(message: MessageSchema): Brush { @@ -163,6 +163,7 @@ fun Message( parse: (MessageSchema) -> SpannableStringBuilder = { SpannableStringBuilder(it.content) }, onMessageContextMenu: () -> Unit = {}, onAvatarClick: () -> Unit = {}, + onNameClick: (() -> Unit)? = null, canReply: Boolean = false, onReply: () -> Unit = {} ) { @@ -252,7 +253,17 @@ fun Message( brush = authorColour(message) ), maxLines = 1, - overflow = TextOverflow.Ellipsis + overflow = TextOverflow.Ellipsis, + modifier = Modifier.then( + if (onNameClick != null) + Modifier.combinedClickable( + onClick = onNameClick, + onLongClick = { + onMessageContextMenu() + } + ) + else Modifier + ) ) InlineBadges( diff --git a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt index 0bcedd1d..52bab3c1 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreen.kt @@ -347,6 +347,11 @@ fun ChannelScreen( onUserSheetOpenFor(author, channel?.server) } }, + onNameClick = { + val author = message.author?.let { RevoltAPI.userCache[it] } + ?: return@Message + viewModel.putAtCursorPosition("@${author.username}#${author.discriminator}") + }, canReply = true, onReply = { if (viewModel.pendingReplies.size >= 5) { diff --git a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt index 63ad68e4..706bf78b 100644 --- a/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt +++ b/app/src/main/java/chat/revolt/screens/chat/views/channel/ChannelScreenViewModel.kt @@ -14,6 +14,7 @@ import chat.revolt.R import chat.revolt.api.RevoltAPI import chat.revolt.api.RevoltJson import chat.revolt.api.internals.ChannelUtils +import chat.revolt.api.internals.MessageProcessor import chat.revolt.api.internals.PermissionBit import chat.revolt.api.internals.Roles import chat.revolt.api.internals.SpecialUsers @@ -211,7 +212,7 @@ class ChannelScreenViewModel : ViewModel() { sendMessage( activeChannel!!.id!!, - pendingMessageContent.trimIndent(), + MessageProcessor.processOutgoing(pendingMessageContent.trimIndent()), attachments = if (attachmentIds.isEmpty()) null else attachmentIds, replies = pendingReplies )