feat: do not show messages from blocked users

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2024-04-10 23:07:49 +02:00
parent 71895c348f
commit 1d7bc309a3
3 changed files with 289 additions and 226 deletions

View File

@ -36,6 +36,7 @@ import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.key import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -44,6 +45,7 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -181,53 +183,20 @@ fun Message(
// do nothing // do nothing
} }
) )
val authorIsBlocked = remember(author) { author.relationship == "Blocked" }
Column { Column {
if (message.tail == false) { if (message.tail == false) {
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
} }
Column( if (authorIsBlocked) {
modifier = Modifier.then(
if (message.mentions?.contains(RevoltAPI.selfId) == true) {
Modifier.background(
MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
)
} else {
Modifier
}
)
) {
message.replies?.forEach { reply ->
val replyMessage = RevoltAPI.messageCache[reply]
message.channel?.let { chId ->
InReplyTo(
channelId = chId,
messageId = reply,
withMention = replyMessage?.author?.let {
message.mentions?.contains(
replyMessage.author
)
}
?: false
) {
// TODO Add jump to message
if (replyMessage == null) {
Toast.makeText(context, "lmao prankd", Toast.LENGTH_SHORT).show()
}
}
}
}
Row( Row(
modifier = Modifier modifier = Modifier
.combinedClickable( .combinedClickable(
onClick = {}, onClick = {},
onDoubleClick = { onDoubleClick = {},
if (canReply && GlobalState.messageReplyStyle == MessageReplyStyle.DoubleTap) {
onReply()
}
},
onLongClick = { onLongClick = {
onMessageContextMenu() onMessageContextMenu()
} }
@ -235,206 +204,289 @@ fun Message(
.padding(horizontal = 10.dp) .padding(horizontal = 10.dp)
.fillMaxWidth() .fillMaxWidth()
) { ) {
if (message.tail == false) { UserAvatarWidthPlaceholder()
Column {
Spacer(modifier = Modifier.height(4.dp))
UserAvatar(
username = User.resolveDefaultName(author),
userId = author.id ?: message.id ?: ULID.makeSpecial(0),
avatar = author.avatar,
rawUrl = authorAvatarUrl(message),
onClick = onAvatarClick
)
}
} else {
UserAvatarWidthPlaceholder()
}
Column(modifier = Modifier.padding(start = 10.dp)) { Column(modifier = Modifier.padding(start = 10.dp)) {
if (message.tail == false) { Row(
Row(verticalAlignment = Alignment.CenterVertically) { horizontalArrangement = Arrangement.spacedBy(8.dp),
Text( verticalAlignment = Alignment.CenterVertically,
text = authorName(message), modifier = Modifier.padding(vertical = 8.dp)
style = LocalTextStyle.current.copy( ) {
fontWeight = FontWeight.Bold, Icon(
brush = authorColour(message) painter = painterResource(R.drawable.ic_close_octagon_24dp),
), contentDescription = null
maxLines = 1, )
overflow = TextOverflow.Ellipsis,
modifier = Modifier.then(
if (onNameClick != null)
Modifier.combinedClickable(
onClick = onNameClick,
onLongClick = {
onMessageContextMenu()
}
)
else Modifier
)
)
InlineBadges( Text(
bot = author.bot != null && message.masquerade == null, text = stringResource(R.string.message_blocked),
bridge = message.masquerade != null && author.bot != null, fontSize = 12.sp,
platformModeration = author.id == SpecialUsers.PLATFORM_MODERATION_USER, color = LocalContentColor.current.copy(alpha = 0.5f),
teamMember = author.id in SpecialUsers.TEAM_MEMBER_FLAIRS.keys, fontStyle = FontStyle.Italic
colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f), )
modifier = Modifier.size(16.dp), }
precedingIfAny = { }
Spacer(modifier = Modifier.width(5.dp)) }
} } else {
) Column(
modifier = Modifier.then(
if (message.mentions?.contains(RevoltAPI.selfId) == true) {
Modifier.background(
MaterialTheme.colorScheme.primary.copy(alpha = 0.1f)
)
} else {
Modifier
}
)
) {
message.replies?.forEach { reply ->
val replyMessage = RevoltAPI.messageCache[reply]
Spacer(modifier = Modifier.width(5.dp)) message.channel?.let { chId ->
InReplyTo(
Text( channelId = chId,
text = formatLongAsTime(ULID.asTimestamp(message.id!!)), messageId = reply,
fontSize = 12.sp, withMention = replyMessage?.author?.let {
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f), message.mentions?.contains(
maxLines = 1, replyMessage.author
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.width(2.dp))
if (message.edited != null) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = stringResource(id = R.string.edited),
tint = MaterialTheme.colorScheme.onBackground.copy(
alpha = 0.5f
),
modifier = Modifier.size(16.dp)
) )
} }
} ?: false
}
key(message.content) {
message.content?.let {
if (message.content.isBlank()) return@let // if only an attachment is sent
CompositionLocalProvider(
LocalMarkdownTreeConfig provides LocalMarkdownTreeConfig.current.copy(
currentServer = RevoltAPI.channelCache[message.channel]?.server
),
LocalTextStyle provides LocalTextStyle.current.copy(
lineHeight = 25.sp,
)
) {
RichMarkdown(input = message.content)
}
}
}
message.attachments?.let {
message.attachments.forEach { attachment ->
Spacer(modifier = Modifier.height(2.dp))
MessageAttachment(attachment) {
when (attachment.metadata?.type) {
"Image" -> {
attachmentView.launch(
Intent(context, ImageViewActivity::class.java).apply {
putExtra("autumnResource", attachment)
}
)
}
"Video" -> {
attachmentView.launch(
Intent(context, VideoViewActivity::class.java).apply {
putExtra("autumnResource", attachment)
}
)
}
"Audio" -> {
/* no-op */
}
else -> {
viewAttachmentInBrowser(context, attachment)
}
}
}
Spacer(modifier = Modifier.height(2.dp))
}
}
message.embeds?.let {
message.embeds.forEach { embed ->
val embedIsEmpty =
embed.title == null && embed.description == null && embed.iconURL == null && embed.image == null
if (embedIsEmpty) {
// if we do not emit anything, compose will cause an internal error.
// FIXME if you are doing fixme's anyways then check if this is still an issue
Box {}
return@forEach
}
Spacer(modifier = Modifier.height(8.dp))
Embed(embed = embed, onLinkClick = {
viewUrlInBrowser(context, it)
})
Spacer(modifier = Modifier.height(8.dp))
}
}
if ((message.reactions?.size ?: 0) > 0) {
Spacer(modifier = Modifier.height(8.dp))
FlowRow(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
message.reactions?.forEach { reaction -> // TODO Add jump to message
Reaction(reaction.key, reaction.value, if (replyMessage == null) {
onClick = { hasOwn -> Toast.makeText(context, "lmao prankd", Toast.LENGTH_SHORT).show()
scope.launch { }
if (hasOwn) { }
unreact( }
message.channel!!, }
message.id!!,
reaction.key Row(
) modifier = Modifier
} else { .combinedClickable(
react( onClick = {},
message.channel!!, onDoubleClick = {
message.id!!, if (canReply && GlobalState.messageReplyStyle == MessageReplyStyle.DoubleTap) {
reaction.key onReply()
) }
} },
onLongClick = {
onMessageContextMenu()
}
)
.padding(horizontal = 10.dp)
.fillMaxWidth()
) {
if (message.tail == false) {
Column {
Spacer(modifier = Modifier.height(4.dp))
UserAvatar(
username = User.resolveDefaultName(author),
userId = author.id ?: message.id ?: ULID.makeSpecial(0),
avatar = author.avatar,
rawUrl = authorAvatarUrl(message),
onClick = onAvatarClick
)
}
} else {
UserAvatarWidthPlaceholder()
}
Column(modifier = Modifier.padding(start = 10.dp)) {
if (message.tail == false) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = authorName(message),
style = LocalTextStyle.current.copy(
fontWeight = FontWeight.Bold,
brush = authorColour(message)
),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.then(
if (onNameClick != null)
Modifier.combinedClickable(
onClick = onNameClick,
onLongClick = {
onMessageContextMenu()
}
)
else Modifier
)
)
InlineBadges(
bot = author.bot != null && message.masquerade == null,
bridge = message.masquerade != null && author.bot != null,
platformModeration = author.id == SpecialUsers.PLATFORM_MODERATION_USER,
teamMember = author.id in SpecialUsers.TEAM_MEMBER_FLAIRS.keys,
colour = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
modifier = Modifier.size(16.dp),
precedingIfAny = {
Spacer(modifier = Modifier.width(5.dp))
}
)
Spacer(modifier = Modifier.width(5.dp))
Text(
text = formatLongAsTime(ULID.asTimestamp(message.id!!)),
fontSize = 12.sp,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.5f),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Spacer(modifier = Modifier.width(2.dp))
if (message.edited != null) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = stringResource(id = R.string.edited),
tint = MaterialTheme.colorScheme.onBackground.copy(
alpha = 0.5f
),
modifier = Modifier.size(16.dp)
)
}
}
}
key(message.content) {
message.content?.let {
if (message.content.isBlank()) return@let // if only an attachment is sent
CompositionLocalProvider(
LocalMarkdownTreeConfig provides LocalMarkdownTreeConfig.current.copy(
currentServer = RevoltAPI.channelCache[message.channel]?.server
),
LocalTextStyle provides LocalTextStyle.current.copy(
lineHeight = 25.sp,
)
) {
RichMarkdown(input = message.content)
}
}
}
message.attachments?.let {
message.attachments.forEach { attachment ->
Spacer(modifier = Modifier.height(2.dp))
MessageAttachment(attachment) {
when (attachment.metadata?.type) {
"Image" -> {
attachmentView.launch(
Intent(
context,
ImageViewActivity::class.java
).apply {
putExtra("autumnResource", attachment)
}
)
}
"Video" -> {
attachmentView.launch(
Intent(
context,
VideoViewActivity::class.java
).apply {
putExtra("autumnResource", attachment)
}
)
}
"Audio" -> {
/* no-op */
}
else -> {
viewAttachmentInBrowser(context, attachment)
} }
} }
) {
scope.launch {
ActionChannel.send(
Action.MessageReactionInfo(
message.id!!,
reaction.key
)
)
}
} }
} Spacer(modifier = Modifier.height(2.dp))
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(MaterialTheme.shapes.small)
.background(MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp))
.clickable(onClick = onAddReaction)
.padding(8.dp)
) {
Icon(
painter = painterResource(R.drawable.ic_hamburger_plus_24dp),
contentDescription = stringResource(R.string.message_context_sheet_actions_react),
modifier = Modifier.size(16.dp)
)
} }
} }
Spacer(modifier = Modifier.height(8.dp))
message.embeds?.let {
message.embeds.forEach { embed ->
val embedIsEmpty =
embed.title == null && embed.description == null && embed.iconURL == null && embed.image == null
if (embedIsEmpty) {
// if we do not emit anything, compose will cause an internal error.
// FIXME if you are doing fixme's anyways then check if this is still an issue
Box {}
return@forEach
}
Spacer(modifier = Modifier.height(8.dp))
Embed(embed = embed, onLinkClick = {
viewUrlInBrowser(context, it)
})
Spacer(modifier = Modifier.height(8.dp))
}
}
if ((message.reactions?.size ?: 0) > 0) {
Spacer(modifier = Modifier.height(8.dp))
FlowRow(
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
message.reactions?.forEach { reaction ->
Reaction(reaction.key, reaction.value,
onClick = { hasOwn ->
scope.launch {
if (hasOwn) {
unreact(
message.channel!!,
message.id!!,
reaction.key
)
} else {
react(
message.channel!!,
message.id!!,
reaction.key
)
}
}
}
) {
scope.launch {
ActionChannel.send(
Action.MessageReactionInfo(
message.id!!,
reaction.key
)
)
}
}
}
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.clip(MaterialTheme.shapes.small)
.background(
MaterialTheme.colorScheme.surfaceColorAtElevation(
2.dp
)
)
.clickable(onClick = onAddReaction)
.padding(8.dp)
) {
Icon(
painter = painterResource(R.drawable.ic_hamburger_plus_24dp),
contentDescription = stringResource(R.string.message_context_sheet_actions_react),
modifier = Modifier.size(16.dp)
)
}
}
Spacer(modifier = Modifier.height(8.dp))
}
} }
} }
} }

View File

@ -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:fillColor="#ffffff"
android:pathData="M8.27,3L3,8.27V15.73L8.27,21H15.73L21,15.73V8.27L15.73,3M8.41,7L12,10.59L15.59,7L17,8.41L13.41,12L17,15.59L15.59,17L12,13.41L8.41,17L7,15.59L10.59,12L7,8.41" />
</vector>

View File

@ -187,6 +187,8 @@
<string name="reply_message_not_cached">Unknown message</string> <string name="reply_message_not_cached">Unknown message</string>
<string name="reply_message_empty_has_attachments">Sent attachments</string> <string name="reply_message_empty_has_attachments">Sent attachments</string>
<string name="message_blocked">Blocked message</string>
<string name="system_message_ownership_changed_alt">Ownership changed</string> <string name="system_message_ownership_changed_alt">Ownership changed</string>
<string name="system_message_channel_icon_changed_alt">Channel icon changed</string> <string name="system_message_channel_icon_changed_alt">Channel icon changed</string>
<string name="system_message_channel_description_changed_alt">Channel description changed</string> <string name="system_message_channel_description_changed_alt">Channel description changed</string>