Merge TimelineItemEventRow's textForInReplyTo and attachmentThumbnailInfoForInReplyTo functions (#1859)
The flow is somewhat misleading so its logic has been merged into `InReplyToDetails.metadata()`.
This commit is contained in:
@@ -23,6 +23,11 @@ plugins {
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.features.messages.impl"
|
||||
testOptions {
|
||||
unitTests {
|
||||
isIncludeAndroidResources = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
anvil {
|
||||
@@ -88,6 +93,8 @@ dependencies {
|
||||
testImplementation(projects.libraries.voicerecorder.test)
|
||||
testImplementation(projects.libraries.mediaplayer.test)
|
||||
testImplementation(libs.test.mockk)
|
||||
testImplementation(libs.test.junitext)
|
||||
testImplementation(libs.test.robolectric)
|
||||
|
||||
ksp(libs.showkase.processor)
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import androidx.constraintlayout.compose.ConstrainScope
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.messages.impl.timeline.TimelineEvents
|
||||
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
|
||||
import io.element.android.features.messages.impl.timeline.components.event.TimelineItemEventContentView
|
||||
@@ -66,6 +67,7 @@ import io.element.android.features.messages.impl.timeline.components.event.toExt
|
||||
import io.element.android.features.messages.impl.timeline.components.receipt.ReadReceiptViewState
|
||||
import io.element.android.features.messages.impl.timeline.components.receipt.TimelineItemReadReceiptView
|
||||
import io.element.android.features.messages.impl.timeline.model.InReplyToDetails
|
||||
import io.element.android.features.messages.impl.timeline.model.InReplyToMetadata
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemGroupPosition
|
||||
import io.element.android.features.messages.impl.timeline.model.bubble.BubbleState
|
||||
@@ -75,6 +77,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
|
||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVideoContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemImageContent
|
||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
|
||||
import io.element.android.features.messages.impl.timeline.model.metadata
|
||||
import io.element.android.libraries.designsystem.colors.AvatarColorsProvider
|
||||
import io.element.android.libraries.designsystem.components.EqualWidthColumn
|
||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||
@@ -89,18 +92,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.utils.CommonDrawables
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
|
||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnail
|
||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
|
||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.abs
|
||||
@@ -538,13 +530,10 @@ private fun MessageEventBubbleContent(
|
||||
}
|
||||
val inReplyTo = @Composable { inReplyTo: InReplyToDetails ->
|
||||
val senderName = inReplyTo.senderDisplayName ?: inReplyTo.senderId.value
|
||||
val attachmentThumbnailInfo = attachmentThumbnailInfoForInReplyTo(inReplyTo)
|
||||
val text = textForInReplyTo(inReplyTo)
|
||||
val topPadding = if (showThreadDecoration) 0.dp else 8.dp
|
||||
ReplyToContent(
|
||||
senderName = senderName,
|
||||
text = text,
|
||||
attachmentThumbnailInfo = attachmentThumbnailInfo,
|
||||
metadata = inReplyTo.metadata(),
|
||||
modifier = Modifier
|
||||
.padding(top = topPadding, start = 8.dp, end = 8.dp)
|
||||
.clip(RoundedCornerShape(6.dp))
|
||||
@@ -585,11 +574,10 @@ private fun MessageEventBubbleContent(
|
||||
@Composable
|
||||
private fun ReplyToContent(
|
||||
senderName: String,
|
||||
text: String?,
|
||||
attachmentThumbnailInfo: AttachmentThumbnailInfo?,
|
||||
metadata: InReplyToMetadata?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val paddings = if (attachmentThumbnailInfo != null) {
|
||||
val paddings = if (metadata is InReplyToMetadata.Thumbnail) {
|
||||
PaddingValues(start = 4.dp, end = 12.dp, top = 4.dp, bottom = 4.dp)
|
||||
} else {
|
||||
PaddingValues(horizontal = 12.dp, vertical = 4.dp)
|
||||
@@ -599,9 +587,9 @@ private fun ReplyToContent(
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
.padding(paddings)
|
||||
) {
|
||||
if (attachmentThumbnailInfo != null) {
|
||||
if (metadata is InReplyToMetadata.Thumbnail) {
|
||||
AttachmentThumbnail(
|
||||
info = attachmentThumbnailInfo,
|
||||
info = metadata.attachmentThumbnailInfo,
|
||||
backgroundColor = MaterialTheme.colorScheme.surfaceVariant,
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
@@ -619,7 +607,7 @@ private fun ReplyToContent(
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
Text(
|
||||
text = text.orEmpty(),
|
||||
text = metadata?.text.orEmpty(),
|
||||
style = ElementTheme.typography.fontBodyMdRegular,
|
||||
textAlign = TextAlign.Start,
|
||||
color = ElementTheme.materialColors.secondary,
|
||||
@@ -630,60 +618,6 @@ private fun ReplyToContent(
|
||||
}
|
||||
}
|
||||
|
||||
private fun attachmentThumbnailInfoForInReplyTo(inReplyTo: InReplyToDetails): AttachmentThumbnailInfo? {
|
||||
return when (val eventContent = inReplyTo.eventContent) {
|
||||
is MessageContent -> when (val type = eventContent.type) {
|
||||
is ImageMessageType -> AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource ?: type.source,
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.Image,
|
||||
blurHash = type.info?.blurhash,
|
||||
)
|
||||
is VideoMessageType -> AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource,
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.Video,
|
||||
blurHash = type.info?.blurhash,
|
||||
)
|
||||
is FileMessageType -> AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource,
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.File,
|
||||
)
|
||||
is LocationMessageType -> AttachmentThumbnailInfo(
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.Location,
|
||||
)
|
||||
is AudioMessageType -> AttachmentThumbnailInfo(
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.Audio,
|
||||
)
|
||||
is VoiceMessageType -> AttachmentThumbnailInfo(
|
||||
type = AttachmentThumbnailType.Voice,
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
is PollContent -> AttachmentThumbnailInfo(
|
||||
textContent = eventContent.question,
|
||||
type = AttachmentThumbnailType.Poll,
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun textForInReplyTo(inReplyTo: InReplyToDetails): String {
|
||||
return when (val eventContent = inReplyTo.eventContent) {
|
||||
is MessageContent -> when (eventContent.type) {
|
||||
is LocationMessageType -> stringResource(CommonStrings.common_shared_location)
|
||||
is VoiceMessageType -> stringResource(CommonStrings.common_voice_message)
|
||||
else -> inReplyTo.textContent ?: eventContent.body
|
||||
}
|
||||
is PollContent -> eventContent.question
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun TimelineItemEventRowPreview() = ElementPreview {
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.messages.impl.timeline.model
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.PollContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
|
||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
|
||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
|
||||
@Immutable
|
||||
internal sealed interface InReplyToMetadata {
|
||||
|
||||
val text: String?
|
||||
|
||||
data class Thumbnail(
|
||||
val attachmentThumbnailInfo: AttachmentThumbnailInfo
|
||||
) : InReplyToMetadata {
|
||||
override val text: String? = attachmentThumbnailInfo.textContent
|
||||
}
|
||||
|
||||
data class Text(
|
||||
override val text: String
|
||||
) : InReplyToMetadata
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes metadata for the in reply to message.
|
||||
*
|
||||
* Metadata can be either a thumbnail with a text OR just a text.
|
||||
*/
|
||||
@Composable
|
||||
internal fun InReplyToDetails.metadata(): InReplyToMetadata? = when (eventContent) {
|
||||
is MessageContent -> when (val type = eventContent.type) {
|
||||
is ImageMessageType -> InReplyToMetadata.Thumbnail(
|
||||
AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource ?: type.source,
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.Image,
|
||||
blurHash = type.info?.blurhash,
|
||||
)
|
||||
)
|
||||
is VideoMessageType -> InReplyToMetadata.Thumbnail(
|
||||
AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource,
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.Video,
|
||||
blurHash = type.info?.blurhash,
|
||||
)
|
||||
)
|
||||
is FileMessageType -> InReplyToMetadata.Thumbnail(
|
||||
AttachmentThumbnailInfo(
|
||||
thumbnailSource = type.info?.thumbnailSource,
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.File,
|
||||
)
|
||||
)
|
||||
is LocationMessageType -> InReplyToMetadata.Thumbnail(
|
||||
AttachmentThumbnailInfo(
|
||||
textContent = stringResource(CommonStrings.common_shared_location),
|
||||
type = AttachmentThumbnailType.Location,
|
||||
)
|
||||
)
|
||||
is AudioMessageType -> InReplyToMetadata.Thumbnail(
|
||||
AttachmentThumbnailInfo(
|
||||
textContent = eventContent.body,
|
||||
type = AttachmentThumbnailType.Audio,
|
||||
)
|
||||
)
|
||||
is VoiceMessageType -> InReplyToMetadata.Thumbnail(
|
||||
AttachmentThumbnailInfo(
|
||||
textContent = stringResource(CommonStrings.common_voice_message),
|
||||
type = AttachmentThumbnailType.Voice,
|
||||
)
|
||||
)
|
||||
else -> InReplyToMetadata.Text(textContent ?: eventContent.body)
|
||||
}
|
||||
is PollContent -> InReplyToMetadata.Thumbnail(
|
||||
AttachmentThumbnailInfo(
|
||||
textContent = eventContent.question,
|
||||
type = AttachmentThumbnailType.Poll,
|
||||
)
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.messages.impl.timeline.model
|
||||
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
||||
internal class TimelineItemGroupPositionProvider : PreviewParameterProvider<TimelineItemGroupPosition> {
|
||||
override val values = sequenceOf(
|
||||
TimelineItemGroupPosition.First,
|
||||
TimelineItemGroupPosition.Middle,
|
||||
TimelineItemGroupPosition.Last,
|
||||
TimelineItemGroupPosition.None,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.features.messages.impl.timeline.model
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import app.cash.molecule.RecompositionMode
|
||||
import app.cash.molecule.moleculeFlow
|
||||
import app.cash.turbine.test
|
||||
import com.google.common.truth.Truth
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.media.AudioInfo
|
||||
import io.element.android.libraries.matrix.api.media.FileInfo
|
||||
import io.element.android.libraries.matrix.api.media.VideoInfo
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.ImageMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.LocationMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.VoiceMessageType
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.media.aMediaSource
|
||||
import io.element.android.libraries.matrix.test.room.aMessageContent
|
||||
import io.element.android.libraries.matrix.test.room.aPollContent
|
||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailInfo
|
||||
import io.element.android.libraries.matrix.ui.components.AttachmentThumbnailType
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class InReplyToMetadataKtTest {
|
||||
@Test
|
||||
fun `any message content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
anInReplyToDetails(eventContent = aMessageContent()).metadata()
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(InReplyToMetadata.Text("textContent"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `an image message content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
anInReplyToDetails(
|
||||
eventContent = aMessageContent(
|
||||
messageType = ImageMessageType(
|
||||
body = "body",
|
||||
source = aMediaSource(),
|
||||
info = null,
|
||||
)
|
||||
)
|
||||
).metadata()
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(
|
||||
InReplyToMetadata.Thumbnail(
|
||||
attachmentThumbnailInfo = AttachmentThumbnailInfo(
|
||||
thumbnailSource = aMediaSource(),
|
||||
textContent = "body",
|
||||
type = AttachmentThumbnailType.Image,
|
||||
blurHash = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a video message content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
anInReplyToDetails(
|
||||
eventContent = aMessageContent(
|
||||
messageType = VideoMessageType(
|
||||
body = "body",
|
||||
source = aMediaSource(),
|
||||
info = VideoInfo(
|
||||
duration = null,
|
||||
height = null,
|
||||
width = null,
|
||||
mimetype = null,
|
||||
size = null,
|
||||
thumbnailInfo = null,
|
||||
thumbnailSource = aMediaSource(),
|
||||
blurhash = null
|
||||
),
|
||||
)
|
||||
)
|
||||
).metadata()
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(
|
||||
InReplyToMetadata.Thumbnail(
|
||||
attachmentThumbnailInfo = AttachmentThumbnailInfo(
|
||||
thumbnailSource = aMediaSource(),
|
||||
textContent = "body",
|
||||
type = AttachmentThumbnailType.Video,
|
||||
blurHash = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a file message content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
anInReplyToDetails(
|
||||
eventContent = aMessageContent(
|
||||
messageType = FileMessageType(
|
||||
body = "body",
|
||||
source = aMediaSource(),
|
||||
info = FileInfo(
|
||||
mimetype = null,
|
||||
size = null,
|
||||
thumbnailInfo = null,
|
||||
thumbnailSource = aMediaSource(),
|
||||
),
|
||||
)
|
||||
)
|
||||
).metadata()
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(
|
||||
InReplyToMetadata.Thumbnail(
|
||||
attachmentThumbnailInfo = AttachmentThumbnailInfo(
|
||||
thumbnailSource = aMediaSource(),
|
||||
textContent = "body",
|
||||
type = AttachmentThumbnailType.File,
|
||||
blurHash = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a audio message content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
anInReplyToDetails(
|
||||
eventContent = aMessageContent(
|
||||
messageType = AudioMessageType(
|
||||
body = "body",
|
||||
source = aMediaSource(),
|
||||
info = AudioInfo(
|
||||
duration = null,
|
||||
size = null,
|
||||
mimetype = null
|
||||
),
|
||||
)
|
||||
)
|
||||
).metadata()
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(
|
||||
InReplyToMetadata.Thumbnail(
|
||||
attachmentThumbnailInfo = AttachmentThumbnailInfo(
|
||||
textContent = "body",
|
||||
type = AttachmentThumbnailType.Audio,
|
||||
blurHash = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a location message content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
testEnv {
|
||||
anInReplyToDetails(
|
||||
eventContent = aMessageContent(
|
||||
messageType = LocationMessageType(
|
||||
body = "body",
|
||||
geoUri = "geo:3.0,4.0;u=5.0",
|
||||
description = null,
|
||||
)
|
||||
)
|
||||
).metadata()
|
||||
}
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(
|
||||
InReplyToMetadata.Thumbnail(
|
||||
attachmentThumbnailInfo = AttachmentThumbnailInfo(
|
||||
thumbnailSource = null,
|
||||
textContent = "Shared location",
|
||||
type = AttachmentThumbnailType.Location,
|
||||
blurHash = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a voice message content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
testEnv {
|
||||
anInReplyToDetails(
|
||||
eventContent = aMessageContent(
|
||||
messageType = VoiceMessageType(
|
||||
body = "body",
|
||||
source = aMediaSource(),
|
||||
info = null,
|
||||
details = null,
|
||||
)
|
||||
)
|
||||
).metadata()
|
||||
}
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(
|
||||
InReplyToMetadata.Thumbnail(
|
||||
attachmentThumbnailInfo = AttachmentThumbnailInfo(
|
||||
thumbnailSource = null,
|
||||
textContent = "Voice message",
|
||||
type = AttachmentThumbnailType.Voice,
|
||||
blurHash = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `a poll content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
anInReplyToDetails(
|
||||
eventContent = aPollContent()
|
||||
).metadata()
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(
|
||||
InReplyToMetadata.Thumbnail(
|
||||
attachmentThumbnailInfo = AttachmentThumbnailInfo(
|
||||
thumbnailSource = null,
|
||||
textContent = "Do you like polls?",
|
||||
type = AttachmentThumbnailType.Poll,
|
||||
blurHash = null,
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `any other content`() = runTest {
|
||||
moleculeFlow(RecompositionMode.Immediate) {
|
||||
anInReplyToDetails(
|
||||
eventContent = RedactedContent
|
||||
).metadata()
|
||||
}.test {
|
||||
awaitItem().let {
|
||||
Truth.assertThat(it).isEqualTo(null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun anInReplyToDetails(
|
||||
eventId: EventId = AN_EVENT_ID,
|
||||
senderId: UserId = A_USER_ID,
|
||||
senderDisplayName: String? = "senderDisplayName",
|
||||
senderAvatarUrl: String? = "senderAvatarUrl",
|
||||
eventContent: EventContent? = aMessageContent(),
|
||||
textContent: String? = "textContent",
|
||||
) = InReplyToDetails(
|
||||
eventId = eventId,
|
||||
senderId = senderId,
|
||||
senderDisplayName = senderDisplayName,
|
||||
senderAvatarUrl = senderAvatarUrl,
|
||||
eventContent = eventContent,
|
||||
textContent = textContent,
|
||||
)
|
||||
|
||||
@Composable
|
||||
private fun testEnv(content: @Composable () -> Any?): Any? {
|
||||
var result: Any? = null
|
||||
CompositionLocalProvider(
|
||||
LocalConfiguration provides Configuration(),
|
||||
LocalContext provides ApplicationProvider.getApplicationContext(),
|
||||
) {
|
||||
content().apply {
|
||||
result = this
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user