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 e89eb652..a22a0590 100644 --- a/app/src/main/java/chat/revolt/components/chat/Message.kt +++ b/app/src/main/java/chat/revolt/components/chat/Message.kt @@ -5,7 +5,6 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -19,12 +18,12 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import chat.revolt.api.REVOLT_BASE import chat.revolt.api.REVOLT_FILES import chat.revolt.api.RevoltAPI import chat.revolt.api.internals.ULID import chat.revolt.api.schemas.AutumnResource import chat.revolt.components.generic.RemoteImage +import chat.revolt.components.generic.UserAvatar import chat.revolt.markdown.Renderer import chat.revolt.api.schemas.Message as MessageSchema @@ -54,38 +53,28 @@ fun Message( val author = RevoltAPI.userCache[message.author] ?: return CircularProgressIndicator() val context = LocalContext.current - Row(modifier = Modifier - .padding(8.dp) - .fillMaxWidth()) { - if (author.avatar != null) { - RemoteImage( - url = "$REVOLT_FILES/avatars/${author.avatar.id!!}/user.png", - modifier = Modifier - .size(50.dp) - .clip(CircleShape), - description = "Avatar for ${author.username}" - ) - } else { - RemoteImage( - url = "$REVOLT_BASE/users/${author.id}/default_avatar", - modifier = Modifier - .size(50.dp) - .clip(CircleShape), - description = "Avatar for ${author.username}" - ) - } + Row( + modifier = Modifier + .padding(8.dp) + .fillMaxWidth() + ) { + UserAvatar( + username = author.username ?: "", + userId = author.id!!, + avatar = author.avatar + ) Column(modifier = Modifier.padding(start = 10.dp)) { Row(verticalAlignment = Alignment.CenterVertically) { - author.username?.let { - Text( - text = it, - fontWeight = FontWeight.Bold, - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } + Text( + text = author.username ?: "", + fontWeight = FontWeight.Bold, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Spacer(modifier = Modifier.width(5.dp)) + Text( text = formatLongAsTime(ULID.asTimestamp(message.id!!)), fontSize = 12.sp, diff --git a/app/src/main/java/chat/revolt/components/generic/UserAvatar.kt b/app/src/main/java/chat/revolt/components/generic/UserAvatar.kt new file mode 100644 index 00000000..6b2590fd --- /dev/null +++ b/app/src/main/java/chat/revolt/components/generic/UserAvatar.kt @@ -0,0 +1,87 @@ +package chat.revolt.components.generic + +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import chat.revolt.R +import chat.revolt.api.REVOLT_BASE +import chat.revolt.api.REVOLT_FILES +import chat.revolt.api.schemas.AutumnResource + +enum class Presence { + Online, + Idle, + Dnd, + Focus, + Offline, +} + +fun presenceColour(presence: Presence): Color { + return when (presence) { + Presence.Online -> Color(0xff73b258) + Presence.Idle -> Color(0xffecc73c) + Presence.Dnd -> Color(0xffd24c41) + Presence.Focus -> Color(0xff69a2ef) + Presence.Offline -> Color(0xff546e7a) + } +} + +@Composable +fun PresenceBadge(presence: Presence) { + Box( + modifier = Modifier + .size(16.dp) + .clip(CircleShape) + .border(2.dp, MaterialTheme.colorScheme.background, CircleShape) + .background(presenceColour(presence)) + ) +} + +@Composable +fun UserAvatar( + username: String, + userId: String, + modifier: Modifier = Modifier, + presence: Presence? = null, + avatar: AutumnResource? = null, +) { + Box( + modifier = modifier + .size(40.dp), + contentAlignment = Alignment.BottomEnd + ) { + if (avatar != null) { + RemoteImage( + url = "$REVOLT_FILES/avatars/${avatar.id!!}/user.png", + description = stringResource(id = R.string.avatar_alt, username), + contentScale = ContentScale.Crop, + modifier = Modifier + .clip(CircleShape) + .size(40.dp) + ) + } else { + RemoteImage( + url = "$REVOLT_BASE/users/${userId}/default_avatar", + modifier = Modifier + .size(40.dp) + .clip(CircleShape), + description = stringResource(id = R.string.avatar_alt, username), + ) + } + + if (presence != null) { + PresenceBadge(presence) + } + } +} \ No newline at end of file