Rich replies: Use live sender info for reply name, if wanted

Change-Id: I3de535c9fdbe7fcff54bee486182b1d84464f832
This commit is contained in:
SpiritCroc 2022-11-22 11:28:59 +01:00
parent 772ff30045
commit bbbefae75c
7 changed files with 39 additions and 6 deletions

View file

@ -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.
* <p>
@ -111,6 +113,11 @@ interface Timeline {
*/
fun getSnapshot(): List<TimelineEvent>
/**
* 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.

View file

@ -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)

View file

@ -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) {

View file

@ -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<RoomDetailViewState, RoomDetailAction, RoomDetailViewEvents>(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

View file

@ -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)

View file

@ -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()
}

View file

@ -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.