Extract to sub classes
This commit is contained in:
parent
bbe4b7d26a
commit
be478cadaa
8 changed files with 490 additions and 198 deletions
|
|
@ -37,6 +37,7 @@ dependencies {
|
||||||
anvil(projects.anvilcodegen)
|
anvil(projects.anvilcodegen)
|
||||||
implementation(projects.anvilannotations)
|
implementation(projects.anvilannotations)
|
||||||
|
|
||||||
|
implementation(projects.libraries.core)
|
||||||
implementation(projects.libraries.architecture)
|
implementation(projects.libraries.architecture)
|
||||||
implementation(projects.libraries.matrix.api)
|
implementation(projects.libraries.matrix.api)
|
||||||
implementation(projects.libraries.uiStrings)
|
implementation(projects.libraries.uiStrings)
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import androidx.compose.ui.text.withStyle
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
|
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
|
||||||
|
import io.element.android.libraries.eventformatter.impl.mode.RenderingMode
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
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.AudioMessageType
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
|
import io.element.android.libraries.matrix.api.timeline.item.event.EmoteMessageType
|
||||||
|
|
@ -32,11 +33,9 @@ import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParse
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
|
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.FileMessageType
|
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.ImageMessageType
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
|
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
|
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.MessageType
|
import io.element.android.libraries.matrix.api.timeline.item.event.MessageType
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageType
|
import io.element.android.libraries.matrix.api.timeline.item.event.NoticeMessageType
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
|
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
|
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
|
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
|
import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
|
||||||
|
|
@ -49,7 +48,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.UnknownConten
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownMessageType
|
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.matrix.api.timeline.item.event.VideoMessageType
|
||||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
import timber.log.Timber
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import io.element.android.libraries.ui.strings.R as StringR
|
import io.element.android.libraries.ui.strings.R as StringR
|
||||||
|
|
||||||
|
|
@ -57,6 +55,9 @@ import io.element.android.libraries.ui.strings.R as StringR
|
||||||
class DefaultRoomLastMessageFormatter @Inject constructor(
|
class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
private val sp: StringProvider,
|
private val sp: StringProvider,
|
||||||
private val matrixClient: MatrixClient,
|
private val matrixClient: MatrixClient,
|
||||||
|
private val roomMembershipContentFormatter: RoomMembershipContentFormatter,
|
||||||
|
private val profileChangeContentFormatter: ProfileChangeContentFormatter,
|
||||||
|
private val stateContentFormatter: StateContentFormatter,
|
||||||
) : RoomLastMessageFormatter {
|
) : RoomLastMessageFormatter {
|
||||||
|
|
||||||
override fun format(event: EventTimelineItem, isDmRoom: Boolean): CharSequence? {
|
override fun format(event: EventTimelineItem, isDmRoom: Boolean): CharSequence? {
|
||||||
|
|
@ -84,13 +85,13 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is RoomMembershipContent -> {
|
is RoomMembershipContent -> {
|
||||||
processRoomMembershipChange(content, senderDisplayName, isOutgoing)
|
roomMembershipContentFormatter.format(content, senderDisplayName, isOutgoing)
|
||||||
}
|
}
|
||||||
is ProfileChangeContent -> {
|
is ProfileChangeContent -> {
|
||||||
processProfileChangeContent(content, senderDisplayName, isOutgoing)
|
profileChangeContentFormatter.format(content, senderDisplayName, isOutgoing)
|
||||||
}
|
}
|
||||||
is StateContent -> {
|
is StateContent -> {
|
||||||
processRoomStateChange(content, senderDisplayName, isOutgoing)
|
stateContentFormatter.format(content, senderDisplayName, isOutgoing, RenderingMode.RoomList)
|
||||||
}
|
}
|
||||||
is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
|
is FailedToParseMessageLikeContent, is FailedToParseStateContent, is UnknownContent -> {
|
||||||
prefixIfNeeded(sp.getString(StringR.string.common_unsupported_event), senderDisplayName, isDmRoom)
|
prefixIfNeeded(sp.getString(StringR.string.common_unsupported_event), senderDisplayName, isDmRoom)
|
||||||
|
|
@ -131,186 +132,6 @@ class DefaultRoomLastMessageFormatter @Inject constructor(
|
||||||
return prefixIfNeeded(internalMessage, senderDisplayName, isDmRoom)
|
return prefixIfNeeded(internalMessage, senderDisplayName, isDmRoom)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processRoomMembershipChange(membershipContent: RoomMembershipContent, senderDisplayName: String, senderIsYou: Boolean): CharSequence? {
|
|
||||||
val userId = membershipContent.userId
|
|
||||||
val memberIsYou = userId == matrixClient.sessionId
|
|
||||||
return when (val change = membershipContent.change) {
|
|
||||||
MembershipChange.JOINED -> if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_join_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_join, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.LEFT -> if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_leave_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_leave, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.BANNED, MembershipChange.KICKED_AND_BANNED -> if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_ban_by_you, userId.value)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_ban, senderDisplayName, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.UNBANNED -> if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_unban_by_you, userId.value)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_unban, senderDisplayName, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.KICKED -> if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_remove_by_you, userId.value)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_remove, senderDisplayName, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.INVITED -> if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_invite_by_you, userId.value)
|
|
||||||
} else if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_invite_you, senderDisplayName)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_invite, senderDisplayName, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.INVITATION_ACCEPTED -> if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_invite_accepted_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_invite_accepted, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.INVITATION_REJECTED -> if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_reject_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_reject, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.INVITATION_REVOKED -> if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_third_party_revoked_invite_by_you, userId.value)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_third_party_revoked_invite, senderDisplayName, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.KNOCKED -> if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_knock_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_knock, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.KNOCK_ACCEPTED -> if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_knock_accepted_by_you, userId.value)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_knock_accepted, senderDisplayName, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.KNOCK_RETRACTED -> if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_knock_retracted_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_knock_retracted, userId.value)
|
|
||||||
}
|
|
||||||
MembershipChange.KNOCK_DENIED -> if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_knock_denied_by_you, userId.value)
|
|
||||||
} else if (memberIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_knock_denied_you, senderDisplayName)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_knock_denied, senderDisplayName, userId.value)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
Timber.v("Filtering timeline item for room membership: $membershipContent")
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processRoomStateChange(stateContent: StateContent, senderDisplayName: String, senderIsYou: Boolean): CharSequence? {
|
|
||||||
return when (val content = stateContent.content) {
|
|
||||||
is OtherState.RoomAvatar -> {
|
|
||||||
val hasAvatarUrl = content.url != null
|
|
||||||
when {
|
|
||||||
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) {
|
|
||||||
sp.getString(R.string.state_event_room_created_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_created, senderDisplayName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is OtherState.RoomEncryption -> sp.getString(StringR.string.common_encryption_enabled)
|
|
||||||
is OtherState.RoomName -> {
|
|
||||||
val hasRoomName = content.name != null
|
|
||||||
when {
|
|
||||||
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 -> {
|
|
||||||
if (content.displayName == null) {
|
|
||||||
Timber.e("RoomThirdPartyInvite undisplayable due to missing name")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_room_third_party_invite_by_you, content.displayName)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_room_third_party_invite, senderDisplayName, content.displayName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
is OtherState.RoomTopic -> {
|
|
||||||
val hasRoomTopic = content.topic != null
|
|
||||||
when {
|
|
||||||
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 -> {
|
|
||||||
Timber.v("Filtering timeline item for room state change: $content")
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processProfileChangeContent(
|
|
||||||
profileChangeContent: ProfileChangeContent,
|
|
||||||
senderDisplayName: String,
|
|
||||||
senderIsYou: Boolean
|
|
||||||
): String? = profileChangeContent.run {
|
|
||||||
val displayNameChanged = displayName != prevDisplayName
|
|
||||||
val avatarChanged = avatarUrl != prevAvatarUrl
|
|
||||||
return when {
|
|
||||||
avatarChanged && displayNameChanged -> {
|
|
||||||
val message = processProfileChangeContent(profileChangeContent.copy(avatarUrl = null, prevAvatarUrl = null), senderDisplayName, senderIsYou)
|
|
||||||
val avatarChangedToo = sp.getString(R.string.state_event_avatar_changed_too)
|
|
||||||
"$message\n$avatarChangedToo"
|
|
||||||
}
|
|
||||||
displayNameChanged -> {
|
|
||||||
if (displayName != null && prevDisplayName != null) {
|
|
||||||
if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_display_name_changed_from_by_you, prevDisplayName, displayName)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_display_name_changed_from, senderDisplayName, prevDisplayName, displayName)
|
|
||||||
}
|
|
||||||
} else if (displayName != null) {
|
|
||||||
if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_display_name_set_by_you, displayName)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_display_name_set, senderDisplayName, displayName)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_display_name_removed_by_you, prevDisplayName)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_display_name_removed, senderDisplayName, prevDisplayName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
avatarChanged -> {
|
|
||||||
if (senderIsYou) {
|
|
||||||
sp.getString(R.string.state_event_avatar_url_changed_by_you)
|
|
||||||
} else {
|
|
||||||
sp.getString(R.string.state_event_avatar_url_changed, senderDisplayName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun prefixIfNeeded(message: String, senderDisplayName: String, isDmRoom: Boolean): CharSequence = if (isDmRoom) {
|
private fun prefixIfNeeded(message: String, senderDisplayName: String, isDmRoom: Boolean): CharSequence = if (isDmRoom) {
|
||||||
message
|
message
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -17,26 +17,62 @@
|
||||||
package io.element.android.libraries.eventformatter.impl
|
package io.element.android.libraries.eventformatter.impl
|
||||||
|
|
||||||
import com.squareup.anvil.annotations.ContributesBinding
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.core.meta.BuildMeta
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
|
|
||||||
import io.element.android.libraries.eventformatter.api.TimelineEventFormatter
|
import io.element.android.libraries.eventformatter.api.TimelineEventFormatter
|
||||||
|
import io.element.android.libraries.eventformatter.impl.mode.RenderingMode
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseMessageLikeContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.FailedToParseStateContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.MessageContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileTimelineDetails
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.RedactedContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.StickerContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.UnableToDecryptContent
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.UnknownContent
|
||||||
|
import io.element.android.libraries.ui.strings.R
|
||||||
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
|
||||||
* For now use the same formatter than for the room list using [RoomLastMessageFormatter].
|
|
||||||
* We will change this if we want to have a different rendering in the timeline.
|
|
||||||
*/
|
|
||||||
@ContributesBinding(SessionScope::class)
|
@ContributesBinding(SessionScope::class)
|
||||||
class DefaultTimelineEventFormatter @Inject constructor(
|
class DefaultTimelineEventFormatter @Inject constructor(
|
||||||
private val roomLastMessageFormatter: RoomLastMessageFormatter,
|
private val sp: StringProvider,
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val buildMeta: BuildMeta,
|
||||||
|
private val roomMembershipContentFormatter: RoomMembershipContentFormatter,
|
||||||
|
private val profileChangeContentFormatter: ProfileChangeContentFormatter,
|
||||||
|
private val stateContentFormatter: StateContentFormatter,
|
||||||
) : TimelineEventFormatter {
|
) : TimelineEventFormatter {
|
||||||
|
|
||||||
override fun format(event: EventTimelineItem): CharSequence? {
|
override fun format(event: EventTimelineItem): CharSequence? {
|
||||||
return roomLastMessageFormatter.format(
|
val isOutgoing = event.sender == matrixClient.sessionId
|
||||||
event,
|
val senderDisplayName = (event.senderProfile as? ProfileTimelineDetails.Ready)?.displayName ?: event.sender.value
|
||||||
/* We do not want to distinguish DM and room here */
|
return when (val content = event.content) {
|
||||||
isDmRoom = false,
|
is RoomMembershipContent -> {
|
||||||
)
|
roomMembershipContentFormatter.format(content, senderDisplayName, isOutgoing)
|
||||||
|
}
|
||||||
|
is ProfileChangeContent -> {
|
||||||
|
profileChangeContentFormatter.format(content, senderDisplayName, isOutgoing)
|
||||||
|
}
|
||||||
|
is StateContent -> {
|
||||||
|
stateContentFormatter.format(content, senderDisplayName, isOutgoing, RenderingMode.Timeline)
|
||||||
|
}
|
||||||
|
RedactedContent,
|
||||||
|
is StickerContent,
|
||||||
|
is UnableToDecryptContent,
|
||||||
|
is MessageContent,
|
||||||
|
is FailedToParseMessageLikeContent,
|
||||||
|
is FailedToParseStateContent,
|
||||||
|
is UnknownContent -> {
|
||||||
|
if (buildMeta.isDebuggable) {
|
||||||
|
error("You should not use this formatter for this event: $event")
|
||||||
|
}
|
||||||
|
sp.getString(R.string.common_unsupported_event)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* 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.libraries.eventformatter.impl
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
|
||||||
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class ProfileChangeContentFormatter @Inject constructor(
|
||||||
|
private val sp: StringProvider,
|
||||||
|
) {
|
||||||
|
fun format(
|
||||||
|
profileChangeContent: ProfileChangeContent,
|
||||||
|
senderDisplayName: String,
|
||||||
|
senderIsYou: Boolean,
|
||||||
|
): String? = profileChangeContent.run {
|
||||||
|
val displayNameChanged = displayName != prevDisplayName
|
||||||
|
val avatarChanged = avatarUrl != prevAvatarUrl
|
||||||
|
return when {
|
||||||
|
avatarChanged && displayNameChanged -> {
|
||||||
|
val message = format(profileChangeContent.copy(avatarUrl = null, prevAvatarUrl = null), senderDisplayName, senderIsYou)
|
||||||
|
val avatarChangedToo = sp.getString(R.string.state_event_avatar_changed_too)
|
||||||
|
"$message\n$avatarChangedToo"
|
||||||
|
}
|
||||||
|
displayNameChanged -> {
|
||||||
|
if (displayName != null && prevDisplayName != null) {
|
||||||
|
if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_display_name_changed_from_by_you, prevDisplayName, displayName)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_display_name_changed_from, senderDisplayName, prevDisplayName, displayName)
|
||||||
|
}
|
||||||
|
} else if (displayName != null) {
|
||||||
|
if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_display_name_set_by_you, displayName)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_display_name_set, senderDisplayName, displayName)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_display_name_removed_by_you, prevDisplayName)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_display_name_removed, senderDisplayName, prevDisplayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avatarChanged -> {
|
||||||
|
if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_avatar_url_changed_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_avatar_url_changed, senderDisplayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* 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.libraries.eventformatter.impl
|
||||||
|
|
||||||
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
|
||||||
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class RoomMembershipContentFormatter @Inject constructor(
|
||||||
|
private val matrixClient: MatrixClient,
|
||||||
|
private val sp: StringProvider,
|
||||||
|
) {
|
||||||
|
fun format(
|
||||||
|
membershipContent: RoomMembershipContent,
|
||||||
|
senderDisplayName: String,
|
||||||
|
senderIsYou: Boolean,
|
||||||
|
): CharSequence? {
|
||||||
|
val userId = membershipContent.userId
|
||||||
|
val memberIsYou = userId == matrixClient.sessionId
|
||||||
|
return when (val change = membershipContent.change) {
|
||||||
|
MembershipChange.JOINED -> if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_join_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_join, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.LEFT -> if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_leave_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_leave, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.BANNED, MembershipChange.KICKED_AND_BANNED -> if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_ban_by_you, userId.value)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_ban, senderDisplayName, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.UNBANNED -> if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_unban_by_you, userId.value)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_unban, senderDisplayName, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.KICKED -> if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_remove_by_you, userId.value)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_remove, senderDisplayName, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.INVITED -> if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_invite_by_you, userId.value)
|
||||||
|
} else if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_invite_you, senderDisplayName)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_invite, senderDisplayName, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.INVITATION_ACCEPTED -> if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_invite_accepted_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_invite_accepted, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.INVITATION_REJECTED -> if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_reject_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_reject, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.INVITATION_REVOKED -> if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_third_party_revoked_invite_by_you, userId.value)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_third_party_revoked_invite, senderDisplayName, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.KNOCKED -> if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_knock_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_knock, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.KNOCK_ACCEPTED -> if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_knock_accepted_by_you, userId.value)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_knock_accepted, senderDisplayName, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.KNOCK_RETRACTED -> if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_knock_retracted_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_knock_retracted, userId.value)
|
||||||
|
}
|
||||||
|
MembershipChange.KNOCK_DENIED -> if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_knock_denied_by_you, userId.value)
|
||||||
|
} else if (memberIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_knock_denied_you, senderDisplayName)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_knock_denied, senderDisplayName, userId.value)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
Timber.v("Filtering timeline item for room membership: $membershipContent")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,219 @@
|
||||||
|
/*
|
||||||
|
* 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.libraries.eventformatter.impl
|
||||||
|
|
||||||
|
import io.element.android.libraries.eventformatter.impl.mode.RenderingMode
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
|
||||||
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class StateContentFormatter @Inject constructor(
|
||||||
|
private val sp: StringProvider,
|
||||||
|
) {
|
||||||
|
fun format(
|
||||||
|
stateContent: StateContent,
|
||||||
|
senderDisplayName: String,
|
||||||
|
senderIsYou: Boolean,
|
||||||
|
renderingMode: RenderingMode,
|
||||||
|
): CharSequence? {
|
||||||
|
return when (val content = stateContent.content) {
|
||||||
|
is OtherState.RoomAvatar -> {
|
||||||
|
val hasAvatarUrl = content.url != null
|
||||||
|
when {
|
||||||
|
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) {
|
||||||
|
sp.getString(R.string.state_event_room_created_by_you)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_created, senderDisplayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is OtherState.RoomEncryption -> sp.getString(io.element.android.libraries.ui.strings.R.string.common_encryption_enabled)
|
||||||
|
is OtherState.RoomName -> {
|
||||||
|
val hasRoomName = content.name != null
|
||||||
|
when {
|
||||||
|
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 -> {
|
||||||
|
if (content.displayName == null) {
|
||||||
|
Timber.e("RoomThirdPartyInvite undisplayable due to missing name")
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (senderIsYou) {
|
||||||
|
sp.getString(R.string.state_event_room_third_party_invite_by_you, content.displayName)
|
||||||
|
} else {
|
||||||
|
sp.getString(R.string.state_event_room_third_party_invite, senderDisplayName, content.displayName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is OtherState.RoomTopic -> {
|
||||||
|
val hasRoomTopic = content.topic != null
|
||||||
|
when {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is OtherState.Custom -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"Custom event ${content.eventType}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.PolicyRuleRoom -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"PolicyRuleRoom"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.PolicyRuleServer -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"PolicyRuleServer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.PolicyRuleUser -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"PolicyRuleUser"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomAliases -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomAliases"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomCanonicalAlias -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomCanonicalAlias"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomGuestAccess -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomGuestAccess"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomHistoryVisibility -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomHistoryVisibility"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomJoinRules -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomJoinRules"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomPinnedEvents -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomPinnedEvents"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomPowerLevels -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomPowerLevels"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomServerAcl -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomServerAcl"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.RoomTombstone -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"RoomTombstone"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.SpaceChild -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"SpaceChild"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OtherState.SpaceParent -> when (renderingMode) {
|
||||||
|
RenderingMode.RoomList -> {
|
||||||
|
Timber.v("Filtering timeline item for room state change: $content")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
RenderingMode.Timeline -> {
|
||||||
|
"SpaceParent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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.libraries.eventformatter.impl.mode
|
||||||
|
|
||||||
|
enum class RenderingMode {
|
||||||
|
RoomList,
|
||||||
|
Timeline,
|
||||||
|
}
|
||||||
|
|
@ -32,6 +32,9 @@ import io.element.android.libraries.dateformatter.impl.DefaultLastMessageTimesta
|
||||||
import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider
|
import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider
|
||||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||||
import io.element.android.libraries.eventformatter.impl.DefaultRoomLastMessageFormatter
|
import io.element.android.libraries.eventformatter.impl.DefaultRoomLastMessageFormatter
|
||||||
|
import io.element.android.libraries.eventformatter.impl.ProfileChangeContentFormatter
|
||||||
|
import io.element.android.libraries.eventformatter.impl.RoomMembershipContentFormatter
|
||||||
|
import io.element.android.libraries.eventformatter.impl.StateContentFormatter
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||||
|
|
@ -53,10 +56,17 @@ class RoomListScreen(
|
||||||
private val dateTimeProvider = LocalDateTimeProvider(clock, timeZone)
|
private val dateTimeProvider = LocalDateTimeProvider(clock, timeZone)
|
||||||
private val dateFormatters = DateFormatters(locale, clock, timeZone)
|
private val dateFormatters = DateFormatters(locale, clock, timeZone)
|
||||||
private val sessionVerificationService = matrixClient.sessionVerificationService()
|
private val sessionVerificationService = matrixClient.sessionVerificationService()
|
||||||
|
private val stringProvider = AndroidStringProvider(context.resources)
|
||||||
private val presenter = RoomListPresenter(
|
private val presenter = RoomListPresenter(
|
||||||
client = matrixClient,
|
client = matrixClient,
|
||||||
lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
|
lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
|
||||||
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(AndroidStringProvider(context.resources), matrixClient),
|
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(
|
||||||
|
sp = stringProvider,
|
||||||
|
matrixClient = matrixClient,
|
||||||
|
roomMembershipContentFormatter = RoomMembershipContentFormatter(matrixClient, stringProvider),
|
||||||
|
profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider),
|
||||||
|
stateContentFormatter = StateContentFormatter(stringProvider),
|
||||||
|
),
|
||||||
sessionVerificationService = sessionVerificationService,
|
sessionVerificationService = sessionVerificationService,
|
||||||
networkMonitor = NetworkMonitorImpl(context),
|
networkMonitor = NetworkMonitorImpl(context),
|
||||||
snackbarDispatcher = SnackbarDispatcher(),
|
snackbarDispatcher = SnackbarDispatcher(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue