From 9017fc52a5793dd0887d3bc80d10a75c54644ca4 Mon Sep 17 00:00:00 2001 From: Infi Date: Sun, 5 Feb 2023 19:22:41 +0100 Subject: [PATCH] feat: masquerade support --- .../main/java/chat/revolt/api/RevoltAPI.kt | 5 +++ .../chat/revolt/api/internals/WebCompat.kt | 32 +++++++++++++++ .../chat/revolt/components/chat/InReplyTo.kt | 21 ++++++++-- .../revolt/components/chat/InlineBadge.kt | 40 +++++++++++++++++++ .../chat/revolt/components/chat/Message.kt | 35 +++++++++------- .../revolt/components/generic/UserAvatar.kt | 3 +- .../res/drawable/ic_link_variant_24dp.xml | 9 +++++ app/src/main/res/drawable/ic_robot_24dp.xml | 9 +++++ app/src/main/res/values/strings.xml | 4 +- 9 files changed, 137 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/chat/revolt/api/internals/WebCompat.kt create mode 100644 app/src/main/java/chat/revolt/components/chat/InlineBadge.kt create mode 100644 app/src/main/res/drawable/ic_link_variant_24dp.xml create mode 100644 app/src/main/res/drawable/ic_robot_24dp.xml diff --git a/app/src/main/java/chat/revolt/api/RevoltAPI.kt b/app/src/main/java/chat/revolt/api/RevoltAPI.kt index eaad8bfc..8d72f6ea 100644 --- a/app/src/main/java/chat/revolt/api/RevoltAPI.kt +++ b/app/src/main/java/chat/revolt/api/RevoltAPI.kt @@ -23,8 +23,13 @@ const val REVOLT_BASE = "https://api.revolt.chat" const val REVOLT_SUPPORT = "https://support.revolt.chat" const val REVOLT_MARKETING = "https://revolt.chat" const val REVOLT_FILES = "https://autumn.revolt.chat" +const val REVOLT_JANUARY = "https://jan.revolt.chat" const val REVOLT_WEBSOCKET = "wss://ws.revolt.chat" +fun asJanuaryProxyUrl(url: String): String { + return "$REVOLT_JANUARY/proxy?url=${url}" +} + private const val BACKEND_IS_STABLE = false val RevoltJson = Json { ignoreUnknownKeys = true } diff --git a/app/src/main/java/chat/revolt/api/internals/WebCompat.kt b/app/src/main/java/chat/revolt/api/internals/WebCompat.kt new file mode 100644 index 00000000..ecdcc8ce --- /dev/null +++ b/app/src/main/java/chat/revolt/api/internals/WebCompat.kt @@ -0,0 +1,32 @@ +package chat.revolt.api.internals + +import android.util.Log +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +object WebCompat { + @Composable + fun parseColour(colour: String): Color { + if (colour.startsWith("var(")) { + return when (colour.substringAfter("var(").substringBefore(")")) { + "accent" -> MaterialTheme.colorScheme.primary + "foreground" -> MaterialTheme.colorScheme.onBackground + "background" -> MaterialTheme.colorScheme.background + "error" -> MaterialTheme.colorScheme.error + else -> LocalContentColor.current + } + } else { + try { + return Color(android.graphics.Color.parseColor(colour)) + } catch (e: IllegalArgumentException) { + Log.d( + "WebCompat", + "Failed to parse colour $colour, falling back to LocalContentColor.current" + ) + return LocalContentColor.current + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/components/chat/InReplyTo.kt b/app/src/main/java/chat/revolt/components/chat/InReplyTo.kt index fe956e46..cc06dfb8 100644 --- a/app/src/main/java/chat/revolt/components/chat/InReplyTo.kt +++ b/app/src/main/java/chat/revolt/components/chat/InReplyTo.kt @@ -15,6 +15,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.revolt.R import chat.revolt.api.RevoltAPI +import chat.revolt.api.asJanuaryProxyUrl import chat.revolt.components.generic.UserAvatar @Composable @@ -27,6 +28,8 @@ fun InReplyTo( val message = RevoltAPI.messageCache[messageId] val author = RevoltAPI.userCache[message?.author ?: ""] + val username = message?.masquerade?.name ?: author?.username ?: "" + Row( modifier = modifier .fillMaxWidth() @@ -38,22 +41,23 @@ fun InReplyTo( if (message != null) { UserAvatar( - username = author?.username ?: "", + username = username, userId = author?.id ?: "", avatar = author?.avatar, + rawUrl = message.masquerade?.avatar?.let { asJanuaryProxyUrl(it) }, size = 16.dp ) Text( text = if (author != null) { if (withMention) { - "@${author.username}" + "@$username" } else { - author.username + username } } else { stringResource(id = R.string.unknown) - } ?: stringResource(id = R.string.unknown), + }, fontWeight = FontWeight.Bold, fontSize = 12.sp, color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.9f), @@ -62,6 +66,15 @@ fun InReplyTo( modifier = Modifier.padding(horizontal = 4.dp) ) + if (message.masquerade != null && author?.bot != null) { + InlineBadge( + badge = InlineBadge.Masquerade, + colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f), + modifier = Modifier.size(8.dp) + ) + Spacer(modifier = Modifier.width(4.dp)) + } + Text( text = message.content ?: "", fontSize = 12.sp, diff --git a/app/src/main/java/chat/revolt/components/chat/InlineBadge.kt b/app/src/main/java/chat/revolt/components/chat/InlineBadge.kt new file mode 100644 index 00000000..99b6ee0a --- /dev/null +++ b/app/src/main/java/chat/revolt/components/chat/InlineBadge.kt @@ -0,0 +1,40 @@ +package chat.revolt.components.chat + +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import chat.revolt.R + +enum class InlineBadge { + Bot, + Masquerade, + PlatformModeration, + Developer +} + +@Composable +fun InlineBadge( + badge: InlineBadge, + modifier: Modifier = Modifier, + colour: Color = Color.Unspecified, +) { + when (badge) { + InlineBadge.Bot -> Icon( + painter = painterResource(id = R.drawable.ic_robot_24dp), + contentDescription = stringResource(id = R.string.badge_bot_alt), + tint = colour, + modifier = modifier + ) + InlineBadge.Masquerade -> Icon( + painter = painterResource(id = R.drawable.ic_link_variant_24dp), + contentDescription = stringResource(id = R.string.badge_masquerade_alt), + tint = colour, + modifier = modifier + ) + InlineBadge.PlatformModeration -> TODO() + InlineBadge.Developer -> TODO() + } +} \ 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 b1f9466d..2adfcee5 100644 --- a/app/src/main/java/chat/revolt/components/chat/Message.kt +++ b/app/src/main/java/chat/revolt/components/chat/Message.kt @@ -3,14 +3,9 @@ package chat.revolt.components.chat import android.net.Uri import android.widget.Toast import androidx.browser.customtabs.CustomTabsIntent -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable -import androidx.compose.foundation.combinedClickable +import androidx.compose.foundation.* import androidx.compose.foundation.layout.* -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text +import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -26,7 +21,9 @@ import androidx.compose.ui.unit.sp import chat.revolt.R import chat.revolt.api.REVOLT_FILES import chat.revolt.api.RevoltAPI +import chat.revolt.api.asJanuaryProxyUrl import chat.revolt.api.internals.ULID +import chat.revolt.api.internals.WebCompat import chat.revolt.api.schemas.AutumnResource import chat.revolt.components.generic.RemoteImage import chat.revolt.components.generic.UserAvatar @@ -50,12 +47,6 @@ fun formatLongAsTime(time: Long): String { val format = java.text.SimpleDateFormat("dd.MM.yyyy HH:mm:ss", java.util.Locale.getDefault()) - // EQUIVALENT CODE WITH kotlinx.datetime: - - // val date = Instant.fromEpochMilliseconds(time) - // val format = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss") - - return format.format(date) } @@ -109,7 +100,8 @@ fun Message( UserAvatar( username = author.username ?: "", userId = author.id!!, - avatar = author.avatar + avatar = author.avatar, + rawUrl = message.masquerade?.avatar?.let { asJanuaryProxyUrl(it) } ) } else { UserAvatarWidthPlaceholder() @@ -119,12 +111,25 @@ fun Message( if (message.tail == false) { Row(verticalAlignment = Alignment.CenterVertically) { Text( - text = author.username ?: "", + text = message.masquerade?.name ?: author.username ?: "", fontWeight = FontWeight.Bold, + color = if (message.masquerade?.colour != null) { + WebCompat.parseColour(message.masquerade.colour) + } else LocalContentColor.current, maxLines = 1, overflow = TextOverflow.Ellipsis ) + if (message.masquerade != null && author.bot != null) { + Spacer(modifier = Modifier.width(5.dp)) + + InlineBadge( + badge = InlineBadge.Masquerade, + colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f), + modifier = Modifier.size(16.dp) + ) + } + Spacer(modifier = Modifier.width(5.dp)) Text( diff --git a/app/src/main/java/chat/revolt/components/generic/UserAvatar.kt b/app/src/main/java/chat/revolt/components/generic/UserAvatar.kt index 61a113ef..2cd24ad8 100644 --- a/app/src/main/java/chat/revolt/components/generic/UserAvatar.kt +++ b/app/src/main/java/chat/revolt/components/generic/UserAvatar.kt @@ -57,6 +57,7 @@ fun UserAvatar( modifier: Modifier = Modifier, presence: Presence? = null, avatar: AutumnResource? = null, + rawUrl: String? = null, size: Dp = 40.dp, presenceSize: Dp = 16.dp, ) { @@ -67,7 +68,7 @@ fun UserAvatar( ) { if (avatar != null) { RemoteImage( - url = "$REVOLT_FILES/avatars/${avatar.id!!}/user.png", + url = rawUrl ?: "$REVOLT_FILES/avatars/${avatar.id!!}/user.png", description = stringResource(id = R.string.avatar_alt, username), contentScale = ContentScale.Crop, modifier = Modifier diff --git a/app/src/main/res/drawable/ic_link_variant_24dp.xml b/app/src/main/res/drawable/ic_link_variant_24dp.xml new file mode 100644 index 00000000..db6947ab --- /dev/null +++ b/app/src/main/res/drawable/ic_link_variant_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_robot_24dp.xml b/app/src/main/res/drawable/ic_robot_24dp.xml new file mode 100644 index 00000000..3a862f18 --- /dev/null +++ b/app/src/main/res/drawable/ic_robot_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 906020c3..9f4ae91c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -70,7 +70,9 @@ Send Add attachment Remove attachment - Show more + + Bot + From linked channel Welcome to Revolt\'s in-progress Android experience! Select a server and channel by swiping from the left.