feat: redesign reply manager

This commit is contained in:
Infi 2023-02-16 21:46:01 +01:00
parent 2db44900ae
commit 2b83dd95ca
6 changed files with 173 additions and 36 deletions

View File

@ -66,14 +66,15 @@ fun InReplyTo(
modifier = Modifier.padding(horizontal = 4.dp) modifier = Modifier.padding(horizontal = 4.dp)
) )
if (message.masquerade != null && author?.bot != null) { InlineBadges(
InlineBadge( bot = message.masquerade == null && author?.bot != null,
badge = InlineBadge.Masquerade, masquerade = message.masquerade != null && author?.bot != null,
colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f), colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
modifier = Modifier.size(8.dp) modifier = Modifier.size(8.dp),
) followingIfAny = {
Spacer(modifier = Modifier.width(4.dp)) Spacer(modifier = Modifier.width(4.dp))
} }
)
Text( Text(
text = message.content ?: "", text = message.content ?: "",

View File

@ -1,5 +1,6 @@
package chat.revolt.components.chat package chat.revolt.components.chat
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -37,4 +38,55 @@ fun InlineBadge(
InlineBadge.PlatformModeration -> TODO() InlineBadge.PlatformModeration -> TODO()
InlineBadge.Developer -> TODO() InlineBadge.Developer -> TODO()
} }
}
@Composable
fun InlineBadges(
modifier: Modifier = Modifier,
bot: Boolean = false,
masquerade: Boolean = false,
platformModeration: Boolean = false,
developer: Boolean = false,
colour: Color = Color.Unspecified,
precedingIfAny: @Composable () -> Unit = {},
followingIfAny: @Composable () -> Unit = {},
) {
if (bot || masquerade || platformModeration || developer) {
precedingIfAny()
}
Row {
if (bot) {
InlineBadge(
badge = InlineBadge.Bot,
modifier = modifier,
colour = colour
)
}
if (masquerade) {
InlineBadge(
badge = InlineBadge.Masquerade,
modifier = modifier,
colour = colour
)
}
if (platformModeration) {
InlineBadge(
badge = InlineBadge.PlatformModeration,
modifier = modifier,
colour = colour
)
}
if (developer) {
InlineBadge(
badge = InlineBadge.Developer,
modifier = modifier,
colour = colour
)
}
}
if (bot || masquerade || platformModeration || developer) {
followingIfAny()
}
} }

View File

@ -107,15 +107,15 @@ fun Message(
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
if (message.masquerade != null && author.bot != null) { InlineBadges(
Spacer(modifier = Modifier.width(5.dp)) bot = author.bot != null && message.masquerade == null,
masquerade = message.masquerade != null && author.bot != null,
InlineBadge( colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
badge = InlineBadge.Masquerade, modifier = Modifier.size(16.dp),
colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f), precedingIfAny = {
modifier = Modifier.size(16.dp) Spacer(modifier = Modifier.width(5.dp))
) }
} )
Spacer(modifier = Modifier.width(5.dp)) Spacer(modifier = Modifier.width(5.dp))

View File

