feat: masquerade support
This commit is contained in:
parent
fcddb8a968
commit
9017fc52a5
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M10.59,13.41C11,13.8 11,14.44 10.59,14.83C10.2,15.22 9.56,15.22 9.17,14.83C7.22,12.88 7.22,9.71 9.17,7.76V7.76L12.71,4.22C14.66,2.27 17.83,2.27 19.78,4.22C21.73,6.17 21.73,9.34 19.78,11.29L18.29,12.78C18.3,11.96 18.17,11.14 17.89,10.36L18.36,9.88C19.54,8.71 19.54,6.81 18.36,5.64C17.19,4.46 15.29,4.46 14.12,5.64L10.59,9.17C9.41,10.34 9.41,12.24 10.59,13.41M13.41,9.17C13.8,8.78 14.44,8.78 14.83,9.17C16.78,11.12 16.78,14.29 14.83,16.24V16.24L11.29,19.78C9.34,21.73 6.17,21.73 4.22,19.78C2.27,17.83 2.27,14.66 4.22,12.71L5.71,11.22C5.7,12.04 5.83,12.86 6.11,13.65L5.64,14.12C4.46,15.29 4.46,17.19 5.64,18.36C6.81,19.54 8.71,19.54 9.88,18.36L13.41,14.83C14.59,13.66 14.59,11.76 13.41,10.59C13,10.2 13,9.56 13.41,9.17Z"
|
||||
android:fillColor="#ffffff" />
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12,2A2,2 0 0,1 14,4C14,4.74 13.6,5.39 13,5.73V7H14A7,7 0 0,1 21,14H22A1,1 0 0,1 23,15V18A1,1 0 0,1 22,19H21V20A2,2 0 0,1 19,22H5A2,2 0 0,1 3,20V19H2A1,1 0 0,1 1,18V15A1,1 0 0,1 2,14H3A7,7 0 0,1 10,7H11V5.73C10.4,5.39 10,4.74 10,4A2,2 0 0,1 12,2M7.5,13A2.5,2.5 0 0,0 5,15.5A2.5,2.5 0 0,0 7.5,18A2.5,2.5 0 0,0 10,15.5A2.5,2.5 0 0,0 7.5,13M16.5,13A2.5,2.5 0 0,0 14,15.5A2.5,2.5 0 0,0 16.5,18A2.5,2.5 0 0,0 19,15.5A2.5,2.5 0 0,0 16.5,13Z"
|
||||
android:fillColor="#ffffff" />
|
||||
</vector>
|
||||
|
|
@ -70,7 +70,9 @@
|
|||
<string name="send_alt">Send</string>
|
||||
<string name="add_attachment_alt">Add attachment</string>
|
||||
<string name="remove_attachment_alt">Remove attachment</string>
|
||||
<string name="show_more_alt">Show more</string>
|
||||
|
||||
<string name="badge_bot_alt">Bot</string>
|
||||
<string name="badge_masquerade_alt">From linked channel</string>
|
||||
|
||||
<string name="tutorial">Welcome to Revolt\'s in-progress Android experience!</string>
|
||||
<string name="select_channel">Select a server and channel by swiping from the left.</string>
|
||||
|
|
|
|||
Loading…
Reference in New Issue