Merge pull request #7566 from vector-im/fix/mna/missing-translation-reply-to
Missing translations on "replyTo" messages (PSG-978)
This commit is contained in:
commit
14de485c67
|
@ -0,0 +1 @@
|
||||||
|
Missing translations on "replyTo" messages
|
|
@ -3464,4 +3464,13 @@
|
||||||
<string name="rich_text_editor_format_underline">Apply underline format</string>
|
<string name="rich_text_editor_format_underline">Apply underline format</string>
|
||||||
<string name="rich_text_editor_full_screen_toggle">Toggle full screen mode</string>
|
<string name="rich_text_editor_full_screen_toggle">Toggle full screen mode</string>
|
||||||
|
|
||||||
|
<!-- ReplyTo events -->
|
||||||
|
<string name="message_reply_to_prefix">In reply to</string>
|
||||||
|
<string name="message_reply_to_sender_sent_file">sent a file.</string>
|
||||||
|
<string name="message_reply_to_sender_sent_audio_file">sent an audio file.</string>
|
||||||
|
<string name="message_reply_to_sender_sent_voice_message">sent a voice message.</string>
|
||||||
|
<string name="message_reply_to_sender_sent_image">sent an image.</string>
|
||||||
|
<string name="message_reply_to_sender_sent_video">sent a video.</string>
|
||||||
|
<string name="message_reply_to_sender_sent_sticker">sent a sticker.</string>
|
||||||
|
<string name="message_reply_to_sender_created_poll">created a poll.</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -33,6 +33,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageStickerConte
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
import org.matrix.android.sdk.api.session.room.model.message.MessageType
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
|
import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.relation.isReply
|
||||||
import org.matrix.android.sdk.api.session.room.model.relation.shouldRenderInThread
|
import org.matrix.android.sdk.api.session.room.model.relation.shouldRenderInThread
|
||||||
import org.matrix.android.sdk.api.session.room.send.SendState
|
import org.matrix.android.sdk.api.session.room.send.SendState
|
||||||
import org.matrix.android.sdk.api.session.threads.ThreadDetails
|
import org.matrix.android.sdk.api.session.threads.ThreadDetails
|
||||||
|
@ -228,11 +229,14 @@ data class Event(
|
||||||
return when {
|
return when {
|
||||||
isReplyRenderedInThread() || isQuote() -> ContentUtils.extractUsefulTextFromReply(text)
|
isReplyRenderedInThread() || isQuote() -> ContentUtils.extractUsefulTextFromReply(text)
|
||||||
isFileMessage() -> "sent a file."
|
isFileMessage() -> "sent a file."
|
||||||
|
isVoiceMessage() -> "sent a voice message."
|
||||||
isAudioMessage() -> "sent an audio file."
|
isAudioMessage() -> "sent an audio file."
|
||||||
isImageMessage() -> "sent an image."
|
isImageMessage() -> "sent an image."
|
||||||
isVideoMessage() -> "sent a video."
|
isVideoMessage() -> "sent a video."
|
||||||
isSticker() -> "sent a sticker"
|
isSticker() -> "sent a sticker."
|
||||||
isPoll() -> getPollQuestion() ?: "created a poll."
|
isPoll() -> getPollQuestion() ?: "created a poll."
|
||||||
|
isLiveLocation() -> "Live location."
|
||||||
|
isLocationMessage() -> "has shared their location."
|
||||||
else -> text
|
else -> text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,7 +424,7 @@ fun Event.getRelationContentForType(type: String): RelationDefaultContent? =
|
||||||
getRelationContent()?.takeIf { it.type == type }
|
getRelationContent()?.takeIf { it.type == type }
|
||||||
|
|
||||||
fun Event.isReply(): Boolean {
|
fun Event.isReply(): Boolean {
|
||||||
return getRelationContent()?.inReplyTo?.eventId != null
|
return getRelationContent().isReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Event.isReplyRenderedInThread(): Boolean {
|
fun Event.isReplyRenderedInThread(): Boolean {
|
||||||
|
@ -443,7 +447,7 @@ fun Event.isInvitation(): Boolean = type == EventType.STATE_ROOM_MEMBER &&
|
||||||
content?.toModel<RoomMemberContent>()?.membership == Membership.INVITE
|
content?.toModel<RoomMemberContent>()?.membership == Membership.INVITE
|
||||||
|
|
||||||
fun Event.getPollContent(): MessagePollContent? {
|
fun Event.getPollContent(): MessagePollContent? {
|
||||||
return content.toModel<MessagePollContent>()
|
return getClearContent().toModel<MessagePollContent>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Event.supportsNotification() =
|
fun Event.supportsNotification() =
|
||||||
|
|
|
@ -47,10 +47,9 @@ interface LocationSharingService {
|
||||||
/**
|
/**
|
||||||
* Starts sharing live location in the room.
|
* Starts sharing live location in the room.
|
||||||
* @param timeoutMillis timeout of the live in milliseconds
|
* @param timeoutMillis timeout of the live in milliseconds
|
||||||
* @param description description of the live for text fallback
|
|
||||||
* @return the result of the update of the live
|
* @return the result of the update of the live
|
||||||
*/
|
*/
|
||||||
suspend fun startLiveLocationShare(timeoutMillis: Long, description: String): UpdateLiveLocationShareResult
|
suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stops sharing live location in the room.
|
* Stops sharing live location in the room.
|
||||||
|
|
|
@ -28,3 +28,5 @@ data class RelationDefaultContent(
|
||||||
) : RelationContent
|
) : RelationContent
|
||||||
|
|
||||||
fun RelationDefaultContent.shouldRenderInThread(): Boolean = isFallingBack == false
|
fun RelationDefaultContent.shouldRenderInThread(): Boolean = isFallingBack == false
|
||||||
|
|
||||||
|
fun RelationDefaultContent?.isReply(): Boolean = this?.inReplyTo?.eventId != null
|
||||||
|
|
|
@ -73,7 +73,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
|
||||||
return sendLiveLocationTask.execute(params)
|
return sendLiveLocationTask.execute(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun startLiveLocationShare(timeoutMillis: Long, description: String): UpdateLiveLocationShareResult {
|
override suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult {
|
||||||
// Ensure to stop any active live before starting a new one
|
// Ensure to stop any active live before starting a new one
|
||||||
if (checkIfExistingActiveLive()) {
|
if (checkIfExistingActiveLive()) {
|
||||||
val result = stopLiveLocationShare()
|
val result = stopLiveLocationShare()
|
||||||
|
@ -84,7 +84,6 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
|
||||||
val params = StartLiveLocationShareTask.Params(
|
val params = StartLiveLocationShareTask.Params(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
timeoutMillis = timeoutMillis,
|
timeoutMillis = timeoutMillis,
|
||||||
description = description
|
|
||||||
)
|
)
|
||||||
return startLiveLocationShareTask.execute(params)
|
return startLiveLocationShareTask.execute(params)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@ internal interface StartLiveLocationShareTask : Task<StartLiveLocationShareTask.
|
||||||
data class Params(
|
data class Params(
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
val timeoutMillis: Long,
|
val timeoutMillis: Long,
|
||||||
val description: String,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ internal class DefaultStartLiveLocationShareTask @Inject constructor(
|
||||||
|
|
||||||
override suspend fun execute(params: StartLiveLocationShareTask.Params): UpdateLiveLocationShareResult {
|
override suspend fun execute(params: StartLiveLocationShareTask.Params): UpdateLiveLocationShareResult {
|
||||||
val beaconContent = MessageBeaconInfoContent(
|
val beaconContent = MessageBeaconInfoContent(
|
||||||
body = params.description,
|
body = "Live location",
|
||||||
timeout = params.timeoutMillis,
|
timeout = params.timeoutMillis,
|
||||||
isLive = true,
|
isLive = true,
|
||||||
unstableTimestampMillis = clock.epochMillis()
|
unstableTimestampMillis = clock.epochMillis()
|
||||||
|
|
|
@ -53,7 +53,6 @@ private const val A_LATITUDE = 1.4
|
||||||
private const val A_LONGITUDE = 40.0
|
private const val A_LONGITUDE = 40.0
|
||||||
private const val AN_UNCERTAINTY = 5.0
|
private const val AN_UNCERTAINTY = 5.0
|
||||||
private const val A_TIMEOUT = 15_000L
|
private const val A_TIMEOUT = 15_000L
|
||||||
private const val A_DESCRIPTION = "description"
|
|
||||||
private const val A_REASON = "reason"
|
private const val A_REASON = "reason"
|
||||||
|
|
||||||
@ExperimentalCoroutinesApi
|
@ExperimentalCoroutinesApi
|
||||||
|
@ -143,7 +142,7 @@ internal class DefaultLocationSharingServiceTest {
|
||||||
coEvery { stopLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success("stopped-event-id")
|
coEvery { stopLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success("stopped-event-id")
|
||||||
coEvery { startLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
coEvery { startLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
||||||
|
|
||||||
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT, A_DESCRIPTION)
|
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
|
||||||
|
|
||||||
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
||||||
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
|
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
|
||||||
|
@ -157,7 +156,6 @@ internal class DefaultLocationSharingServiceTest {
|
||||||
val expectedStartParams = StartLiveLocationShareTask.Params(
|
val expectedStartParams = StartLiveLocationShareTask.Params(
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
timeoutMillis = A_TIMEOUT,
|
timeoutMillis = A_TIMEOUT,
|
||||||
description = A_DESCRIPTION
|
|
||||||
)
|
)
|
||||||
coVerify { startLiveLocationShareTask.execute(expectedStartParams) }
|
coVerify { startLiveLocationShareTask.execute(expectedStartParams) }
|
||||||
}
|
}
|
||||||
|
@ -168,7 +166,7 @@ internal class DefaultLocationSharingServiceTest {
|
||||||
val error = Throwable()
|
val error = Throwable()
|
||||||
coEvery { stopLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Failure(error)
|
coEvery { stopLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Failure(error)
|
||||||
|
|
||||||
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT, A_DESCRIPTION)
|
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
|
||||||
|
|
||||||
result shouldBeEqualTo UpdateLiveLocationShareResult.Failure(error)
|
result shouldBeEqualTo UpdateLiveLocationShareResult.Failure(error)
|
||||||
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
|
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
|
||||||
|
@ -186,7 +184,7 @@ internal class DefaultLocationSharingServiceTest {
|
||||||
coEvery { checkIfExistingActiveLiveTask.execute(any()) } returns false
|
coEvery { checkIfExistingActiveLiveTask.execute(any()) } returns false
|
||||||
coEvery { startLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
coEvery { startLiveLocationShareTask.execute(any()) } returns UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
||||||
|
|
||||||
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT, A_DESCRIPTION)
|
val result = defaultLocationSharingService.startLiveLocationShare(A_TIMEOUT)
|
||||||
|
|
||||||
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
||||||
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
|
val expectedCheckExistingParams = CheckIfExistingActiveLiveTask.Params(
|
||||||
|
@ -196,7 +194,6 @@ internal class DefaultLocationSharingServiceTest {
|
||||||
val expectedStartParams = StartLiveLocationShareTask.Params(
|
val expectedStartParams = StartLiveLocationShareTask.Params(
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
timeoutMillis = A_TIMEOUT,
|
timeoutMillis = A_TIMEOUT,
|
||||||
description = A_DESCRIPTION
|
|
||||||
)
|
)
|
||||||
coVerify { startLiveLocationShareTask.execute(expectedStartParams) }
|
coVerify { startLiveLocationShareTask.execute(expectedStartParams) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ import org.matrix.android.sdk.test.fakes.FakeSendStateTask
|
||||||
private const val A_USER_ID = "user-id"
|
private const val A_USER_ID = "user-id"
|
||||||
private const val A_ROOM_ID = "room-id"
|
private const val A_ROOM_ID = "room-id"
|
||||||
private const val AN_EVENT_ID = "event-id"
|
private const val AN_EVENT_ID = "event-id"
|
||||||
private const val A_DESCRIPTION = "description"
|
|
||||||
private const val A_TIMEOUT = 15_000L
|
private const val A_TIMEOUT = 15_000L
|
||||||
private const val AN_EPOCH = 1655210176L
|
private const val AN_EPOCH = 1655210176L
|
||||||
|
|
||||||
|
@ -60,7 +59,6 @@ internal class DefaultStartLiveLocationShareTaskTest {
|
||||||
val params = StartLiveLocationShareTask.Params(
|
val params = StartLiveLocationShareTask.Params(
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
timeoutMillis = A_TIMEOUT,
|
timeoutMillis = A_TIMEOUT,
|
||||||
description = A_DESCRIPTION
|
|
||||||
)
|
)
|
||||||
fakeClock.givenEpoch(AN_EPOCH)
|
fakeClock.givenEpoch(AN_EPOCH)
|
||||||
fakeSendStateTask.givenExecuteRetryReturns(AN_EVENT_ID)
|
fakeSendStateTask.givenExecuteRetryReturns(AN_EVENT_ID)
|
||||||
|
@ -69,7 +67,7 @@ internal class DefaultStartLiveLocationShareTaskTest {
|
||||||
|
|
||||||
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
result shouldBeEqualTo UpdateLiveLocationShareResult.Success(AN_EVENT_ID)
|
||||||
val expectedBeaconContent = MessageBeaconInfoContent(
|
val expectedBeaconContent = MessageBeaconInfoContent(
|
||||||
body = A_DESCRIPTION,
|
body = "Live location",
|
||||||
timeout = params.timeoutMillis,
|
timeout = params.timeoutMillis,
|
||||||
isLive = true,
|
isLive = true,
|
||||||
unstableTimestampMillis = AN_EPOCH
|
unstableTimestampMillis = AN_EPOCH
|
||||||
|
@ -91,7 +89,6 @@ internal class DefaultStartLiveLocationShareTaskTest {
|
||||||
val params = StartLiveLocationShareTask.Params(
|
val params = StartLiveLocationShareTask.Params(
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
timeoutMillis = A_TIMEOUT,
|
timeoutMillis = A_TIMEOUT,
|
||||||
description = A_DESCRIPTION
|
|
||||||
)
|
)
|
||||||
fakeClock.givenEpoch(AN_EPOCH)
|
fakeClock.givenEpoch(AN_EPOCH)
|
||||||
fakeSendStateTask.givenExecuteRetryReturns("")
|
fakeSendStateTask.givenExecuteRetryReturns("")
|
||||||
|
@ -106,7 +103,6 @@ internal class DefaultStartLiveLocationShareTaskTest {
|
||||||
val params = StartLiveLocationShareTask.Params(
|
val params = StartLiveLocationShareTask.Params(
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
timeoutMillis = A_TIMEOUT,
|
timeoutMillis = A_TIMEOUT,
|
||||||
description = A_DESCRIPTION
|
|
||||||
)
|
)
|
||||||
fakeClock.givenEpoch(AN_EPOCH)
|
fakeClock.givenEpoch(AN_EPOCH)
|
||||||
val error = Throwable()
|
val error = Throwable()
|
||||||
|
|
|
@ -65,6 +65,7 @@ import im.vector.app.features.home.room.detail.timeline.item.RedactedMessageItem
|
||||||
import im.vector.app.features.home.room.detail.timeline.item.VerificationRequestItem
|
import im.vector.app.features.home.room.detail.timeline.item.VerificationRequestItem
|
||||||
import im.vector.app.features.home.room.detail.timeline.item.VerificationRequestItem_
|
import im.vector.app.features.home.room.detail.timeline.item.VerificationRequestItem_
|
||||||
import im.vector.app.features.home.room.detail.timeline.render.EventTextRenderer
|
import im.vector.app.features.home.room.detail.timeline.render.EventTextRenderer
|
||||||
|
import im.vector.app.features.home.room.detail.timeline.render.ProcessBodyOfReplyToEventUseCase
|
||||||
import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
|
import im.vector.app.features.home.room.detail.timeline.tools.createLinkMovementMethod
|
||||||
import im.vector.app.features.home.room.detail.timeline.tools.linkify
|
import im.vector.app.features.home.room.detail.timeline.tools.linkify
|
||||||
import im.vector.app.features.html.EventHtmlRenderer
|
import im.vector.app.features.html.EventHtmlRenderer
|
||||||
|
@ -106,6 +107,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageVideoContent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
|
import org.matrix.android.sdk.api.session.room.model.message.asMessageAudioEvent
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
import org.matrix.android.sdk.api.session.room.model.message.getFileUrl
|
||||||
import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl
|
import org.matrix.android.sdk.api.session.room.model.message.getThumbnailUrl
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
|
||||||
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
|
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
|
||||||
import org.matrix.android.sdk.api.util.MimeTypes
|
import org.matrix.android.sdk.api.util.MimeTypes
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -139,6 +141,7 @@ class MessageItemFactory @Inject constructor(
|
||||||
private val liveLocationShareMessageItemFactory: LiveLocationShareMessageItemFactory,
|
private val liveLocationShareMessageItemFactory: LiveLocationShareMessageItemFactory,
|
||||||
private val pollItemViewStateFactory: PollItemViewStateFactory,
|
private val pollItemViewStateFactory: PollItemViewStateFactory,
|
||||||
private val voiceBroadcastItemFactory: VoiceBroadcastItemFactory,
|
private val voiceBroadcastItemFactory: VoiceBroadcastItemFactory,
|
||||||
|
private val processBodyOfReplyToEventUseCase: ProcessBodyOfReplyToEventUseCase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// TODO inject this properly?
|
// TODO inject this properly?
|
||||||
|
@ -200,7 +203,7 @@ class MessageItemFactory @Inject constructor(
|
||||||
is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
|
is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
|
||||||
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
|
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
|
||||||
is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, attributes)
|
is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, attributes)
|
||||||
is MessageBeaconInfoContent -> liveLocationShareMessageItemFactory.create(params.event, highlight, attributes)
|
is MessageBeaconInfoContent -> liveLocationShareMessageItemFactory.create(event, highlight, attributes)
|
||||||
is MessageVoiceBroadcastInfoContent -> voiceBroadcastItemFactory.create(params, messageContent, highlight, attributes)
|
is MessageVoiceBroadcastInfoContent -> voiceBroadcastItemFactory.create(params, messageContent, highlight, attributes)
|
||||||
else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes)
|
else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes)
|
||||||
}
|
}
|
||||||
|
@ -437,7 +440,14 @@ class MessageItemFactory @Inject constructor(
|
||||||
attributes: AbsMessageItem.Attributes
|
attributes: AbsMessageItem.Attributes
|
||||||
): MessageTextItem? {
|
): MessageTextItem? {
|
||||||
// For compatibility reason we should display the body
|
// For compatibility reason we should display the body
|
||||||
return buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
|
return buildMessageTextItem(
|
||||||
|
messageContent.body,
|
||||||
|
false,
|
||||||
|
informationData,
|
||||||
|
highlight,
|
||||||
|
callback,
|
||||||
|
attributes,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildImageMessageItem(
|
private fun buildImageMessageItem(
|
||||||
|
@ -540,7 +550,8 @@ class MessageItemFactory @Inject constructor(
|
||||||
): VectorEpoxyModel<*>? {
|
): VectorEpoxyModel<*>? {
|
||||||
val matrixFormattedBody = messageContent.matrixFormattedBody
|
val matrixFormattedBody = messageContent.matrixFormattedBody
|
||||||
return if (matrixFormattedBody != null) {
|
return if (matrixFormattedBody != null) {
|
||||||
buildFormattedTextItem(matrixFormattedBody, informationData, highlight, callback, attributes)
|
val replyToContent = messageContent.relatesTo?.inReplyTo
|
||||||
|
buildFormattedTextItem(matrixFormattedBody, informationData, highlight, callback, attributes, replyToContent)
|
||||||
} else {
|
} else {
|
||||||
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
|
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
|
||||||
}
|
}
|
||||||
|
@ -552,10 +563,21 @@ class MessageItemFactory @Inject constructor(
|
||||||
highlight: Boolean,
|
highlight: Boolean,
|
||||||
callback: TimelineEventController.Callback?,
|
callback: TimelineEventController.Callback?,
|
||||||
attributes: AbsMessageItem.Attributes,
|
attributes: AbsMessageItem.Attributes,
|
||||||
|
replyToContent: ReplyToContent?,
|
||||||
): MessageTextItem? {
|
): MessageTextItem? {
|
||||||
val compressed = htmlCompressor.compress(matrixFormattedBody)
|
val processedBody = replyToContent
|
||||||
|
?.let { processBodyOfReplyToEventUseCase.execute(roomId, matrixFormattedBody, it) }
|
||||||
|
?: matrixFormattedBody
|
||||||
|
val compressed = htmlCompressor.compress(processedBody)
|
||||||
val renderedFormattedBody = htmlRenderer.get().render(compressed, pillsPostProcessor) as Spanned
|
val renderedFormattedBody = htmlRenderer.get().render(compressed, pillsPostProcessor) as Spanned
|
||||||
return buildMessageTextItem(renderedFormattedBody, true, informationData, highlight, callback, attributes)
|
return buildMessageTextItem(
|
||||||
|
renderedFormattedBody,
|
||||||
|
true,
|
||||||
|
informationData,
|
||||||
|
highlight,
|
||||||
|
callback,
|
||||||
|
attributes,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildMessageTextItem(
|
private fun buildMessageTextItem(
|
||||||
|
|
|
@ -34,22 +34,22 @@ class EventTextRenderer @AssistedInject constructor(
|
||||||
@Assisted private val roomId: String?,
|
@Assisted private val roomId: String?,
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val avatarRenderer: AvatarRenderer,
|
private val avatarRenderer: AvatarRenderer,
|
||||||
private val sessionHolder: ActiveSessionHolder
|
private val activeSessionHolder: ActiveSessionHolder,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
/* ==========================================================================================
|
|
||||||
* Public api
|
|
||||||
* ========================================================================================== */
|
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(roomId: String?): EventTextRenderer
|
fun create(roomId: String?): EventTextRenderer
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param text the text you want to render
|
* @param text the text to be rendered
|
||||||
*/
|
*/
|
||||||
fun render(text: CharSequence): CharSequence {
|
fun render(text: CharSequence): CharSequence {
|
||||||
|
return renderNotifyEveryone(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun renderNotifyEveryone(text: CharSequence): CharSequence {
|
||||||
return if (roomId != null && text.contains(MatrixItem.NOTIFY_EVERYONE)) {
|
return if (roomId != null && text.contains(MatrixItem.NOTIFY_EVERYONE)) {
|
||||||
SpannableStringBuilder(text).apply {
|
SpannableStringBuilder(text).apply {
|
||||||
addNotifyEveryoneSpans(this, roomId)
|
addNotifyEveryoneSpans(this, roomId)
|
||||||
|
@ -59,12 +59,8 @@ class EventTextRenderer @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ==========================================================================================
|
|
||||||
* Helper methods
|
|
||||||
* ========================================================================================== */
|
|
||||||
|
|
||||||
private fun addNotifyEveryoneSpans(text: Spannable, roomId: String) {
|
private fun addNotifyEveryoneSpans(text: Spannable, roomId: String) {
|
||||||
val room: RoomSummary? = sessionHolder.getSafeActiveSession()?.roomService()?.getRoomSummary(roomId)
|
val room: RoomSummary? = activeSessionHolder.getSafeActiveSession()?.roomService()?.getRoomSummary(roomId)
|
||||||
val matrixItem = MatrixItem.EveryoneInRoomItem(
|
val matrixItem = MatrixItem.EveryoneInRoomItem(
|
||||||
id = roomId,
|
id = roomId,
|
||||||
avatarUrl = room?.avatarUrl,
|
avatarUrl = room?.avatarUrl,
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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 im.vector.app.features.home.room.detail.timeline.render
|
||||||
|
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
|
import im.vector.app.core.resources.StringProvider
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.getPollQuestion
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isAudioMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isFileMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isImageMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isLiveLocation
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isPoll
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isSticker
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isVideoMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isVoiceMessage
|
||||||
|
import org.matrix.android.sdk.api.session.getRoom
|
||||||
|
import org.matrix.android.sdk.api.session.room.getTimelineEvent
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
private const val IN_REPLY_TO = "In reply to"
|
||||||
|
private const val BREAKING_LINE = "<br />"
|
||||||
|
private const val ENDING_BLOCK_QUOTE = "</blockquote>"
|
||||||
|
|
||||||
|
class ProcessBodyOfReplyToEventUseCase @Inject constructor(
|
||||||
|
private val activeSessionHolder: ActiveSessionHolder,
|
||||||
|
private val stringProvider: StringProvider,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun execute(roomId: String, matrixFormattedBody: String, replyToContent: ReplyToContent): String {
|
||||||
|
val repliedToEvent = replyToContent.eventId?.let { getEvent(it, roomId) }
|
||||||
|
val breakingLineIndex = matrixFormattedBody.indexOf(BREAKING_LINE)
|
||||||
|
val endOfBlockQuoteIndex = matrixFormattedBody.lastIndexOf(ENDING_BLOCK_QUOTE)
|
||||||
|
|
||||||
|
val withTranslatedContent = if (repliedToEvent != null && breakingLineIndex != -1 && endOfBlockQuoteIndex != -1) {
|
||||||
|
val afterBreakingLineIndex = breakingLineIndex + BREAKING_LINE.length
|
||||||
|
when {
|
||||||
|
repliedToEvent.isFileMessage() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
stringProvider.getString(R.string.message_reply_to_sender_sent_file)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
repliedToEvent.isVoiceMessage() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
stringProvider.getString(R.string.message_reply_to_sender_sent_voice_message)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
repliedToEvent.isAudioMessage() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
stringProvider.getString(R.string.message_reply_to_sender_sent_audio_file)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
repliedToEvent.isImageMessage() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
stringProvider.getString(R.string.message_reply_to_sender_sent_image)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
repliedToEvent.isVideoMessage() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
stringProvider.getString(R.string.message_reply_to_sender_sent_video)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
repliedToEvent.isSticker() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
stringProvider.getString(R.string.message_reply_to_sender_sent_sticker)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
repliedToEvent.isPoll() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
repliedToEvent.getPollQuestion() ?: stringProvider.getString(R.string.message_reply_to_sender_created_poll)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
repliedToEvent.isLiveLocation() -> {
|
||||||
|
matrixFormattedBody.replaceRange(
|
||||||
|
afterBreakingLineIndex,
|
||||||
|
endOfBlockQuoteIndex,
|
||||||
|
stringProvider.getString(R.string.live_location_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> matrixFormattedBody
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
matrixFormattedBody
|
||||||
|
}
|
||||||
|
|
||||||
|
return withTranslatedContent.replace(
|
||||||
|
IN_REPLY_TO,
|
||||||
|
stringProvider.getString(R.string.message_reply_to_prefix)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getEvent(eventId: String, roomId: String) =
|
||||||
|
activeSessionHolder.getSafeActiveSession()
|
||||||
|
?.getRoom(roomId)
|
||||||
|
?.getTimelineEvent(eventId)
|
||||||
|
?.root
|
||||||
|
}
|
|
@ -21,7 +21,6 @@ import android.os.IBinder
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import im.vector.app.R
|
|
||||||
import im.vector.app.core.di.ActiveSessionHolder
|
import im.vector.app.core.di.ActiveSessionHolder
|
||||||
import im.vector.app.core.services.VectorAndroidService
|
import im.vector.app.core.services.VectorAndroidService
|
||||||
import im.vector.app.features.location.LocationData
|
import im.vector.app.features.location.LocationData
|
||||||
|
@ -125,10 +124,7 @@ class LocationSharingAndroidService : VectorAndroidService(), LocationTracker.Ca
|
||||||
val updateLiveResult = session
|
val updateLiveResult = session
|
||||||
.getRoom(roomArgs.roomId)
|
.getRoom(roomArgs.roomId)
|
||||||
?.locationSharingService()
|
?.locationSharingService()
|
||||||
?.startLiveLocationShare(
|
?.startLiveLocationShare(roomArgs.durationMillis)
|
||||||
timeoutMillis = roomArgs.durationMillis,
|
|
||||||
description = getString(R.string.live_location_description)
|
|
||||||
)
|
|
||||||
|
|
||||||
updateLiveResult
|
updateLiveResult
|
||||||
?.let { result ->
|
?.let { result ->
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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 im.vector.app.features.home.room.detail.timeline.render
|
||||||
|
|
||||||
|
import android.annotation.StringRes
|
||||||
|
import im.vector.app.R
|
||||||
|
import im.vector.app.test.fakes.FakeActiveSessionHolder
|
||||||
|
import im.vector.app.test.fakes.FakeStringProvider
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.mockkStatic
|
||||||
|
import io.mockk.unmockkAll
|
||||||
|
import org.amshove.kluent.shouldBeEqualTo
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.Event
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.getPollQuestion
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isAudioMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isFileMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isImageMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isLiveLocation
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isPoll
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isSticker
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isVideoMessage
|
||||||
|
import org.matrix.android.sdk.api.session.events.model.isVoiceMessage
|
||||||
|
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
|
||||||
|
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||||
|
|
||||||
|
private const val A_ROOM_ID = "room-id"
|
||||||
|
private const val AN_EVENT_ID = "event-id"
|
||||||
|
private const val A_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY =
|
||||||
|
"<mx-reply>" +
|
||||||
|
"<blockquote>" +
|
||||||
|
"<a href=\"matrixToLink\">In reply to</a> " +
|
||||||
|
"<a href=\"matrixToLink\">@user:matrix.org</a>" +
|
||||||
|
"<br />" +
|
||||||
|
"Message content" +
|
||||||
|
"</blockquote>" +
|
||||||
|
"</mx-reply>" +
|
||||||
|
"Reply text"
|
||||||
|
private const val A_NEW_PREFIX = "new-prefix"
|
||||||
|
private const val A_NEW_CONTENT = "new-content"
|
||||||
|
private const val PREFIX_PROCESSED_ONLY_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY =
|
||||||
|
"<mx-reply>" +
|
||||||
|
"<blockquote>" +
|
||||||
|
"<a href=\"matrixToLink\">$A_NEW_PREFIX</a> " +
|
||||||
|
"<a href=\"matrixToLink\">@user:matrix.org</a>" +
|
||||||
|
"<br />" +
|
||||||
|
"Message content" +
|
||||||
|
"</blockquote>" +
|
||||||
|
"</mx-reply>" +
|
||||||
|
"Reply text"
|
||||||
|
private const val FULLY_PROCESSED_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY =
|
||||||
|
"<mx-reply>" +
|
||||||
|
"<blockquote>" +
|
||||||
|
"<a href=\"matrixToLink\">$A_NEW_PREFIX</a> " +
|
||||||
|
"<a href=\"matrixToLink\">@user:matrix.org</a>" +
|
||||||
|
"<br />" +
|
||||||
|
A_NEW_CONTENT +
|
||||||
|
"</blockquote>" +
|
||||||
|
"</mx-reply>" +
|
||||||
|
"Reply text"
|
||||||
|
|
||||||
|
class ProcessBodyOfReplyToEventUseCaseTest {
|
||||||
|
|
||||||
|
private val fakeActiveSessionHolder = FakeActiveSessionHolder()
|
||||||
|
private val fakeStringProvider = FakeStringProvider()
|
||||||
|
private val fakeReplyToContent = ReplyToContent(eventId = AN_EVENT_ID)
|
||||||
|
private val fakeRepliedEvent = givenARepliedEvent()
|
||||||
|
|
||||||
|
private val processBodyOfReplyToEventUseCase = ProcessBodyOfReplyToEventUseCase(
|
||||||
|
activeSessionHolder = fakeActiveSessionHolder.instance,
|
||||||
|
stringProvider = fakeStringProvider.instance,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
givenNewPrefix()
|
||||||
|
mockkStatic("org.matrix.android.sdk.api.session.events.model.EventKt")
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
unmockkAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type file message when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isFileMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_sent_file)
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type voice message when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isVoiceMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_sent_voice_message)
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type audio message when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isAudioMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_sent_audio_file)
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type image message when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isImageMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_sent_image)
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type video message when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isVideoMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_sent_video)
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type sticker message when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isStickerMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_sent_sticker)
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type poll message with null question when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isPollMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_created_poll)
|
||||||
|
every { fakeRepliedEvent.getPollQuestion() } returns null
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type poll message with existing question when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isPollMessage = true)
|
||||||
|
givenNewContentForId(R.string.message_reply_to_sender_created_poll)
|
||||||
|
every { fakeRepliedEvent.getPollQuestion() } returns A_NEW_CONTENT
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type live location message when process the formatted body then content is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent(isLiveLocationMessage = true)
|
||||||
|
givenNewContentForId(R.string.live_location_description)
|
||||||
|
|
||||||
|
executeAndAssertResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given a replied event of type not handled when process the formatted body only prefix is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenTypeOfRepliedEvent()
|
||||||
|
|
||||||
|
// When
|
||||||
|
val result = processBodyOfReplyToEventUseCase.execute(
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
matrixFormattedBody = A_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY,
|
||||||
|
replyToContent = fakeReplyToContent,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result shouldBeEqualTo PREFIX_PROCESSED_ONLY_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `given no replied event found when process the formatted body then only prefix is replaced by correct string`() {
|
||||||
|
// Given
|
||||||
|
givenARepliedEvent(timelineEvent = null)
|
||||||
|
|
||||||
|
// When
|
||||||
|
val result = processBodyOfReplyToEventUseCase.execute(
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
matrixFormattedBody = A_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY,
|
||||||
|
replyToContent = fakeReplyToContent,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result shouldBeEqualTo PREFIX_PROCESSED_ONLY_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun executeAndAssertResult() {
|
||||||
|
// When
|
||||||
|
val result = processBodyOfReplyToEventUseCase.execute(
|
||||||
|
roomId = A_ROOM_ID,
|
||||||
|
matrixFormattedBody = A_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY,
|
||||||
|
replyToContent = fakeReplyToContent,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Then
|
||||||
|
result shouldBeEqualTo FULLY_PROCESSED_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenARepliedEvent(timelineEvent: TimelineEvent? = mockk()): Event {
|
||||||
|
val event = mockk<Event>()
|
||||||
|
timelineEvent?.let { every { it.root } returns event }
|
||||||
|
fakeActiveSessionHolder
|
||||||
|
.fakeSession
|
||||||
|
.roomService()
|
||||||
|
.getRoom(A_ROOM_ID)
|
||||||
|
.timelineService()
|
||||||
|
.givenTimelineEvent(timelineEvent)
|
||||||
|
return event
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenTypeOfRepliedEvent(
|
||||||
|
isFileMessage: Boolean = false,
|
||||||
|
isVoiceMessage: Boolean = false,
|
||||||
|
isAudioMessage: Boolean = false,
|
||||||
|
isImageMessage: Boolean = false,
|
||||||
|
isVideoMessage: Boolean = false,
|
||||||
|
isStickerMessage: Boolean = false,
|
||||||
|
isPollMessage: Boolean = false,
|
||||||
|
isLiveLocationMessage: Boolean = false,
|
||||||
|
) {
|
||||||
|
every { fakeRepliedEvent.isFileMessage() } returns isFileMessage
|
||||||
|
every { fakeRepliedEvent.isVoiceMessage() } returns isVoiceMessage
|
||||||
|
every { fakeRepliedEvent.isAudioMessage() } returns isAudioMessage
|
||||||
|
every { fakeRepliedEvent.isImageMessage() } returns isImageMessage
|
||||||
|
every { fakeRepliedEvent.isVideoMessage() } returns isVideoMessage
|
||||||
|
every { fakeRepliedEvent.isSticker() } returns isStickerMessage
|
||||||
|
every { fakeRepliedEvent.isPoll() } returns isPollMessage
|
||||||
|
every { fakeRepliedEvent.isLiveLocation() } returns isLiveLocationMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenNewPrefix() {
|
||||||
|
fakeStringProvider.given(R.string.message_reply_to_prefix, A_NEW_PREFIX)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun givenNewContentForId(@StringRes resId: Int) {
|
||||||
|
fakeStringProvider.given(resId, A_NEW_CONTENT)
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineService
|
||||||
|
|
||||||
class FakeTimelineService : TimelineService by mockk() {
|
class FakeTimelineService : TimelineService by mockk() {
|
||||||
|
|
||||||
fun givenTimelineEvent(event: TimelineEvent) {
|
fun givenTimelineEvent(event: TimelineEvent?) {
|
||||||
every { getTimelineEvent(any()) } returns event
|
every { getTimelineEvent(any()) } returns event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue