Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement MSC4027 (Custom images in reactions) #2160

Merged
merged 13 commits into from
Jan 4, 2024
1 change: 1 addition & 0 deletions changelog.d/2159.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added support for MSC4027 (render custom images in reactions)
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
Expand All @@ -41,6 +43,8 @@
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import io.element.android.compound.theme.ElementTheme
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.AggregatedReactionProvider
Expand All @@ -52,7 +56,8 @@
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text
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
@OptIn(ExperimentalFoundationApi::class)
Expand Down Expand Up @@ -114,16 +119,17 @@
val isHighlighted get() = this is Reaction && reaction.isHighlighted
}

private val reactionEmojiLineHeight = 20.sp
private val addEmojiSize = 16.dp
internal val REACTION_EMOJI_LINE_HEIGHT = 20.sp
internal const val REACTION_IMAGE_ASPECT_RATIO = 1.0f
private val ADD_EMOJI_SIZE = 16.dp

@Composable
private fun TextContent(
text: String,
modifier: Modifier = Modifier,
) = Text(
modifier = modifier
.height(reactionEmojiLineHeight.toDp()),
.height(REACTION_EMOJI_LINE_HEIGHT.toDp()),
text = text,
style = ElementTheme.typography.fontBodyMdRegular,
color = ElementTheme.materialColors.primary
Expand All @@ -138,7 +144,7 @@
contentDescription = stringResource(id = R.string.screen_room_timeline_add_reaction),
tint = ElementTheme.materialColors.secondary,
modifier = modifier
.size(addEmojiSize)
.size(ADD_EMOJI_SIZE)

)

Expand All @@ -150,13 +156,25 @@
verticalAlignment = Alignment.CenterVertically,
modifier = modifier,
) {
Text(
text = reaction.displayKey,
style = ElementTheme.typography.fontBodyMdRegular.copy(
fontSize = 15.sp,
lineHeight = reactionEmojiLineHeight,
),
)
// Check if this is a custom reaction (MSC4027)
if (reaction.key.startsWith("mxc://")) {
surakin marked this conversation as resolved.
Show resolved Hide resolved
AsyncImage(
modifier = modifier
.heightIn(min = REACTION_EMOJI_LINE_HEIGHT.toDp(), max = REACTION_EMOJI_LINE_HEIGHT.toDp())
.aspectRatio(REACTION_IMAGE_ASPECT_RATIO, false),
model = MediaRequestData(MediaSource(reaction.key), MediaRequestData.Kind.Content),
contentDescription = null

Check warning on line 166 in features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessagesReactionButton.kt

View check run for this annotation

Codecov / codecov/patch

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/MessagesReactionButton.kt#L161-L166

Added lines #L161 - L166 were not covered by tests
)
}
else {
Text(
text = reaction.displayKey,
style = ElementTheme.typography.fontBodyMdRegular.copy(
fontSize = 15.sp,
lineHeight = REACTION_EMOJI_LINE_HEIGHT,
),
)
}
if (reaction.count > 1) {
Spacer(modifier = Modifier.width(4.dp))
Text(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
Expand Down Expand Up @@ -57,20 +58,27 @@
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.timeline.components.REACTION_IMAGE_ASPECT_RATIO
import io.element.android.features.messages.impl.timeline.model.AggregatedReaction
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.AvatarSize
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
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.Surface
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.ui.media.MediaRequestData
import io.element.android.libraries.matrix.ui.model.getAvatarData
import io.element.android.compound.theme.ElementTheme
import kotlinx.coroutines.launch

internal val REACTION_SUMMARY_LINE_HEIGHT = 25.sp

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ReactionSummaryView(
Expand Down Expand Up @@ -192,21 +200,33 @@
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier,
) {
Text(
text = reaction.displayKey,
style = ElementTheme.typography.fontBodyMdRegular.copy(
fontSize = 20.sp,
lineHeight = 25.sp
),
)
// Check if this is a custom reaction (MSC4027)
if (reaction.key.startsWith("mxc://")) {
AsyncImage(
modifier = Modifier
.heightIn(min = REACTION_SUMMARY_LINE_HEIGHT.toDp(), max = REACTION_SUMMARY_LINE_HEIGHT.toDp())
.aspectRatio(REACTION_IMAGE_ASPECT_RATIO, false),
model = MediaRequestData(MediaSource(reaction.key), MediaRequestData.Kind.Content),
contentDescription = null

Check warning on line 210 in features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt

View check run for this annotation

Codecov / codecov/patch

features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/reactionsummary/ReactionSummaryView.kt#L205-L210

Added lines #L205 - L210 were not covered by tests
)
}
else {
Text(
text = reaction.displayKey,
style = ElementTheme.typography.fontBodyMdRegular.copy(
fontSize = 20.sp,
lineHeight = REACTION_SUMMARY_LINE_HEIGHT
),
)
}
if (reaction.count > 1) {
Spacer(modifier = Modifier.width(4.dp))
Text(
text = reaction.count.toString(),
color = textColor,
style = ElementTheme.typography.fontBodyMdRegular.copy(
fontSize = 20.sp,
lineHeight = 25.sp
lineHeight = REACTION_SUMMARY_LINE_HEIGHT
)
)
}
Expand Down