Invalidate the timeline when the DM state changes for a room

We need to redraw messages when this changes, since we use different
layouts for DMs and non-direct chats.

Change-Id: Icf2df3a14655f7c9b6e5f7cdb29b590f393de4fd
This commit is contained in:
SpiritCroc 2021-05-20 13:22:37 +02:00
parent b5e3a83ff2
commit d3ca5d0db0
5 changed files with 62 additions and 0 deletions

View file

@ -95,6 +95,11 @@ interface Timeline {
*/
fun getTimelineEventWithId(eventId: String?): TimelineEvent?
/**
* Called when the DM flag of the room is changed
*/
fun onDmStateChanged()
interface Listener {
/**
* Call when the timeline has been updated through pagination or sync.
@ -112,6 +117,11 @@ interface Timeline {
* Called when new events come through the sync
*/
fun onNewTimelineEvents(eventIds: List<String>)
/**
* Called when the DM flag of the room is changed
*/
fun onDmStateChanged()
}
/**

View file

@ -285,6 +285,12 @@ internal class DefaultTimeline(
}
}
override fun onDmStateChanged() {
listeners.forEach {
it.onDmStateChanged()
}
}
override fun rebuildEvent(eventId: String, builder: (TimelineEvent) -> TimelineEvent?): Boolean {
return tryOrNull {
builtEventsIdMap[eventId]?.let { builtIndex ->

View file

@ -1498,6 +1498,7 @@ class RoomDetailViewModel @AssistedInject constructor(
private fun observeSummaryState() {
asyncSubscribe(RoomDetailViewState::asyncRoomSummary) { summary ->
val previousSummary = roomSummariesHolder.get(summary.roomId)
roomSummariesHolder.set(summary)
setState {
val typingMessage = typingHelper.getTypingMessage(summary.typingUsers)
@ -1516,6 +1517,9 @@ class RoomDetailViewModel @AssistedInject constructor(
room.getStateEvent(EventType.STATE_ROOM_TOMBSTONE)?.also {
setState { copy(tombstoneEvent = it) }
}
if (previousSummary == null || previousSummary.isDirect != summary.isDirect) {
timeline.onDmStateChanged()
}
}
}
@ -1567,4 +1571,8 @@ class RoomDetailViewModel @AssistedInject constructor(
callManager.removePstnSupportListener(this)
super.onCleared()
}
override fun onDmStateChanged() {
// No-op
}
}

View file

@ -46,6 +46,7 @@ import im.vector.app.features.home.room.detail.timeline.helper.TimelineEventDiff
import im.vector.app.features.home.room.detail.timeline.helper.TimelineEventVisibilityHelper
import im.vector.app.features.home.room.detail.timeline.helper.TimelineEventVisibilityStateChangedListener
import im.vector.app.features.home.room.detail.timeline.factory.TimelineItemFactoryParams
import im.vector.app.features.home.room.detail.timeline.helper.InvalidateTimelineEventDiffUtilCallback
import im.vector.app.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider
import im.vector.app.features.home.room.detail.timeline.item.AbsMessageItem
import im.vector.app.features.home.room.detail.timeline.item.BasedMergedItem
@ -292,6 +293,18 @@ class TimelineEventController @Inject constructor(private val dateFormatter: Vec
// no-op, already handled
}
override fun onDmStateChanged() {
backgroundHandler.post {
inSubmitList = true
// Invalidate all timeline events to rebuild the whole Room/DM layout
val diffCallback = InvalidateTimelineEventDiffUtilCallback(currentSnapshot)
val diffResult = DiffUtil.calculateDiff(diffCallback)
diffResult.dispatchUpdatesTo(listUpdateCallback)
requestModelBuild()
inSubmitList = false
}
}
private fun submitSnapshot(newSnapshot: List<TimelineEvent>) {
backgroundHandler.post {
inSubmitList = true

View file

@ -0,0 +1,25 @@
package im.vector.app.features.home.room.detail.timeline.helper
import androidx.recyclerview.widget.DiffUtil
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
class InvalidateTimelineEventDiffUtilCallback(private val oldAndNewList: List<TimelineEvent>): DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldAndNewList.size
}
override fun getNewListSize(): Int {
return oldAndNewList.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
// We want to 'fake' updated items with this class - updated means in this case, not completely invalidated.
return oldItemPosition == newItemPosition
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
// We want to 'fake' updated items with this class.
return false
}
}