Platform: fix RoomSummaryHolder usage (temporary)

This commit is contained in:
ganfra 2020-12-22 16:44:02 +01:00
parent c53111a85a
commit 8734101d87
18 changed files with 56 additions and 42 deletions

View file

@ -52,6 +52,8 @@ data class TimelineEvent(
}
}
val roomId = root.roomId ?: ""
val metadata = HashMap<String, Any>()
/**

View file

@ -38,6 +38,7 @@ import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.home.HomeRoomListDataSource
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
import im.vector.app.features.home.room.detail.timeline.helper.MatrixItemColorProvider
import im.vector.app.features.home.room.detail.timeline.helper.RoomSummaryHolder
import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.html.VectorHtmlCompressor
import im.vector.app.features.login.ReAuthHelper
@ -158,6 +159,8 @@ interface VectorComponent {
fun webRtcCallManager(): WebRtcCallManager
fun roomSummaryHolder(): RoomSummaryHolder
@Component.Factory
interface Factory {
fun create(@BindsInstance context: Context): VectorComponent

View file

@ -1421,7 +1421,7 @@ class RoomDetailViewModel @AssistedInject constructor(
}
override fun onCleared() {
roomSummaryHolder.clear()
roomSummaryHolder.remove(room.roomId)
timeline.dispose()
timeline.removeAllListeners()
if (vectorPreferences.sendTypingNotifs()) {

View file

@ -35,7 +35,6 @@ import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.RoomDetailViewState
import im.vector.app.features.home.room.detail.UnreadState
import im.vector.app.features.home.room.detail.timeline.factory.MergedHeaderItemFactory
import im.vector.app.features.home.room.detail.timeline.factory.NoticeItemFactory
import im.vector.app.features.home.room.detail.timeline.factory.TimelineItemFactory
import im.vector.app.features.home.room.detail.timeline.helper.ContentDownloadStateTrackerBinder
import im.vector.app.features.home.room.detail.timeline.helper.ContentUploadStateTrackerBinder
@ -77,7 +76,6 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
private val mergedHeaderItemFactory: MergedHeaderItemFactory,
private val session: Session,
private val callManager: WebRtcCallManager,
private val noticeItemFactory: NoticeItemFactory,
@TimelineEventControllerHandler
private val backgroundHandler: Handler
) : EpoxyController(backgroundHandler, backgroundHandler), Timeline.Listener, EpoxyController.Interceptor {
@ -104,6 +102,7 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
// TODO move all callbacks to this?
fun onTimelineItemAction(itemAction: RoomDetailAction)
// Introduce ViewModel scoped component (or Hilt?)
fun getPreviewUrlRetriever(): PreviewUrlRetriever
}

View file

@ -196,7 +196,7 @@ class MessageActionsViewModel @AssistedInject constructor(@Assisted
EventType.CALL_CANDIDATES,
EventType.CALL_HANGUP,
EventType.CALL_ANSWER -> {
noticeEventFormatter.format(timelineEvent, room?.roomSummary())
noticeEventFormatter.format(timelineEvent)
}
else -> null
} ?: ""

View file

@ -52,6 +52,7 @@ class CallItemFactory @Inject constructor(
callback: TimelineEventController.Callback?
): VectorEpoxyModel<*>? {
if (event.root.eventId == null) return null
val roomId = event.roomId
val informationData = messageInformationDataFactory.create(event, null)
val callSignalingContent = event.getCallSignallingContent() ?: return null
val callId = callSignalingContent.callId ?: return null
@ -64,6 +65,7 @@ class CallItemFactory @Inject constructor(
return when (event.root.getClearType()) {
EventType.CALL_ANSWER -> {
createCallTileTimelineItem(
roomId = roomId,
callId = callId,
callStatus = CallTileTimelineItem.CallStatus.IN_CALL,
callKind = callKind,
@ -75,6 +77,7 @@ class CallItemFactory @Inject constructor(
}
EventType.CALL_INVITE -> {
createCallTileTimelineItem(
roomId = roomId,
callId = callId,
callStatus = CallTileTimelineItem.CallStatus.INVITED,
callKind = callKind,
@ -86,6 +89,7 @@ class CallItemFactory @Inject constructor(
}
EventType.CALL_REJECT -> {
createCallTileTimelineItem(
roomId = roomId,
callId = callId,
callStatus = CallTileTimelineItem.CallStatus.REJECTED,
callKind = callKind,
@ -97,6 +101,7 @@ class CallItemFactory @Inject constructor(
}
EventType.CALL_HANGUP -> {
createCallTileTimelineItem(
roomId = roomId,
callId = callId,
callStatus = CallTileTimelineItem.CallStatus.ENDED,
callKind = callKind,
@ -121,6 +126,7 @@ class CallItemFactory @Inject constructor(
}
private fun createCallTileTimelineItem(
roomId: String,
callId: String,
callKind: CallTileTimelineItem.CallKind,
callStatus: CallTileTimelineItem.CallStatus,
@ -129,7 +135,7 @@ class CallItemFactory @Inject constructor(
isStillActive: Boolean,
callback: TimelineEventController.Callback?
): CallTileTimelineItem? {
val userOfInterest = roomSummaryHolder.roomSummary?.toMatrixItem() ?: return null
val userOfInterest = roomSummaryHolder.get(roomId)?.toMatrixItem() ?: return null
val attributes = messageItemAttributesFactory.create(null, informationData, callback).let {
CallTileTimelineItem.Attributes(
callId = callId,

View file

@ -77,7 +77,7 @@ class MergedHeaderItemFactory @Inject constructor(private val activeSessionHolde
}
}
private fun isDirectRoom() = roomSummaryHolder.roomSummary?.isDirect.orFalse()
private fun isDirectRoom(roomId: String) = roomSummaryHolder.get(roomId)?.isDirect.orFalse()
private fun buildMembershipEventsMergedSummary(currentPosition: Int,
items: List<TimelineEvent>,
@ -102,7 +102,7 @@ class MergedHeaderItemFactory @Inject constructor(private val activeSessionHolde
memberName = mergedEvent.senderInfo.disambiguatedDisplayName,
localId = mergedEvent.localId,
eventId = mergedEvent.root.eventId ?: "",
isDirectRoom = isDirectRoom()
isDirectRoom = isDirectRoom(event.roomId)
)
mergedData.add(data)
}
@ -174,7 +174,7 @@ class MergedHeaderItemFactory @Inject constructor(private val activeSessionHolde
memberName = mergedEvent.senderInfo.disambiguatedDisplayName,
localId = mergedEvent.localId,
eventId = mergedEvent.root.eventId ?: "",
isDirectRoom = isDirectRoom()
isDirectRoom = isDirectRoom(event.roomId)
)
mergedData.add(data)
}
@ -191,8 +191,7 @@ class MergedHeaderItemFactory @Inject constructor(private val activeSessionHolde
collapsedEventIds.removeAll(mergedEventIds)
}
val mergeId = mergedEventIds.joinToString(separator = "_") { it.toString() }
val powerLevelsHelper = roomSummaryHolder.roomSummary?.roomId
?.let { activeSessionHolder.getSafeActiveSession()?.getRoom(it) }
val powerLevelsHelper = activeSessionHolder.getSafeActiveSession()?.getRoom(event.roomId)
?.let { it.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.NoCondition)?.content?.toModel<PowerLevelsContent>() }
?.let { PowerLevelsHelper(it) }
val currentUserId = activeSessionHolder.getSafeActiveSession()?.myUserId ?: ""
@ -209,7 +208,7 @@ class MergedHeaderItemFactory @Inject constructor(private val activeSessionHolde
readReceiptsCallback = callback,
callback = callback,
currentUserId = currentUserId,
roomSummary = roomSummaryHolder.roomSummary,
roomSummary = roomSummaryHolder.get(event.roomId),
canChangeAvatar = powerLevelsHelper?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_AVATAR) ?: false,
canChangeTopic = powerLevelsHelper?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_TOPIC) ?: false,
canChangeName = powerLevelsHelper?.isUserAllowedToSend(currentUserId, true, EventType.STATE_ROOM_NAME) ?: false

View file

@ -16,6 +16,8 @@
package im.vector.app.features.home.room.detail.timeline.factory
import android.content.Intent
import android.os.Parcelable
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
@ -105,15 +107,17 @@ class MessageItemFactory @Inject constructor(
private val messageItemAttributesFactory: MessageItemAttributesFactory,
private val contentUploadStateTrackerBinder: ContentUploadStateTrackerBinder,
private val contentDownloadStateTrackerBinder: ContentDownloadStateTrackerBinder,
private val roomSummaryHolder: RoomSummaryHolder,
private val defaultItemFactory: DefaultItemFactory,
private val noticeItemFactory: NoticeItemFactory,
private val avatarSizeProvider: AvatarSizeProvider,
private val pillsPostProcessorFactory: PillsPostProcessor.Factory,
private val session: Session) {
// TODO inject this properly?
private var roomId: String = ""
private val pillsPostProcessor by lazy {
pillsPostProcessorFactory.create(roomSummaryHolder.roomSummary?.roomId)
pillsPostProcessorFactory.create(roomId)
}
fun create(event: TimelineEvent,
@ -122,8 +126,8 @@ class MessageItemFactory @Inject constructor(
callback: TimelineEventController.Callback?
): VectorEpoxyModel<*>? {
event.root.eventId ?: return null
roomId = event.roomId
val informationData = messageInformationDataFactory.create(event, nextEvent)
if (event.root.isRedacted()) {
// message is redacted
val attributes = messageItemAttributesFactory.create(null, informationData, callback)
@ -139,7 +143,7 @@ class MessageItemFactory @Inject constructor(
|| event.isEncrypted() && event.root.content.toModel<EncryptedEventContent>()?.relatesTo?.type == RelationType.REPLACE
) {
// This is an edit event, we should display it when debugging as a notice event
return noticeItemFactory.create(event, highlight, roomSummaryHolder.roomSummary, callback)
return noticeItemFactory.create(event, highlight, callback)
}
val attributes = messageItemAttributesFactory.create(messageContent, informationData, callback)
@ -155,7 +159,7 @@ class MessageItemFactory @Inject constructor(
is MessageAudioContent -> buildAudioMessageItem(messageContent, informationData, highlight, attributes)
is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessageOptionsContent -> buildOptionsMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessagePollResponseContent -> noticeItemFactory.create(event, highlight, roomSummaryHolder.roomSummary, callback)
is MessagePollResponseContent -> noticeItemFactory.create(event, highlight, callback)
else -> buildNotHandledMessageItem(messageContent, informationData, highlight, callback, attributes)
}
}
@ -229,14 +233,13 @@ class MessageItemFactory @Inject constructor(
attributes: AbsMessageItem.Attributes): VerificationRequestItem? {
// If this request is not sent by me or sent to me, we should ignore it in timeline
val myUserId = session.myUserId
val roomId = roomSummaryHolder.roomSummary?.roomId
if (informationData.senderId != myUserId && messageContent.toUserId != myUserId) {
return null
}
val otherUserId = if (informationData.sentByMe) messageContent.toUserId else informationData.senderId
val otherUserName = if (informationData.sentByMe) {
session.getRoomMember(messageContent.toUserId, roomId ?: "")?.displayName
session.getRoomMember(messageContent.toUserId, roomId)?.displayName
} else {
informationData.memberName
}

View file

@ -24,7 +24,6 @@ import im.vector.app.features.home.room.detail.timeline.helper.AvatarSizeProvide
import im.vector.app.features.home.room.detail.timeline.helper.MessageInformationDataFactory
import im.vector.app.features.home.room.detail.timeline.item.NoticeItem
import im.vector.app.features.home.room.detail.timeline.item.NoticeItem_
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
import javax.inject.Inject
@ -35,9 +34,8 @@ class NoticeItemFactory @Inject constructor(private val eventFormatter: NoticeEv
fun create(event: TimelineEvent,
highlight: Boolean,
roomSummary: RoomSummary?,
callback: TimelineEventController.Callback?): NoticeItem? {
val formattedText = eventFormatter.format(event, roomSummary) ?: return null
val formattedText = eventFormatter.format(event) ?: return null
val informationData = informationDataFactory.create(event, null)
val attributes = NoticeItem.Attributes(
avatarRenderer = avatarRenderer,

View file

@ -33,7 +33,6 @@ import javax.inject.Inject
class RoomCreateItemFactory @Inject constructor(private val stringProvider: StringProvider,
private val userPreferencesProvider: UserPreferencesProvider,
private val session: Session,
private val roomSummaryHolder: RoomSummaryHolder,
private val noticeItemFactory: NoticeItemFactory) {
fun create(event: TimelineEvent, callback: TimelineEventController.Callback?): VectorEpoxyModel<*>? {
@ -54,7 +53,7 @@ class RoomCreateItemFactory @Inject constructor(private val stringProvider: Stri
private fun defaultRendering(event: TimelineEvent, callback: TimelineEventController.Callback?): VectorEpoxyModel<*>? {
return if (userPreferencesProvider.shouldShowHiddenEvents()) {
noticeItemFactory.create(event, false, roomSummaryHolder.roomSummary, callback)
noticeItemFactory.create(event, false, callback)
} else {
null
}

View file

@ -63,7 +63,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
EventType.STATE_ROOM_WIDGET,
EventType.STATE_ROOM_POWER_LEVELS,
EventType.REACTION,
EventType.REDACTION -> noticeItemFactory.create(event, highlight, roomSummaryHolder.roomSummary, callback)
EventType.REDACTION -> noticeItemFactory.create(event, highlight, callback)
EventType.STATE_ROOM_ENCRYPTION -> encryptionItemFactory.create(event, highlight, callback)
// State room create
EventType.STATE_ROOM_CREATE -> roomCreateItemFactory.create(event, callback)
@ -91,7 +91,7 @@ class TimelineItemFactory @Inject constructor(private val messageItemFactory: Me
// TODO These are not filtered out by timeline when encrypted
// For now manually ignore
if (userPreferencesProvider.shouldShowHiddenEvents()) {
noticeItemFactory.create(event, highlight, roomSummaryHolder.roomSummary, callback)
noticeItemFactory.create(event, highlight, callback)
} else {
null
}

View file

@ -51,7 +51,6 @@ class VerificationItemFactory @Inject constructor(
private val avatarSizeProvider: AvatarSizeProvider,
private val noticeItemFactory: NoticeItemFactory,
private val userPreferencesProvider: UserPreferencesProvider,
private val roomSummaryHolder: RoomSummaryHolder,
private val stringProvider: StringProvider,
private val session: Session
) {
@ -153,7 +152,7 @@ class VerificationItemFactory @Inject constructor(
highlight: Boolean,
callback: TimelineEventController.Callback?
): VectorEpoxyModel<*>? {
if (userPreferencesProvider.shouldShowHiddenEvents()) return noticeItemFactory.create(event, highlight, roomSummaryHolder.roomSummary, callback)
if (userPreferencesProvider.shouldShowHiddenEvents()) return noticeItemFactory.create(event, highlight, callback)
return null
}
}

View file

@ -23,7 +23,6 @@ import im.vector.app.core.resources.StringProvider
import me.gujun.android.span.span
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.message.MessageOptionsContent
import org.matrix.android.sdk.api.session.room.model.message.MessageType
import org.matrix.android.sdk.api.session.room.model.message.OPTION_TYPE_BUTTONS
@ -41,7 +40,7 @@ class DisplayableEventFormatter @Inject constructor(
private val noticeEventFormatter: NoticeEventFormatter
) {
fun format(timelineEvent: TimelineEvent, appendAuthor: Boolean, roomSummary: RoomSummary?): CharSequence {
fun format(timelineEvent: TimelineEvent, appendAuthor: Boolean): CharSequence {
if (timelineEvent.root.isRedacted()) {
return noticeEventFormatter.formatRedactedEvent(timelineEvent.root)
}
@ -131,7 +130,7 @@ class DisplayableEventFormatter @Inject constructor(
}
else -> {
return span {
text = noticeEventFormatter.format(timelineEvent, roomSummary) ?: ""
text = noticeEventFormatter.format(timelineEvent) ?: ""
textStyle = "italic"
}
}

View file

@ -19,6 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.format
import im.vector.app.ActiveSessionDataSource
import im.vector.app.R
import im.vector.app.core.resources.StringProvider
import im.vector.app.features.home.room.detail.timeline.helper.RoomSummaryHolder
import im.vector.app.features.settings.VectorPreferences
import org.matrix.android.sdk.api.extensions.appendNl
import org.matrix.android.sdk.api.extensions.orFalse
@ -55,6 +56,7 @@ class NoticeEventFormatter @Inject constructor(
private val activeSessionDataSource: ActiveSessionDataSource,
private val roomHistoryVisibilityFormatter: RoomHistoryVisibilityFormatter,
private val vectorPreferences: VectorPreferences,
private val roomSummaryHolder: RoomSummaryHolder,
private val sp: StringProvider
) {
@ -65,7 +67,8 @@ class NoticeEventFormatter @Inject constructor(
private fun RoomSummary?.isDm() = this?.isDirect.orFalse()
fun format(timelineEvent: TimelineEvent, rs: RoomSummary?): CharSequence? {
fun format(timelineEvent: TimelineEvent): CharSequence? {
val rs = roomSummaryHolder.get(timelineEvent.roomId)
return when (val type = timelineEvent.root.getClearType()) {
EventType.STATE_ROOM_JOIN_RULES -> formatJoinRulesEvent(timelineEvent.root, timelineEvent.senderInfo.disambiguatedDisplayName, rs)
EventType.STATE_ROOM_CREATE -> formatRoomCreateEvent(timelineEvent.root, rs)

View file

@ -116,7 +116,7 @@ class MessageInformationDataFactory @Inject constructor(private val session: Ses
}
private fun getE2EDecoration(event: TimelineEvent): E2EDecoration {
val roomSummary = roomSummaryHolder.roomSummary
val roomSummary = roomSummaryHolder.get(event.roomId)
return if (
event.root.sendState == SendState.SYNCED
&& roomSummary?.isEncrypted.orFalse()

View file

@ -19,22 +19,26 @@ package im.vector.app.features.home.room.detail.timeline.helper
import im.vector.app.core.di.ScreenScope
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import javax.inject.Inject
import javax.inject.Singleton
/*
This holds an instance of the current room summary.
You should use this in the context of the timeline.
You can use this to share room summary instances within the app.
You should probably use this only in the context of the timeline
*/
@ScreenScope
@Singleton
class RoomSummaryHolder @Inject constructor() {
var roomSummary: RoomSummary? = null
private set
private var roomSummaries = HashMap<String, RoomSummary>()
fun set(roomSummary: RoomSummary) {
this.roomSummary = roomSummary
roomSummaries[roomSummary.roomId] = roomSummary
}
fun get(roomId: String) = roomSummaries[roomId]
fun remove(roomId: String)= roomSummaries.remove(roomId)
fun clear() {
roomSummary = null
roomSummaries.clear()
}
}

