Inject StringProvider instead of context.

This commit is contained in:
Benoit Marty
2023-05-16 12:21:06 +02:00
committed by Benoit Marty
parent 70df081840
commit ac636d9737
5 changed files with 73 additions and 69 deletions

View File

@@ -40,8 +40,10 @@ dependencies {
implementation(projects.libraries.architecture)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.uiStrings)
implementation(projects.services.toolbox.api)
api(projects.libraries.eventformatter.api)
testImplementation(projects.services.toolbox.impl)
testImplementation(libs.test.junit)
testImplementation(libs.test.robolectric)
testImplementation(libs.test.truth)

View File

@@ -16,15 +16,14 @@
package io.element.android.libraries.eventformatter.impl
import android.content.Context
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.withStyle
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.timeline.item.event.AudioMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
@@ -49,15 +48,14 @@ import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecry
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownMessageType
import io.element.android.libraries.matrix.api.timeline.item.event.VideoMessageType
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
import io.element.android.services.toolbox.api.strings.StringProvider
import timber.log.Timber
import javax.inject.Inject
import io.element.android.libraries.ui.strings.R as StringR
@ContributesBinding(SessionScope::class)
class DefaultRoomLastMessageFormatter @Inject constructor(
// TODO replace with StringProvider
@ApplicationContext private val context: Context,
private val sp: StringProvider,
private val matrixClient: MatrixClient,
) : RoomLastMessageFormatter {
@@ -67,7 +65,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
return when (val content = event.content) {
is MessageContent -> processMessageContents(content, senderDisplayName, isDmRoom)
RedactedContent -> {
val message = context.getString(StringR.string.common_message_removed)
val message = sp.getString(StringR.string.common_message_removed)
if (!isDmRoom) {
prefix(message, senderDisplayName)
} else {
@@ -78,7 +76,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
content.body
}
is UnableToDecryptContent -> {
val message = context.getString(StringR.string.common_decryption_error)
val message = sp.getString(StringR.string.common_decryption_error)
if (!isDmRoom) {
prefix(message, senderDisplayName)
} else {
@@ -95,7 +93,7 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
processRoomStateChange(content, senderDisplayName, isOutgoing)
}
is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
prefixIfNeeded(context.getString(StringR.string.common_unsupported_event), senderDisplayName, isDmRoom)
prefixIfNeeded(sp.getString(StringR.string.common_unsupported_event), senderDisplayName, isDmRoom)
}
}
}
@@ -112,19 +110,19 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
messageType.body
}
is VideoMessageType -> {
context.getString(StringR.string.common_video)
sp.getString(StringR.string.common_video)
}
is ImageMessageType -> {
context.getString(StringR.string.common_image)
sp.getString(StringR.string.common_image)
}
is FileMessageType -> {
context.getString(StringR.string.common_file)
sp.getString(StringR.string.common_file)
}
is AudioMessageType -> {
context.getString(StringR.string.common_audio)
sp.getString(StringR.string.common_audio)
}
UnknownMessageType -> {
context.getString(StringR.string.common_unsupported_event)
sp.getString(StringR.string.common_unsupported_event)
}
is NoticeMessageType -> {
messageType.body
@@ -138,73 +136,73 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
val memberIsYou = userId == matrixClient.sessionId
return when (val change = membershipContent.change) {
MembershipChange.JOINED -> if (memberIsYou) {
context.getString(R.string.state_event_room_join_by_you)
sp.getString(R.string.state_event_room_join_by_you)
} else {
context.getString(R.string.state_event_room_join, userId.value)
sp.getString(R.string.state_event_room_join, userId.value)
}
MembershipChange.LEFT -> if (memberIsYou) {
context.getString(R.string.state_event_room_leave_by_you)
sp.getString(R.string.state_event_room_leave_by_you)
} else {
context.getString(R.string.state_event_room_leave, userId.value)
sp.getString(R.string.state_event_room_leave, userId.value)
}
MembershipChange.BANNED, MembershipChange.KICKED_AND_BANNED -> if (senderIsYou) {
context.getString(R.string.state_event_room_ban_by_you, userId.value)
sp.getString(R.string.state_event_room_ban_by_you, userId.value)
} else {
context.getString(R.string.state_event_room_ban, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_ban, senderDisplayName, userId.value)
}
MembershipChange.UNBANNED -> if (senderIsYou) {
context.getString(R.string.state_event_room_unban_by_you, userId.value)
sp.getString(R.string.state_event_room_unban_by_you, userId.value)
} else {
context.getString(R.string.state_event_room_unban, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_unban, senderDisplayName, userId.value)
}
MembershipChange.KICKED -> if (senderIsYou) {
context.getString(R.string.state_event_room_remove_by_you, userId.value)
sp.getString(R.string.state_event_room_remove_by_you, userId.value)
} else {
context.getString(R.string.state_event_room_remove, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_remove, senderDisplayName, userId.value)
}
MembershipChange.INVITED -> if (senderIsYou) {
context.getString(R.string.state_event_room_invite_by_you, userId.value)
sp.getString(R.string.state_event_room_invite_by_you, userId.value)
} else if (memberIsYou) {
context.getString(R.string.state_event_room_invite_you, senderDisplayName)
sp.getString(R.string.state_event_room_invite_you, senderDisplayName)
} else {
context.getString(R.string.state_event_room_invite, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_invite, senderDisplayName, userId.value)
}
MembershipChange.INVITATION_ACCEPTED -> if (memberIsYou) {
context.getString(R.string.state_event_room_invite_accepted_by_you)
sp.getString(R.string.state_event_room_invite_accepted_by_you)
} else {
context.getString(R.string.state_event_room_invite_accepted, userId.value)
sp.getString(R.string.state_event_room_invite_accepted, userId.value)
}
MembershipChange.INVITATION_REJECTED -> if (memberIsYou) {
context.getString(R.string.state_event_room_reject_by_you)
sp.getString(R.string.state_event_room_reject_by_you)
} else {
context.getString(R.string.state_event_room_reject, userId.value)
sp.getString(R.string.state_event_room_reject, userId.value)
}
MembershipChange.INVITATION_REVOKED -> if (senderIsYou) {
context.getString(R.string.state_event_room_third_party_revoked_invite_by_you, userId.value)
sp.getString(R.string.state_event_room_third_party_revoked_invite_by_you, userId.value)
} else {
context.getString(R.string.state_event_room_third_party_revoked_invite, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_third_party_revoked_invite, senderDisplayName, userId.value)
}
MembershipChange.KNOCKED -> if (memberIsYou) {
context.getString(R.string.state_event_room_knock_by_you)
sp.getString(R.string.state_event_room_knock_by_you)
} else {
context.getString(R.string.state_event_room_knock, userId.value)
sp.getString(R.string.state_event_room_knock, userId.value)
}
MembershipChange.KNOCK_ACCEPTED -> if (senderIsYou) {
context.getString(R.string.state_event_room_knock_accepted_by_you, userId.value)
sp.getString(R.string.state_event_room_knock_accepted_by_you, userId.value)
} else {
context.getString(R.string.state_event_room_knock_accepted, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_knock_accepted, senderDisplayName, userId.value)
}
MembershipChange.KNOCK_RETRACTED -> if (memberIsYou) {
context.getString(R.string.state_event_room_knock_retracted_by_you)
sp.getString(R.string.state_event_room_knock_retracted_by_you)
} else {
context.getString(R.string.state_event_room_knock_retracted, userId.value)
sp.getString(R.string.state_event_room_knock_retracted, userId.value)
}
MembershipChange.KNOCK_DENIED -> if (senderIsYou) {
context.getString(R.string.state_event_room_knock_denied_by_you, userId.value)
sp.getString(R.string.state_event_room_knock_denied_by_you, userId.value)
} else if (memberIsYou) {
context.getString(R.string.state_event_room_knock_denied_you, senderDisplayName)
sp.getString(R.string.state_event_room_knock_denied_you, senderDisplayName)
} else {
context.getString(R.string.state_event_room_knock_denied, senderDisplayName, userId.value)
sp.getString(R.string.state_event_room_knock_denied, senderDisplayName, userId.value)
}
else -> {
Timber.v("Filtering timeline item for room membership: $membershipContent")
@@ -218,27 +216,27 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
is OtherState.RoomAvatar -> {
val hasAvatarUrl = content.url != null
when {
senderIsYou && hasAvatarUrl -> context.getString(R.string.state_event_room_avatar_changed_by_you)
senderIsYou && !hasAvatarUrl -> context.getString(R.string.state_event_room_avatar_removed_by_you)
!senderIsYou && hasAvatarUrl -> context.getString(R.string.state_event_room_avatar_changed, senderDisplayName)
else -> context.getString(R.string.state_event_room_avatar_removed, senderDisplayName)
senderIsYou && hasAvatarUrl -> sp.getString(R.string.state_event_room_avatar_changed_by_you)
senderIsYou && !hasAvatarUrl -> sp.getString(R.string.state_event_room_avatar_removed_by_you)
!senderIsYou && hasAvatarUrl -> sp.getString(R.string.state_event_room_avatar_changed, senderDisplayName)
else -> sp.getString(R.string.state_event_room_avatar_removed, senderDisplayName)
}
}
is OtherState.RoomCreate -> {
if (senderIsYou) {
context.getString(R.string.state_event_room_created_by_you)
sp.getString(R.string.state_event_room_created_by_you)
} else {
context.getString(R.string.state_event_room_created, senderDisplayName)
sp.getString(R.string.state_event_room_created, senderDisplayName)
}
}
is OtherState.RoomEncryption -> context.getString(StringR.string.common_encryption_enabled)
is OtherState.RoomEncryption -> sp.getString(StringR.string.common_encryption_enabled)
is OtherState.RoomName -> {
val hasRoomName = content.name != null
when {
senderIsYou && hasRoomName -> context.getString(R.string.state_event_room_name_changed_by_you, content.name)
senderIsYou && !hasRoomName -> context.getString(R.string.state_event_room_name_removed_by_you)
!senderIsYou && hasRoomName -> context.getString(R.string.state_event_room_name_changed, senderDisplayName, content.name)
else -> context.getString(R.string.state_event_room_name_removed, senderDisplayName)
senderIsYou && hasRoomName -> sp.getString(R.string.state_event_room_name_changed_by_you, content.name)
senderIsYou && !hasRoomName -> sp.getString(R.string.state_event_room_name_removed_by_you)
!senderIsYou && hasRoomName -> sp.getString(R.string.state_event_room_name_changed, senderDisplayName, content.name)
else -> sp.getString(R.string.state_event_room_name_removed, senderDisplayName)
}
}
is OtherState.RoomThirdPartyInvite -> {
@@ -247,18 +245,18 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
return null
}
if (senderIsYou) {
context.getString(R.string.state_event_room_third_party_invite_by_you, content.displayName)
sp.getString(R.string.state_event_room_third_party_invite_by_you, content.displayName)
} else {
context.getString(R.string.state_event_room_third_party_invite, senderDisplayName, content.displayName)
sp.getString(R.string.state_event_room_third_party_invite, senderDisplayName, content.displayName)
}
}
is OtherState.RoomTopic -> {
val hasRoomTopic = content.topic != null
when {
senderIsYou && hasRoomTopic -> context.getString(R.string.state_event_room_topic_changed_by_you, content.topic)
senderIsYou && !hasRoomTopic -> context.getString(R.string.state_event_room_topic_removed_by_you)
!senderIsYou && hasRoomTopic -> context.getString(R.string.state_event_room_topic_changed, senderDisplayName, content.topic)
else -> context.getString(R.string.state_event_room_topic_removed, senderDisplayName)
senderIsYou && hasRoomTopic -> sp.getString(R.string.state_event_room_topic_changed_by_you, content.topic)
senderIsYou && !hasRoomTopic -> sp.getString(R.string.state_event_room_topic_removed_by_you)
!senderIsYou && hasRoomTopic -> sp.getString(R.string.state_event_room_topic_changed, senderDisplayName, content.topic)
else -> sp.getString(R.string.state_event_room_topic_removed, senderDisplayName)
}
}
else -> {
@@ -278,35 +276,35 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
return when {
avatarChanged && displayNameChanged -> {
val message = processProfileChangeContent(profileChangeContent.copy(avatarUrl = null, prevAvatarUrl = null), senderDisplayName, senderIsYou)
val avatarChangedToo = context.getString(R.string.state_event_avatar_changed_too)
val avatarChangedToo = sp.getString(R.string.state_event_avatar_changed_too)
"$message\n$avatarChangedToo"
}
displayNameChanged -> {
if (displayName != null && prevDisplayName != null) {
if (senderIsYou) {
context.getString(R.string.state_event_display_name_changed_from_by_you, prevDisplayName, displayName)
sp.getString(R.string.state_event_display_name_changed_from_by_you, prevDisplayName, displayName)
} else {
context.getString(R.string.state_event_display_name_changed_from, senderDisplayName, prevDisplayName, displayName)
sp.getString(R.string.state_event_display_name_changed_from, senderDisplayName, prevDisplayName, displayName)
}
} else if (displayName != null) {
if (senderIsYou) {
context.getString(R.string.state_event_display_name_set_by_you, displayName)
sp.getString(R.string.state_event_display_name_set_by_you, displayName)
} else {
context.getString(R.string.state_event_display_name_set, senderDisplayName, displayName)
sp.getString(R.string.state_event_display_name_set, senderDisplayName, displayName)
}
} else {
if (senderIsYou) {
context.getString(R.string.state_event_display_name_removed_by_you, prevDisplayName)
sp.getString(R.string.state_event_display_name_removed_by_you, prevDisplayName)
} else {
context.getString(R.string.state_event_display_name_removed, senderDisplayName, prevDisplayName)
sp.getString(R.string.state_event_display_name_removed, senderDisplayName, prevDisplayName)
}
}
}
avatarChanged -> {
if (senderIsYou) {
context.getString(R.string.state_event_avatar_url_changed_by_you)
sp.getString(R.string.state_event_avatar_url_changed_by_you)
} else {
context.getString(R.string.state_event_avatar_url_changed, senderDisplayName)
sp.getString(R.string.state_event_avatar_url_changed, senderDisplayName)
}
}
else -> null

View File

@@ -48,6 +48,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID
import io.element.android.libraries.matrix.test.FakeMatrixClient
import io.element.android.libraries.matrix.test.room.aProfileChangeMessageContent
import io.element.android.libraries.matrix.test.room.anEventTimelineItem
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -66,7 +67,7 @@ class DefaultRoomLastMessageFormatterTests {
fun setup() {
context = RuntimeEnvironment.getApplication() as Context
fakeMatrixClient = FakeMatrixClient()
formatter = DefaultRoomLastMessageFormatter(context, fakeMatrixClient)
formatter = DefaultRoomLastMessageFormatter(AndroidStringProvider(context.resources), fakeMatrixClient)
}
@Test
@@ -145,6 +146,7 @@ class DefaultRoomLastMessageFormatterTests {
fun createMessageContent(type: MessageType): MessageContent {
return MessageContent(body, null, false, type)
}
val sharedContentMessagesTypes = arrayOf(
TextMessageType(body, null),
VideoMessageType(body, "url", null),

View File

@@ -61,6 +61,7 @@ dependencies {
implementation(projects.features.leaveroom.impl)
implementation(projects.features.login.impl)
implementation(projects.features.networkmonitor.impl)
implementation(projects.services.toolbox.impl)
implementation(libs.coroutines.core)
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.3")
}

View File

@@ -35,6 +35,7 @@ import io.element.android.libraries.eventformatter.impl.DefaultRoomLastMessageFo
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.datetime.Clock
@@ -55,7 +56,7 @@ class RoomListScreen(
private val presenter = RoomListPresenter(
client = matrixClient,
lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(context, matrixClient),
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(AndroidStringProvider(context.resources), matrixClient),
sessionVerificationService = sessionVerificationService,
networkMonitor = NetworkMonitorImpl(context),
snackbarDispatcher = SnackbarDispatcher(),