feat(jbm): render md in replies

Signed-off-by: Infi <infi@infi.sh>
This commit is contained in:
Infi 2024-10-21 04:09:23 +02:00
parent fcbd13331c
commit 9dc4ecbdf4
2 changed files with 43 additions and 11 deletions

View File

@ -1,5 +1,6 @@
package chat.revolt.components.chat package chat.revolt.components.chat
import android.util.Log
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -12,7 +13,9 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
@ -28,8 +31,13 @@ import chat.revolt.api.RevoltAPI
import chat.revolt.api.internals.solidColor import chat.revolt.api.internals.solidColor
import chat.revolt.api.routes.channel.fetchSingleMessage import chat.revolt.api.routes.channel.fetchSingleMessage
import chat.revolt.api.schemas.User import chat.revolt.api.schemas.User
import chat.revolt.api.settings.Experiments
import chat.revolt.components.generic.UserAvatar import chat.revolt.components.generic.UserAvatar
import chat.revolt.components.markdown.jbm.JBM
import chat.revolt.components.markdown.jbm.JBMRenderer
import chat.revolt.components.markdown.jbm.LocalJBMarkdownTreeState
@OptIn(JBM::class)
@Composable @Composable
fun InReplyTo( fun InReplyTo(
channelId: String, channelId: String,
@ -49,9 +57,15 @@ fun InReplyTo(
val usernameColor = val usernameColor =
message?.let { authorColour(it) } ?: Brush.solidColor(contentColor) message?.let { authorColour(it) } ?: Brush.solidColor(contentColor)
val serverId = remember(channelId) { RevoltAPI.channelCache[channelId]?.server }
LaunchedEffect(messageId) { LaunchedEffect(messageId) {
if (messageId !in RevoltAPI.messageCache) { if (messageId !in RevoltAPI.messageCache) {
RevoltAPI.messageCache[messageId] = fetchSingleMessage(channelId, messageId) try {
RevoltAPI.messageCache[messageId] = fetchSingleMessage(channelId, messageId)
} catch (e: Exception) {
Log.e("InReplyTo", "Failed to fetch message $messageId", e)
}
} }
} }
@ -108,22 +122,34 @@ fun InReplyTo(
if (message.content.isNullOrBlank()) { if (message.content.isNullOrBlank()) {
Text( Text(
text = stringResource(id = R.string.reply_message_empty_has_attachments), text = stringResource(id = R.string.reply_message_empty_has_attachments),
// TODO: inter has italics now, import and use them
fontStyle = FontStyle.Italic, // inter doesn't have italics...
fontSize = 12.sp, fontSize = 12.sp,
fontFamily = FontFamily.Default, // ...so we use the default font
color = contentColor.copy(alpha = 0.7f), color = contentColor.copy(alpha = 0.7f),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )
} else { } else {
Text( if (Experiments.useKotlinBasedMarkdownRenderer.isEnabled) {
text = message.content, CompositionLocalProvider(
fontSize = 12.sp, LocalJBMarkdownTreeState provides LocalJBMarkdownTreeState.current.copy(
color = contentColor.copy(alpha = 0.7f), embedded = true,
maxLines = 1, singleLine = true,
overflow = TextOverflow.Ellipsis currentServer = serverId,
) linksClickable = false
),
LocalContentColor provides contentColor.copy(alpha = 0.7f),
LocalTextStyle provides LocalTextStyle.current.copy(fontSize = 12.sp)
) {
JBMRenderer(message.content)
}
} else {
Text(
text = message.content,
fontSize = 12.sp,
color = contentColor.copy(alpha = 0.7f),
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
} }
} else { } else {
Text( Text(

View File

@ -56,6 +56,7 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontStyle 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.TextDecoration import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
@ -104,6 +105,7 @@ data class JBMarkdownTreeState(
val linksClickable: Boolean = true, val linksClickable: Boolean = true,
val currentServer: String? = null, val currentServer: String? = null,
val embedded: Boolean = false, val embedded: Boolean = false,
val singleLine: Boolean = false,
val colors: JBMColors = JBMColors( val colors: JBMColors = JBMColors(
clickable = Color(0xFFFF00FF), clickable = Color(0xFFFF00FF),
clickableBackground = Color(0x2000FF00) clickableBackground = Color(0x2000FF00)
@ -456,6 +458,8 @@ private fun JBMText(node: ASTNode, modifier: Modifier) {
Text( Text(
text = annotatedText, text = annotatedText,
onTextLayout = { layoutResult = it }, onTextLayout = { layoutResult = it },
maxLines = if (mdState.singleLine) 1 else Int.MAX_VALUE,
overflow = if (mdState.singleLine) TextOverflow.Ellipsis else TextOverflow.Clip,
modifier = modifier.pointerInput(onClick, onLongClick) { modifier = modifier.pointerInput(onClick, onLongClick) {
detectTapGesturesConditionalConsume( detectTapGesturesConditionalConsume(
onTap = { pos -> onTap = { pos ->
@ -771,6 +775,8 @@ private fun JBMBlock(node: ASTNode, modifier: Modifier, nestingCounter: Int = 0)
append("[Unknown block type ${node.type.name}]") append("[Unknown block type ${node.type.name}]")
} }
}, },
maxLines = if (state.singleLine) 1 else Int.MAX_VALUE,
overflow = if (state.singleLine) TextOverflow.Ellipsis else TextOverflow.Clip,
modifier = modifier modifier = modifier
) )
} }