View file

@ -86,7 +86,7 @@ class RoomSummaryItemFactory @Inject constructor(private val displayableEventFor
var latestEventTime: CharSequence = ""
val latestEvent = roomSummary.latestPreviewableEvent
if (latestEvent != null) {
latestFormattedEvent = displayableEventFormatter.format(latestEvent, roomSummary.isDirect.not(), roomSummary)
latestFormattedEvent = displayableEventFormatter.format(latestEvent, roomSummary.isDirect.not())
latestEventTime = dateFormatter.format(latestEvent.root.originServerTs, DateFormatKind.ROOM_LIST)
}
val typingMessage = typingHelper.getTypingMessage(roomSummary.typingUsers)

View file

@ -91,7 +91,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St
if (room == null) {
Timber.e("## Unable to resolve room for eventId [$event]")
// Ok room is not known in store, but we can still display something
val body = displayableEventFormatter.format(event, false, null)
val body = displayableEventFormatter.format(event, false)
val roomName = stringProvider.getString(R.string.notification_unknown_room_name)
val senderDisplayName = event.senderInfo.disambiguatedDisplayName
@ -124,7 +124,7 @@ class NotifiableEventResolver @Inject constructor(private val stringProvider: St
}
}
val body = displayableEventFormatter.format(event, false, room.roomSummary()).toString()
val body = displayableEventFormatter.format(event, false).toString()
val roomName = room.roomSummary()?.displayName ?: ""
val senderDisplayName = event.senderInfo.disambiguatedDisplayName