From af92c95a82e35504dbe118d3d04dcf633ef5f6ae Mon Sep 17 00:00:00 2001 From: Infi Date: Sat, 4 Mar 2023 01:54:51 +0100 Subject: [PATCH] feat: revamp attachment display --- .../chat/revolt/components/chat/Message.kt | 37 +----- .../components/chat/MessageAttachment.kt | 115 ++++++++++++++++++ .../revolt/components/chat/MessageField.kt | 7 +- app/src/main/res/drawable/ic_file_24dp.xml | 9 ++ 4 files changed, 135 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/chat/revolt/components/chat/MessageAttachment.kt create mode 100644 app/src/main/res/drawable/ic_file_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 f03ddd67..ac09b65c 100644 --- a/app/src/main/java/chat/revolt/components/chat/Message.kt +++ b/app/src/main/java/chat/revolt/components/chat/Message.kt @@ -9,8 +9,6 @@ import androidx.compose.material3.* 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.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow @@ -22,7 +20,6 @@ import chat.revolt.api.asJanuaryProxyUrl import chat.revolt.api.internals.ULID import chat.revolt.api.internals.WebCompat import chat.revolt.api.schemas.AutumnResource -import chat.revolt.components.generic.RemoteImage import chat.revolt.components.generic.UserAvatar import chat.revolt.components.generic.UserAvatarWidthPlaceholder import chat.revolt.markdown.Markdown @@ -135,6 +132,8 @@ fun Message( } message.content?.let { + if (message.content.isBlank()) return@let // if only an attachment is sent + Text( text = Markdown.annotate(it), maxLines = if (truncate) 1 else Int.MAX_VALUE, @@ -143,34 +142,10 @@ fun Message( } message.attachments?.let { - if (message.attachments.isNotEmpty()) { - message.attachments.forEach { attachment -> - if (attachment.metadata?.type == "Image") { - RemoteImage( - url = "$REVOLT_FILES/attachments/${attachment.id}/image.png", - modifier = Modifier - .padding(top = 5.dp) - .clickable { - viewAttachmentInBrowser(context, attachment) - }, - width = attachment.metadata.width?.toInt() ?: 0, - height = attachment.metadata.height?.toInt() ?: 0, - contentScale = ContentScale.Fit, - description = "Attached image ${attachment.filename}" - ) - } else { - Text( - text = attachment.filename ?: "Attachment", - fontWeight = FontWeight.Medium, - modifier = Modifier - .clip(MaterialTheme.shapes.medium) - .clickable { - viewAttachmentInBrowser(context, attachment) - } - .background(MaterialTheme.colorScheme.surface) - .padding(8.dp) - ) - } + message.attachments.forEach { attachment -> + Spacer(modifier = Modifier.height(5.dp)) + MessageAttachment(attachment) { + viewAttachmentInBrowser(context, attachment) } } } diff --git a/app/src/main/java/chat/revolt/components/chat/MessageAttachment.kt b/app/src/main/java/chat/revolt/components/chat/MessageAttachment.kt new file mode 100644 index 00000000..20ee3ec8 --- /dev/null +++ b/app/src/main/java/chat/revolt/components/chat/MessageAttachment.kt @@ -0,0 +1,115 @@ +package chat.revolt.components.chat + +import android.text.format.Formatter +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material.Icon +import androidx.compose.material.LocalContentColor +import androidx.compose.material.Text +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.surfaceColorAtElevation +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import chat.revolt.R +import chat.revolt.api.REVOLT_FILES +import chat.revolt.api.schemas.AutumnResource +import chat.revolt.components.generic.RemoteImage + +@Composable +fun FileAttachment(attachment: AutumnResource) { + val context = LocalContext.current + + CompositionLocalProvider(LocalContentColor provides MaterialTheme.colorScheme.onSurface) { + Row( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.surfaceColorAtElevation(2.dp)) + .padding(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_file_24dp), + contentDescription = null, + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Column { + Text( + text = attachment.filename ?: "File", + maxLines = 1, + fontWeight = FontWeight.Bold, + ) + Text( + text = Formatter.formatShortFileSize(context, attachment.size ?: 0), + maxLines = 1, + color = LocalContentColor.current.copy(alpha = 0.7f), + fontWeight = FontWeight.Normal, + ) + } + } + } +} + +@Composable +fun ImageAttachment(attachment: AutumnResource) { + val url = "$REVOLT_FILES/attachments/${attachment.id}/${attachment.filename}" + + RemoteImage( + url = url, + contentScale = ContentScale.Fit, + modifier = Modifier + .fillMaxWidth() + .aspectRatio(attachment.metadata!!.width!!.toFloat() / attachment.metadata.height!!.toFloat()), + description = attachment.filename ?: "Image", + ) +} + +@Composable +fun VideoAttachment(attachment: AutumnResource) { + // FIXME Use ExoPlayer to play videos. + FileAttachment(attachment) +} + +@Composable +fun AudioAttachment(attachment: AutumnResource) { + // FIXME Use ExoPlayer to play audio. + FileAttachment(attachment) +} + +@Composable +fun TextAttachment(attachment: AutumnResource) { + // FIXME Write bespoke viewer for text attachments. + FileAttachment(attachment) +} + +@Composable +fun MessageAttachment(attachment: AutumnResource, onAttachmentClick: (AutumnResource) -> Unit) { + Box( + modifier = Modifier + .clip(MaterialTheme.shapes.medium) + .clickable { onAttachmentClick(attachment) } + ) { + if (attachment.metadata?.type == null) { + FileAttachment(attachment) + return + } + + when (attachment.metadata.type) { + "Image" -> ImageAttachment(attachment) + "Video" -> VideoAttachment(attachment) + "Audio" -> AudioAttachment(attachment) + "Text" -> TextAttachment(attachment) + else -> FileAttachment(attachment) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/chat/revolt/components/chat/MessageField.kt b/app/src/main/java/chat/revolt/components/chat/MessageField.kt index 2d0a8dba..bef72031 100644 --- a/app/src/main/java/chat/revolt/components/chat/MessageField.kt +++ b/app/src/main/java/chat/revolt/components/chat/MessageField.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.VisualTransformation +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import chat.revolt.R @@ -76,10 +77,12 @@ fun MessageField( interactionSource = remember { MutableInteractionSource() }, placeholder = { Text( - stringResource( + text = stringResource( id = placeholderResource, channelName - ) + ), + maxLines = 1, + overflow = TextOverflow.Ellipsis, ) }, colors = TextFieldDefaults.textFieldColors( diff --git a/app/src/main/res/drawable/ic_file_24dp.xml b/app/src/main/res/drawable/ic_file_24dp.xml new file mode 100644 index 00000000..410bf5a3 --- /dev/null +++ b/app/src/main/res/drawable/ic_file_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file