feat: role colours in chat
Signed-off-by: Infi <wingit@geist.ga>
This commit is contained in:
parent
dace8da8a6
commit
813b29fecd
|
|
@ -0,0 +1,36 @@
|
|||
package chat.revolt.api.internals
|
||||
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.schemas.Role
|
||||
|
||||
object Roles {
|
||||
// lowest rank = highest role
|
||||
private fun resolveHighestRole(roles: List<Role?>): Role? {
|
||||
return roles.minByOrNull { role ->
|
||||
role?.rank ?: 0.0
|
||||
}
|
||||
}
|
||||
|
||||
private fun highestRoleWithColour(roles: List<Role?>): Role? {
|
||||
return roles.filter { role ->
|
||||
role?.colour != null
|
||||
}.minByOrNull { role ->
|
||||
role?.rank ?: 0.0
|
||||
}
|
||||
}
|
||||
|
||||
fun resolveHighestRole(serverId: String, userId: String, withColour: Boolean = false): Role? {
|
||||
val server = RevoltAPI.serverCache[serverId] ?: return null
|
||||
val member = RevoltAPI.members.getMember(serverId, userId) ?: return null
|
||||
|
||||
val roles = member.roles?.map { roleId ->
|
||||
server.roles?.get(roleId)
|
||||
} ?: return null
|
||||
|
||||
return if (withColour) {
|
||||
highestRoleWithColour(roles)
|
||||
} else {
|
||||
resolveHighestRole(roles)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,19 @@ fun Brush.Companion.solidColor(colour: Color) = linearGradient(
|
|||
)
|
||||
)
|
||||
|
||||
// Some colours that are not present in Android's built-in list.
|
||||
// not exhaustive, but covers most of the ones I've seen in the wild
|
||||
// for the sake of all of us, please just use hex codes
|
||||
// reference: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
|
||||
private val ADDITIONAL_WEB_COLOURS = mapOf(
|
||||
"orange" to Color(0xFFFFA500),
|
||||
"rebeccapurple" to Color(0xFF663399),
|
||||
"transparent" to Color.Transparent,
|
||||
"inherit" to Color.Unspecified,
|
||||
"initial" to Color.Unspecified,
|
||||
"unset" to Color.Unspecified,
|
||||
)
|
||||
|
||||
object WebCompat {
|
||||
@Composable
|
||||
private fun parseLinearGradient(gradient: String): Brush {
|
||||
|
|
@ -59,15 +72,7 @@ object WebCompat {
|
|||
)
|
||||
}
|
||||
|
||||
else -> parseFunctionColour(colourPart) ?: try {
|
||||
Color(android.graphics.Color.parseColor(colourPart))
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Log.d(
|
||||
"WebCompat",
|
||||
"Failed to parse colour $colourPart in $gradient, falling back to LocalContentColor.current"
|
||||
)
|
||||
LocalContentColor.current
|
||||
}
|
||||
else -> parseFunctionColour(colourPart) ?: parseColourName(colourPart)
|
||||
}
|
||||
|
||||
val stop = if (splitPart.size == 2) {
|
||||
|
|
@ -149,6 +154,28 @@ object WebCompat {
|
|||
return Brush.solidColor(parseVarToColour(varName))
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun parseColourName(colour: String): Color {
|
||||
return try {
|
||||
val additionalWebColour = ADDITIONAL_WEB_COLOURS[colour]
|
||||
if (additionalWebColour != null) {
|
||||
Log.d(
|
||||
"WebCompat",
|
||||
"Parsed additional web colour $colour to $additionalWebColour"
|
||||
)
|
||||
return additionalWebColour
|
||||
}
|
||||
|
||||
Color(android.graphics.Color.parseColor(colour))
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Log.d(
|
||||
"WebCompat",
|
||||
"Failed to parse colour $colour, falling back to LocalContentColor.current"
|
||||
)
|
||||
LocalContentColor.current
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun parseColour(colour: String): Brush {
|
||||
when {
|
||||
|
|
@ -172,15 +199,7 @@ object WebCompat {
|
|||
}
|
||||
|
||||
else -> {
|
||||
return try {
|
||||
Brush.solidColor(Color(android.graphics.Color.parseColor(colour)))
|
||||
} catch (e: IllegalArgumentException) {
|
||||
Log.d(
|
||||
"WebCompat",
|
||||
"Failed to parse colour $colour, falling back to LocalContentColor.current"
|
||||
)
|
||||
Brush.solidColor(LocalContentColor.current)
|
||||
}
|
||||
return Brush.solidColor(parseColourName(colour))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ fun InReplyTo(
|
|||
?: stringResource(id = R.string.unknown)
|
||||
|
||||
val contentColor = LocalContentColor.current
|
||||
val usernameColor = message?.let { authorColour(it) } ?: Brush.solidColor(contentColor)
|
||||
val usernameColor =
|
||||
message?.let { authorColour(it) } ?: Brush.solidColor(contentColor)
|
||||
|
||||
Box(
|
||||
modifier = modifier
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
|
|
@ -50,6 +49,7 @@ import chat.revolt.activities.media.ImageViewActivity
|
|||
import chat.revolt.activities.media.VideoViewActivity
|
||||
import chat.revolt.api.REVOLT_FILES
|
||||
import chat.revolt.api.RevoltAPI
|
||||
import chat.revolt.api.internals.Roles
|
||||
import chat.revolt.api.internals.SpecialUsers
|
||||
import chat.revolt.api.internals.ULID
|
||||
import chat.revolt.api.internals.WebCompat
|
||||
|
|
@ -66,7 +66,16 @@ fun authorColour(message: MessageSchema): Brush {
|
|||
return if (message.masquerade?.colour != null) {
|
||||
WebCompat.parseColour(message.masquerade.colour)
|
||||
} else {
|
||||
Brush.solidColor(LocalContentColor.current)
|
||||
val defaultColour = Brush.solidColor(LocalContentColor.current)
|
||||
|
||||
val serverId = RevoltAPI.channelCache[message.channel]?.server ?: return defaultColour
|
||||
|
||||
val highestRole = message.author?.let {
|
||||
Roles.resolveHighestRole(serverId, it, withColour = true)
|
||||
} ?: return defaultColour
|
||||
|
||||
highestRole.colour?.let { WebCompat.parseColour(it) }
|
||||
?: defaultColour
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +180,7 @@ fun Message(
|
|||
replyMessage.author
|
||||
)
|
||||
}
|
||||
?: false,
|
||||
?: false
|
||||
) {
|
||||
// TODO Add jump to message
|
||||
if (replyMessage == null) {
|
||||
|
|
@ -218,12 +227,7 @@ fun Message(
|
|||
text = authorName(message),
|
||||
style = LocalTextStyle.current.copy(
|
||||
fontWeight = FontWeight.Bold,
|
||||
brush = if (message.author == RevoltAPI.selfId) Brush.horizontalGradient(
|
||||
listOf(
|
||||
Color.Magenta,
|
||||
Color.Cyan,
|
||||
),
|
||||
) else authorColour(message),
|
||||
brush = authorColour(message),
|
||||
),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
|
|
|
|||
Loading…
Reference in New Issue