diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt index 4a0418bc9a..350d60d396 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/timeline/Timeline.kt @@ -16,6 +16,8 @@ package org.matrix.android.sdk.api.session.room.timeline +import org.matrix.android.sdk.api.session.room.sender.SenderInfo + /** * A Timeline instance represents a contiguous sequence of events in a room. *

@@ -111,6 +113,11 @@ interface Timeline { */ fun getSnapshot(): List + /** + * Applies live state to the senderInfo, if live info is enabled in the timeline's settings. + */ + fun senderWithLiveRoomState(senderInfo: SenderInfo): SenderInfo + interface Listener { /** * Call when the timeline has been updated through pagination or sync. diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt index d473d8af3e..0803f46609 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/DefaultTimeline.kt @@ -38,6 +38,7 @@ import okhttp3.internal.closeQuietly import org.matrix.android.sdk.api.MatrixCoroutineDispatchers import org.matrix.android.sdk.api.extensions.tryOrNull import org.matrix.android.sdk.api.session.room.model.Membership +import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings @@ -217,6 +218,8 @@ internal class DefaultTimeline( return strategy.buildSnapshot() } + override fun senderWithLiveRoomState(senderInfo: SenderInfo): SenderInfo = strategy.senderWithLiveRoomState(senderInfo) + override fun getIndexOfEvent(eventId: String?): Int? { if (eventId == null) return null return strategy.getBuiltEventIndex(eventId) diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt index e6b3058268..2675ca5789 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/timeline/LoadTimelineStrategy.kt @@ -30,6 +30,7 @@ import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.failure.MatrixError import org.matrix.android.sdk.api.session.room.send.SendState +import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineSettings @@ -275,6 +276,15 @@ internal class LoadTimelineStrategy constructor( } } + fun senderWithLiveRoomState(senderInfo: SenderInfo): SenderInfo { + return if (dependencies.timelineSettings.useLiveSenderInfo) { + val updatedState = liveRoomStateListener.getLiveState(senderInfo.userId) ?: return senderInfo + senderInfo.copy(avatarUrl = updatedState.avatarUrl, displayName = updatedState.displayName) + } else { + senderInfo + } + } + private fun applyLiveRoomState(event: TimelineEvent): TimelineEvent { val updatedState = liveRoomStateListener.getLiveState(event.senderInfo.userId) return if (updatedState != null) { diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt index 310464e369..352557e294 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineViewModel.kt @@ -126,6 +126,7 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon import org.matrix.android.sdk.api.session.room.model.tombstone.RoomTombstoneContent import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper import org.matrix.android.sdk.api.session.room.read.ReadService +import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.room.timeline.Timeline import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.isLiveLocation @@ -174,7 +175,7 @@ class TimelineViewModel @AssistedInject constructor( spanUtils: SpanUtils, ) : VectorViewModel(initialState), Timeline.Listener, ChatEffectManager.Delegate, CallProtocolsChecker.Listener, LocationSharingServiceConnection.Callback, - ReplyPreviewRetriever.PowerLevelProvider { + ReplyPreviewRetriever.PowerLevelProvider, ReplyPreviewRetriever.PreviewReplyRetrieverCallback { private val room = session.getRoom(initialState.roomId) private val eventId = initialState.eventId ?: if (loadRoomAtFirstUnread() && initialState.rootThreadEventId == null) room?.roomSummary()?.readMarkerId else null @@ -194,13 +195,15 @@ class TimelineViewModel @AssistedInject constructor( displayableEventFormatter, pillsPostProcessorFactory, textRendererFactory, + this, this, messageColorProvider, - this, htmlCompressor, htmlRenderer, spanUtils ) + override fun resolveDisplayName(senderInfo: SenderInfo): String = (timeline?.senderWithLiveRoomState(senderInfo) ?: senderInfo).disambiguatedDisplayName + // Slot to keep a pending action during permission request var pendingAction: RoomDetailAction? = null diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/InReplyToView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/InReplyToView.kt index c50d35eba8..0e22bca042 100755 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/InReplyToView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/InReplyToView.kt @@ -154,7 +154,7 @@ class InReplyToView @JvmOverloads constructor( hideViews() isVisible = true views.replyMemberNameView.isVisible = true - views.replyMemberNameView.text = state.event.senderInfo.disambiguatedDisplayName + views.replyMemberNameView.text = state.senderName val senderColor = retriever.getMemberNameColor(state.event, roomInformationData) views.replyMemberNameView.setTextColor(senderColor) views.inReplyToBar.setBackgroundColor(senderColor) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/PreviewReplyUiState.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/PreviewReplyUiState.kt index 5e7b525786..7765e812fc 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/PreviewReplyUiState.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/PreviewReplyUiState.kt @@ -39,6 +39,7 @@ sealed class PreviewReplyUiState { // Is a reply data class InReplyTo( override val repliedToEventId: String, - val event: TimelineEvent + val event: TimelineEvent, + val senderName: String, ) : PreviewReplyUiState() } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/ReplyPreviewRetriever.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/ReplyPreviewRetriever.kt index f4227c3c36..be23e76c73 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/ReplyPreviewRetriever.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/reply/ReplyPreviewRetriever.kt @@ -39,6 +39,7 @@ import org.matrix.android.sdk.api.session.events.model.getRelationContent 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.powerlevels.PowerLevelsHelper +import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.getLatestEventId import org.matrix.android.sdk.api.util.MatrixItem @@ -53,8 +54,9 @@ class ReplyPreviewRetriever( private val displayableEventFormatter: DisplayableEventFormatter, private val pillsPostProcessorFactory: PillsPostProcessor.Factory, private val textRendererFactory: EventTextRenderer.Factory, + private val callback: PreviewReplyRetrieverCallback, + private val powerLevelProvider: PowerLevelProvider, val messageColorProvider: MessageColorProvider, - val powerLevelProvider: PowerLevelProvider, val htmlCompressor: VectorHtmlCompressor, val htmlRenderer: EventHtmlRenderer, val spanUtils: SpanUtils, @@ -190,7 +192,10 @@ class ReplyPreviewRetriever( synchronized(data) { updateState(eventId, eventIdToRetrieve, if (it == null) PreviewReplyUiState.Error(Exception("Event not found"), eventIdToRetrieve) // TODO proper exception or sth. - else PreviewReplyUiState.InReplyTo(eventIdToRetrieve, it) + else { + val senderName = callback.resolveDisplayName(it.senderInfo) + PreviewReplyUiState.InReplyTo(eventIdToRetrieve, it, senderName) + } ) } }, @@ -258,6 +263,10 @@ class ReplyPreviewRetriever( ) } + interface PreviewReplyRetrieverCallback { + fun resolveDisplayName(senderInfo: SenderInfo): String + } + fun formatFallbackReply(event: TimelineEvent): CharSequence { return displayableEventFormatter.format(event, // This is not a preview in the traditional sense, as sender information is rendered outside either way.