feat: mention user on username tap

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2023-12-01 15:52:45 +01:00
parent 9e3543be37
commit ae87815dca
4 changed files with 42 additions and 3 deletions

View File

@ -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>")
}
}
}

View File

@ -64,11 +64,11 @@ import chat.revolt.api.internals.WebCompat
import chat.revolt.api.internals.solidColor import chat.revolt.api.internals.solidColor
import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl import chat.revolt.api.routes.microservices.january.asJanuaryProxyUrl
import chat.revolt.api.schemas.AutumnResource import chat.revolt.api.schemas.AutumnResource
import chat.revolt.api.schemas.Message as MessageSchema
import chat.revolt.api.schemas.User import chat.revolt.api.schemas.User
import chat.revolt.components.generic.UserAvatar import chat.revolt.components.generic.UserAvatar
import chat.revolt.components.generic.UserAvatarWidthPlaceholder import chat.revolt.components.generic.UserAvatarWidthPlaceholder
import chat.revolt.internals.markdown.LongClickableSpan import chat.revolt.internals.markdown.LongClickableSpan
import chat.revolt.api.schemas.Message as MessageSchema
@Composable @Composable
fun authorColour(message: MessageSchema): Brush { fun authorColour(message: MessageSchema): Brush {
@ -163,6 +163,7 @@ fun Message(
parse: (MessageSchema) -> SpannableStringBuilder = { SpannableStringBuilder(it.content) }, parse: (MessageSchema) -> SpannableStringBuilder = { SpannableStringBuilder(it.content) },
onMessageContextMenu: () -> Unit = {}, onMessageContextMenu: () -> Unit = {},
onAvatarClick: () -> Unit = {}, onAvatarClick: () -> Unit = {},
onNameClick: (() -> Unit)? = null,
canReply: Boolean = false, canReply: Boolean = false,
onReply: () -> Unit = {} onReply: () -> Unit = {}
) { ) {
@ -252,7 +253,17 @@ fun Message(
brush = authorColour(message) brush = authorColour(message)
), ),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis,
modifier = Modifier.then(
if (onNameClick != null)
Modifier.combinedClickable(
onClick = onNameClick,
onLongClick = {
onMessageContextMenu()
}
)
else Modifier
)
) )
InlineBadges( InlineBadges(

View File

@ -347,6 +347,11 @@ fun ChannelScreen(
onUserSheetOpenFor(author, channel?.server) onUserSheetOpenFor(author, channel?.server)
} }
}, },
onNameClick = {
val author = message.author?.let { RevoltAPI.userCache[it] }
?: return@Message
viewModel.putAtCursorPosition("@${author.username}#${author.discriminator}")
},
canReply = true, canReply = true,
onReply = { onReply = {
if (viewModel.pendingReplies.size >= 5) { if (viewModel.pendingReplies.size >= 5) {

View File

@ -14,6 +14,7 @@ import chat.revolt.R
import chat.revolt.api.RevoltAPI import chat.revolt.api.RevoltAPI
import chat.revolt.api.RevoltJson import chat.revolt.api.RevoltJson
import chat.revolt.api.internals.ChannelUtils import chat.revolt.api.internals.ChannelUtils
import chat.revolt.api.internals.MessageProcessor
import chat.revolt.api.internals.PermissionBit import chat.revolt.api.internals.PermissionBit
import chat.revolt.api.internals.Roles import chat.revolt.api.internals.Roles
import chat.revolt.api.internals.SpecialUsers import chat.revolt.api.internals.SpecialUsers
@ -211,7 +212,7 @@ class ChannelScreenViewModel : ViewModel() {
sendMessage( sendMessage(
activeChannel!!.id!!, activeChannel!!.id!!,
pendingMessageContent.trimIndent(), MessageProcessor.processOutgoing(pendingMessageContent.trimIndent()),
attachments = if (attachmentIds.isEmpty()) null else attachmentIds, attachments = if (attachmentIds.isEmpty()) null else attachmentIds,
replies = pendingReplies replies = pendingReplies
) )