Implement MSC4027 (Custom Images in Reactions)

Signed-off-by: Marco Antonio Alvarez <surakin@gmail.com>
This commit is contained in:
Marco Antonio Alvarez 2024-01-03 23:30:14 +01:00
parent c6d109c424
commit 467ccf65a2
2 changed files with 53 additions and 18 deletions

View file

@ -24,7 +24,9 @@ import androidx.compose.foundation.border
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
@ -41,10 +43,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.R import io.element.android.features.messages.impl.R
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
import io.element.android.features.messages.impl.timeline.model.AggregatedReactionProvider import io.element.android.features.messages.impl.timeline.model.AggregatedReactionProvider
import io.element.android.features.messages.impl.timeline.model.aTimelineItemReactions import io.element.android.features.messages.impl.timeline.model.aTimelineItemReactions
import io.element.android.libraries.designsystem.components.BlurHashAsyncImage
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.toDp import io.element.android.libraries.designsystem.text.toDp
@ -52,7 +56,8 @@ import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.utils.CommonDrawables import io.element.android.libraries.designsystem.utils.CommonDrawables
import io.element.android.compound.theme.ElementTheme import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.ui.media.MediaRequestData
@Composable @Composable
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@ -114,7 +119,8 @@ sealed interface MessagesReactionsButtonContent {
val isHighlighted get() = this is Reaction && reaction.isHighlighted val isHighlighted get() = this is Reaction && reaction.isHighlighted
} }
private val reactionEmojiLineHeight = 20.sp internal val reactionEmojiLineHeight = 20.sp
internal val reactionImageAspectRatio = 1.33f
private val addEmojiSize = 16.dp private val addEmojiSize = 16.dp
@Composable @Composable
@ -150,13 +156,24 @@ private fun ReactionContent(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = modifier, modifier = modifier,
) { ) {
Text( if (reaction.key.startsWith("mxc://")) {
text = reaction.displayKey, BlurHashAsyncImage(
style = ElementTheme.typography.fontBodyMdRegular.copy( modifier = modifier
fontSize = 15.sp, .heightIn(min = reactionEmojiLineHeight.toDp(), max = reactionEmojiLineHeight.toDp())
lineHeight = reactionEmojiLineHeight, .aspectRatio(reactionImageAspectRatio, false),
), model = MediaRequestData(MediaSource(reaction.key), MediaRequestData.Kind.Content),
) blurHash = null
)
}
else {
Text(
text = reaction.displayKey,
style = ElementTheme.typography.fontBodyMdRegular.copy(
fontSize = 15.sp,
lineHeight = reactionEmojiLineHeight,
),
)
}
if (reaction.count > 1) { if (reaction.count > 1) {
Spacer(modifier = Modifier.width(4.dp)) Spacer(modifier = Modifier.width(4.dp))
Text( Text(

View file

@ -24,6 +24,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
@ -57,18 +58,24 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.timeline.components.reactionEmojiLineHeight
import io.element.android.features.messages.impl.timeline.components.reactionImageAspectRatio
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
import io.element.android.libraries.designsystem.components.BlurHashAsyncImage
import io.element.android.libraries.designsystem.components.avatar.Avatar import io.element.android.libraries.designsystem.components.avatar.Avatar
import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.text.toDp
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.Surface import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.media.MediaRequestData
import io.element.android.libraries.matrix.ui.model.getAvatarData import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.compound.theme.ElementTheme
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@ -192,13 +199,24 @@ private fun AggregatedReactionButton(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier, modifier = Modifier,
) { ) {
Text( if (reaction.key.startsWith("mxc://")) {
text = reaction.displayKey, BlurHashAsyncImage(
style = ElementTheme.typography.fontBodyMdRegular.copy( modifier = modifier
fontSize = 20.sp, .heightIn(min = reactionEmojiLineHeight.toDp(), max = reactionEmojiLineHeight.toDp())
lineHeight = 25.sp .aspectRatio(reactionImageAspectRatio, false),
), model = MediaRequestData(MediaSource(reaction.key), MediaRequestData.Kind.Content),
) blurHash = null
)
}
else {
Text(
text = reaction.displayKey,
style = ElementTheme.typography.fontBodyMdRegular.copy(
fontSize = 20.sp,
lineHeight = 25.sp
),
)
}
if (reaction.count > 1) { if (reaction.count > 1) {
Spacer(modifier = Modifier.width(4.dp)) Spacer(modifier = Modifier.width(4.dp))
Text( Text(