@ -3,21 +3,26 @@ package chat.revolt.components.screens.chat
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.Icon import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.res.stringResource
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.dp
import androidx.compose.ui.unit.sp
import chat.revolt.R
import chat.revolt.api.RevoltAPI
import chat.revolt.api.asJanuaryProxyUrl
import chat.revolt.api.internals.WebCompat
import chat.revolt.api.routes.channel.SendMessageReply import chat.revolt.api.routes.channel.SendMessageReply
import chat.revolt.components.chat.InReplyTo import chat.revolt.components.generic.UserAvatar
@Composable @Composable
fun ManageableReply( fun ManageableReply(
@ -25,29 +30,93 @@ fun ManageableReply(
onToggleMention: () -> Unit, onToggleMention: () -> Unit,
onRemove: () -> Unit, onRemove: () -> Unit,
) { ) {
// TODO Revamp this. Placeholder design ("functional" but extremely ugly) val replyMessage = RevoltAPI.messageCache[reply.id] ?: return onRemove()
val replyAuthor = RevoltAPI.userCache[replyMessage.author] ?: return onRemove()
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp)) .background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp))
.horizontalScroll(rememberScrollState()) .horizontalScroll(rememberScrollState())
.padding(horizontal = 8.dp, vertical = 4.dp) .padding(horizontal = 8.dp, vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically,
) { ) {
Icon( Icon(
imageVector = Icons.Default.Close, imageVector = Icons.Default.Close,
contentDescription = "Remove reply", contentDescription = stringResource(id = R.string.remove_reply_alt),
modifier = Modifier modifier = Modifier
.clip(MaterialTheme.shapes.small)
.clickable { .clickable {
onRemove() onRemove()
} }
.padding(4.dp)
.size(16.dp),
)
Spacer(modifier = Modifier.width(8.dp))
UserAvatar(
username = replyAuthor.username!!,
userId = replyAuthor.id!!,
avatar = replyAuthor.avatar,
rawUrl = replyMessage.masquerade?.avatar?.let { asJanuaryProxyUrl(it) },
size = 16.dp
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = replyMessage.masquerade?.name ?: replyAuthor.username,
fontSize = 12.sp,
modifier = Modifier
.clickable {
onToggleMention()
}
.padding(4.dp),
color = if (replyMessage.masquerade?.colour != null) {
WebCompat.parseColour(replyMessage.masquerade.colour)
} else LocalContentColor.current,
fontWeight = FontWeight.Bold,
)
Text(
text = if (replyMessage.content?.trim().isNullOrEmpty()) {
stringResource(id = R.string.reply_message_empty_has_attachments)
} else {
replyMessage.content!!
},
fontSize = 12.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier
.clickable {
onToggleMention()
}
.padding(4.dp)
.weight(1f)
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = if (reply.mention) {
stringResource(id = R.string.reply_mention_on)
} else {
stringResource(id = R.string.reply_mention_off)
},
modifier = Modifier
.clip(MaterialTheme.shapes.small)
.clickable {
onToggleMention()
}
.padding(4.dp),
color = if (reply.mention) {
MaterialTheme.colorScheme.primary
} else {
MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f)
},
fontWeight = FontWeight.Bold,
) )
InReplyTo(
messageId = reply.id,
withMention = reply.mention,
modifier = Modifier.weight(1f)
) {
onToggleMention()
}
} }
} }

View File

@ -84,13 +84,24 @@ fun RevoltTheme(
else -> RevoltColorScheme else -> RevoltColorScheme
} }
val colorSchemeIsDark = when {
m3Supported && requestedTheme == Theme.M3Dynamic -> isSystemInDarkTheme()
requestedTheme == Theme.Revolt -> true
requestedTheme == Theme.Light -> false
requestedTheme == Theme.Amoled -> true
requestedTheme == Theme.None && systemInDarkTheme -> true
requestedTheme == Theme.None && !systemInDarkTheme -> false
else -> true
}
val view = LocalView.current val view = LocalView.current
if (!view.isInEditMode) { if (!view.isInEditMode) {
SideEffect { SideEffect {
val window = (view.context as Activity).window val window = (view.context as Activity).window
window.statusBarColor = colorScheme.background.toArgb() window.statusBarColor = colorScheme.background.toArgb()
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = false ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars =
!colorSchemeIsDark
} }
} }

View File

@ -71,6 +71,9 @@
<string name="send_alt">Send</string> <string name="send_alt">Send</string>
<string name="add_attachment_alt">Add attachment</string> <string name="add_attachment_alt">Add attachment</string>
<string name="remove_attachment_alt">Remove attachment</string> <string name="remove_attachment_alt">Remove attachment</string>
<string name="remove_reply_alt">Remove reply</string>
<string name="reply_mention_on">\@ on</string>
<string name="reply_mention_off">\@ off</string>
<string name="badge_bot_alt">Bot</string> <string name="badge_bot_alt">Bot</string>
<string name="badge_masquerade_alt">From linked channel</string> <string name="badge_masquerade_alt">From linked channel</string>
@ -98,6 +101,7 @@
<string name="message_field_placeholder_notes">Add a note</string> <string name="message_field_placeholder_notes">Add a note</string>
<string name="reply_message_not_cached">Unknown message, tap to jump</string> <string name="reply_message_not_cached">Unknown message, tap to jump</string>
<string name="reply_message_empty_has_attachments">Sent attachments</string>
<string name="disconnected">Disconnected</string> <string name="disconnected">Disconnected</string>
<string name="tap_to_reconnect">Tap to reconnect</string> <string name="tap_to_reconnect">Tap to reconnect</string>