diff --git a/changelog.d/7555.bugfix b/changelog.d/7555.bugfix
new file mode 100644
index 0000000000..064b21a9e5
--- /dev/null
+++ b/changelog.d/7555.bugfix
@@ -0,0 +1 @@
+Missing translations on "replyTo" messages
diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index ab98f7e141..0e2b2bef94 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3464,4 +3464,13 @@
Apply underline format
Toggle full screen mode
+
+ In reply to
+ sent a file.
+ sent an audio file.
+ sent a voice message.
+ sent an image.
+ sent a video.
+ sent a sticker.
+ created a poll.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
index 6ae585a273..1e32437727 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/events/model/Event.kt
@@ -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.asMessageAudioEvent
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.send.SendState
import org.matrix.android.sdk.api.session.threads.ThreadDetails
@@ -228,11 +229,14 @@ data class Event(
return when {
isReplyRenderedInThread() || isQuote() -> ContentUtils.extractUsefulTextFromReply(text)
isFileMessage() -> "sent a file."
+ isVoiceMessage() -> "sent a voice message."
isAudioMessage() -> "sent an audio file."
isImageMessage() -> "sent an image."
isVideoMessage() -> "sent a video."
- isSticker() -> "sent a sticker"
+ isSticker() -> "sent a sticker."
isPoll() -> getPollQuestion() ?: "created a poll."
+ isLiveLocation() -> "Live location."
+ isLocationMessage() -> "has shared their location."
else -> text
}
}
@@ -420,7 +424,7 @@ fun Event.getRelationContentForType(type: String): RelationDefaultContent? =
getRelationContent()?.takeIf { it.type == type }
fun Event.isReply(): Boolean {
- return getRelationContent()?.inReplyTo?.eventId != null
+ return getRelationContent().isReply()
}
fun Event.isReplyRenderedInThread(): Boolean {
@@ -443,7 +447,7 @@ fun Event.isInvitation(): Boolean = type == EventType.STATE_ROOM_MEMBER &&
content?.toModel()?.membership == Membership.INVITE
fun Event.getPollContent(): MessagePollContent? {
- return content.toModel()
+ return getClearContent().toModel()
}
fun Event.supportsNotification() =
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
index cd8acbcccc..93208be27b 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/location/LocationSharingService.kt
@@ -47,10 +47,9 @@ interface LocationSharingService {
/**
* Starts sharing live location in the room.
* @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
*/
- suspend fun startLiveLocationShare(timeoutMillis: Long, description: String): UpdateLiveLocationShareResult
+ suspend fun startLiveLocationShare(timeoutMillis: Long): UpdateLiveLocationShareResult
/**
* Stops sharing live location in the room.
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationDefaultContent.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationDefaultContent.kt
index 5dcb1b4323..b9f9335dbd 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationDefaultContent.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/relation/RelationDefaultContent.kt
@@ -28,3 +28,5 @@ data class RelationDefaultContent(
) : RelationContent
fun RelationDefaultContent.shouldRenderInThread(): Boolean = isFallingBack == false
+
+fun RelationDefaultContent?.isReply(): Boolean = this?.inReplyTo?.eventId != null
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt
index 60312071d7..c36efa064f 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/DefaultLocationSharingService.kt
@@ -73,7 +73,7 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
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
if (checkIfExistingActiveLive()) {
val result = stopLiveLocationShare()
@@ -84,7 +84,6 @@ internal class DefaultLocationSharingService @AssistedInject constructor(
val params = StartLiveLocationShareTask.Params(
roomId = roomId,
timeoutMillis = timeoutMillis,
- description = description
)
return startLiveLocationShareTask.execute(params)
}
diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt
index 79019e4765..781def1abe 100644
--- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt
+++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/location/StartLiveLocationShareTask.kt
@@ -30,7 +30,6 @@ internal interface StartLiveLocationShareTask : Task buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, 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)
else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes)
}
@@ -437,7 +440,14 @@ class MessageItemFactory @Inject constructor(
attributes: AbsMessageItem.Attributes
): MessageTextItem? {
// 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(
@@ -540,7 +550,8 @@ class MessageItemFactory @Inject constructor(
): VectorEpoxyModel<*>? {
val matrixFormattedBody = messageContent.matrixFormattedBody
return if (matrixFormattedBody != null) {
- buildFormattedTextItem(matrixFormattedBody, informationData, highlight, callback, attributes)
+ val replyToContent = messageContent.relatesTo?.inReplyTo
+ buildFormattedTextItem(matrixFormattedBody, informationData, highlight, callback, attributes, replyToContent)
} else {
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
}
@@ -552,10 +563,21 @@ class MessageItemFactory @Inject constructor(
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
+ replyToContent: ReplyToContent?,
): 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
- return buildMessageTextItem(renderedFormattedBody, true, informationData, highlight, callback, attributes)
+ return buildMessageTextItem(
+ renderedFormattedBody,
+ true,
+ informationData,
+ highlight,
+ callback,
+ attributes,
+ )
}
private fun buildMessageTextItem(
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt
index 920f3e3b80..c46112f995 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/EventTextRenderer.kt
@@ -34,22 +34,22 @@ class EventTextRenderer @AssistedInject constructor(
@Assisted private val roomId: String?,
private val context: Context,
private val avatarRenderer: AvatarRenderer,
- private val sessionHolder: ActiveSessionHolder
+ private val activeSessionHolder: ActiveSessionHolder,
) {
- /* ==========================================================================================
- * Public api
- * ========================================================================================== */
-
@AssistedFactory
interface Factory {
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 {
+ return renderNotifyEveryone(text)
+ }
+
+ private fun renderNotifyEveryone(text: CharSequence): CharSequence {
return if (roomId != null && text.contains(MatrixItem.NOTIFY_EVERYONE)) {
SpannableStringBuilder(text).apply {
addNotifyEveryoneSpans(this, roomId)
@@ -59,12 +59,8 @@ class EventTextRenderer @AssistedInject constructor(
}
}
- /* ==========================================================================================
- * Helper methods
- * ========================================================================================== */
-
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(
id = roomId,
avatarUrl = room?.avatarUrl,
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt
new file mode 100644
index 0000000000..2197d89a2c
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt
@@ -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 = "
"
+private const val ENDING_BLOCK_QUOTE = ""
+
+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
+}
diff --git a/vector/src/main/java/im/vector/app/features/location/live/tracking/LocationSharingAndroidService.kt b/vector/src/main/java/im/vector/app/features/location/live/tracking/LocationSharingAndroidService.kt
index 545f98f01e..ccab23a83b 100644
--- a/vector/src/main/java/im/vector/app/features/location/live/tracking/LocationSharingAndroidService.kt
+++ b/vector/src/main/java/im/vector/app/features/location/live/tracking/LocationSharingAndroidService.kt
@@ -21,7 +21,6 @@ import android.os.IBinder
import android.os.Parcelable
import androidx.core.app.NotificationManagerCompat
import dagger.hilt.android.AndroidEntryPoint
-import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.services.VectorAndroidService
import im.vector.app.features.location.LocationData
@@ -125,10 +124,7 @@ class LocationSharingAndroidService : VectorAndroidService(), LocationTracker.Ca
val updateLiveResult = session
.getRoom(roomArgs.roomId)
?.locationSharingService()
- ?.startLiveLocationShare(
- timeoutMillis = roomArgs.durationMillis,
- description = getString(R.string.live_location_description)
- )
+ ?.startLiveLocationShare(roomArgs.durationMillis)
updateLiveResult
?.let { result ->
diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCaseTest.kt
new file mode 100644
index 0000000000..f612861511
--- /dev/null
+++ b/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCaseTest.kt
@@ -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 =
+ "" +
+ "" +
+ "In reply to " +
+ "@user:matrix.org" +
+ "
" +
+ "Message content" +
+ "
" +
+ "" +
+ "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 =
+ "" +
+ "" +
+ "$A_NEW_PREFIX " +
+ "@user:matrix.org" +
+ "
" +
+ "Message content" +
+ "
" +
+ "" +
+ "Reply text"
+private const val FULLY_PROCESSED_REPLY_TO_EVENT_MATRIX_FORMATTED_BODY =
+ "" +
+ "" +
+ "$A_NEW_PREFIX " +
+ "@user:matrix.org" +
+ "
" +
+ A_NEW_CONTENT +
+ "
" +
+ "" +
+ "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()
+ 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)
+ }
+}
diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeTimelineService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeTimelineService.kt
index 56f38724b1..a5fac5f1a1 100644
--- a/vector/src/test/java/im/vector/app/test/fakes/FakeTimelineService.kt
+++ b/vector/src/test/java/im/vector/app/test/fakes/FakeTimelineService.kt
@@ -23,7 +23,7 @@ import org.matrix.android.sdk.api.session.room.timeline.TimelineService
class FakeTimelineService : TimelineService by mockk() {
- fun givenTimelineEvent(event: TimelineEvent) {
+ fun givenTimelineEvent(event: TimelineEvent?) {
every { getTimelineEvent(any()) } returns event
}
}