From 1d7bc309a38b62ac392fb1c6a89aaf4cd89536d8 Mon Sep 17 00:00:00 2001 From: Infi Date: Wed, 10 Apr 2024 23:07:49 +0200 Subject: [PATCH] feat: do not show messages from blocked users Signed-off-by: Infi --- .../chat/revolt/components/chat/Message.kt | 504 ++++++++++-------- .../res/drawable/ic_close_octagon_24dp.xml | 9 + app/src/main/res/values/strings.xml | 2 + 3 files changed, 289 insertions(+), 226 deletions(-) create mode 100644 app/src/main/res/drawable/ic_close_octagon_24dp.xml 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 5a50e79c..09b7624e 100644 --- a/app/src/main/java/chat/revolt/components/chat/Message.kt +++ b/app/src/main/java/chat/revolt/components/chat/Message.kt @@ -36,6 +36,7 @@ import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.key +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment 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.res.painterResource 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.style.TextOverflow import androidx.compose.ui.unit.dp @@ -181,53 +183,20 @@ fun Message( // do nothing } ) + + val authorIsBlocked = remember(author) { author.relationship == "Blocked" } + Column { if (message.tail == false) { Spacer(modifier = Modifier.height(10.dp)) } - 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] - - 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() - } - } - } - } - + if (authorIsBlocked) { Row( modifier = Modifier .combinedClickable( onClick = {}, - onDoubleClick = { - if (canReply && GlobalState.messageReplyStyle == MessageReplyStyle.DoubleTap) { - onReply() - } - }, + onDoubleClick = {}, onLongClick = { onMessageContextMenu() } @@ -235,206 +204,289 @@ fun Message( .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() - } + 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 - ) - ) + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(vertical = 8.dp) + ) { + Icon( + painter = painterResource(R.drawable.ic_close_octagon_24dp), + contentDescription = null + ) - 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)) - } - ) + Text( + text = stringResource(R.string.message_blocked), + fontSize = 12.sp, + color = LocalContentColor.current.copy(alpha = 0.5f), + fontStyle = FontStyle.Italic + ) + } + } + } + } 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)) - - 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) + message.channel?.let { chId -> + InReplyTo( + channelId = chId, + messageId = reply, + withMention = replyMessage?.author?.let { + message.mentions?.contains( + replyMessage.author ) } - } - } - - 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) + ?: false ) { - 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 - ) - } + // TODO Add jump to message + if (replyMessage == null) { + Toast.makeText(context, "lmao prankd", Toast.LENGTH_SHORT).show() + } + } + } + } + + Row( + modifier = Modifier + .combinedClickable( + onClick = {}, + onDoubleClick = { + if (canReply && GlobalState.messageReplyStyle == MessageReplyStyle.DoubleTap) { + 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 - ) - ) - } } - } - - 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(2.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)) + } } } } diff --git a/app/src/main/res/drawable/ic_close_octagon_24dp.xml b/app/src/main/res/drawable/ic_close_octagon_24dp.xml new file mode 100644 index 00000000..fceb5602 --- /dev/null +++ b/app/src/main/res/drawable/ic_close_octagon_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dffd60eb..ecd7c776 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -187,6 +187,8 @@ Unknown message Sent attachments + Blocked message + Ownership changed Channel icon changed Channel description changed