Timeline: make group id really stable

This commit is contained in:
ganfra 2023-07-13 17:21:56 +02:00
parent 231f278adb
commit a07305314f
2 changed files with 36 additions and 10 deletions

View file

@ -17,10 +17,20 @@
package io.element.android.features.messages.impl.timeline.groups package io.element.android.features.messages.impl.timeline.groups
import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn
import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toImmutableList
import javax.inject.Inject import javax.inject.Inject
@SingleIn(RoomScope::class)
class TimelineItemGrouper @Inject constructor() { class TimelineItemGrouper @Inject constructor() {
/**
* Keys are identifier of items in a group, only one by group will be kept.
* Values are the actual groupIds.
*/
private val groupIds = HashMap<String, String>()
/** /**
* Create a new list of [TimelineItem] by grouping some of them into [TimelineItem.GroupedEvents]. * Create a new list of [TimelineItem] by grouping some of them into [TimelineItem.GroupedEvents].
*/ */
@ -34,14 +44,14 @@ class TimelineItemGrouper @Inject constructor() {
// timelineItem cannot be grouped // timelineItem cannot be grouped
if (currentGroup.isNotEmpty()) { if (currentGroup.isNotEmpty()) {
// There is a pending group, create a TimelineItem.GroupedEvents if there is more than 1 Event in the pending group. // There is a pending group, create a TimelineItem.GroupedEvents if there is more than 1 Event in the pending group.
result.addGroup(currentGroup) result.addGroup(groupIds, currentGroup)
currentGroup.clear() currentGroup.clear()
} }
result.add(timelineItem) result.add(timelineItem)
} }
} }
if (currentGroup.isNotEmpty()) { if (currentGroup.isNotEmpty()) {
result.addGroup(currentGroup) result.addGroup(groupIds, currentGroup)
} }
return result return result
} }
@ -51,16 +61,33 @@ class TimelineItemGrouper @Inject constructor() {
* Will add a group if there is more than 1 item, else add the item to the list. * Will add a group if there is more than 1 item, else add the item to the list.
*/ */
private fun MutableList<TimelineItem>.addGroup( private fun MutableList<TimelineItem>.addGroup(
group: MutableList<TimelineItem.Event> groupIds: MutableMap<String, String>,
groupOfItems: MutableList<TimelineItem.Event>
) { ) {
if (group.size == 1) { if (groupOfItems.size == 1) {
// Do not create a group with just 1 item, just add the item to the result // Do not create a group with just 1 item, just add the item to the result
add(group.first()) add(groupOfItems.first())
} else { } else {
val groupId = groupIds.getOrPutGroupId(groupOfItems)
add( add(
TimelineItem.GroupedEvents( TimelineItem.GroupedEvents(
events = group.toImmutableList() id = groupId,
events = groupOfItems.toImmutableList()
) )
) )
} }
} }
private fun MutableMap<String, String>.getOrPutGroupId(timelineItems: List<TimelineItem>): String {
assert(timelineItems.isNotEmpty())
for (item in timelineItems) {
val itemIdentifier = item.identifier()
if (this.contains(itemIdentifier)) {
return this[itemIdentifier]!!
}
}
val itemIdentifier = timelineItems.first().identifier()
return "${itemIdentifier}_group".also { groupId ->
this[itemIdentifier] = groupId
}
}

View file

@ -82,9 +82,8 @@ sealed interface TimelineItem {
@Immutable @Immutable
data class GroupedEvents( data class GroupedEvents(
val id: String,
val events: ImmutableList<Event>, val events: ImmutableList<Event>,
) : TimelineItem { ) : TimelineItem
// use last id with a suffix. Last will not change in cas of new event from backpagination.
val id = "${events.last().id}_group"
}
} }