Skip to content

Commit f87422a

Browse files
committed
Fix filtering of Event at the beginning of DM.
1 parent 9d6c945 commit f87422a

File tree

7 files changed

+150
-43
lines changed

7 files changed

+150
-43
lines changed

libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/room/MatrixRoomInfo.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,6 @@ data class MatrixRoomInfo(
4444
val hasRoomCall: Boolean,
4545
val activeRoomCallParticipants: ImmutableList<String>,
4646
val heroes: ImmutableList<MatrixUser>,
47-
val pinnedEventIds: ImmutableList<EventId>
47+
val pinnedEventIds: ImmutableList<EventId>,
48+
val creator: UserId?,
4849
)

libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/MatrixRoomInfoMapper.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class MatrixRoomInfoMapper {
2828
fun map(rustRoomInfo: RustRoomInfo): MatrixRoomInfo = rustRoomInfo.let {
2929
return MatrixRoomInfo(
3030
id = RoomId(it.id),
31+
creator = it.creator?.let(::UserId),
3132
name = it.displayName,
3233
rawName = it.rawName,
3334
topic = it.topic,

libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/RustTimeline.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,17 @@ class RustTimeline(
207207
_timelineItems,
208208
backPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(),
209209
forwardPaginationStatus.map { it.hasMoreToLoad }.distinctUntilChanged(),
210+
matrixRoom.roomInfoFlow.map { it.creator },
210211
isInit,
211-
) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward, isInit ->
212+
) { timelineItems, hasMoreToLoadBackward, hasMoreToLoadForward, roomCreator, isInit ->
212213
withContext(dispatcher) {
213214
timelineItems
214215
.process { items ->
215216
roomBeginningPostProcessor.process(
216217
items = items,
217218
isDm = matrixRoom.isDm,
218-
hasMoreToLoadBackwards = hasMoreToLoadBackward
219+
roomCreator = roomCreator,
220+
hasMoreToLoadBackwards = hasMoreToLoadBackward,
219221
)
220222
}
221223
.process(predicate = isInit) { items ->

libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessor.kt

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package io.element.android.libraries.matrix.impl.timeline.postprocessor
99

1010
import androidx.annotation.VisibleForTesting
1111
import io.element.android.libraries.matrix.api.core.UniqueId
12+
import io.element.android.libraries.matrix.api.core.UserId
1213
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
1314
import io.element.android.libraries.matrix.api.timeline.Timeline
1415
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
@@ -25,12 +26,14 @@ class RoomBeginningPostProcessor(private val mode: Timeline.Mode) {
2526
fun process(
2627
items: List<MatrixTimelineItem>,
2728
isDm: Boolean,
28-
hasMoreToLoadBackwards: Boolean
29+
roomCreator: UserId?,
30+
hasMoreToLoadBackwards: Boolean,
2931
): List<MatrixTimelineItem> {
3032
return when {
33+
items.isEmpty() -> items
3134
mode == Timeline.Mode.PINNED_EVENTS -> items
35+
isDm -> processForDM(items, roomCreator)
3236
hasMoreToLoadBackwards -> items
33-
isDm -> processForDM(items)
3437
else -> processForRoom(items)
3538
}
3639
}
@@ -40,22 +43,28 @@ class RoomBeginningPostProcessor(private val mode: Timeline.Mode) {
4043
return listOf(roomBeginningItem) + items
4144
}
4245

43-
private fun processForDM(items: List<MatrixTimelineItem>): List<MatrixTimelineItem> {
44-
// Find room creation event. This is usually index 0
46+
private fun processForDM(items: List<MatrixTimelineItem>, roomCreator: UserId?): List<MatrixTimelineItem> {
47+
// Find room creation event.
48+
// This is usually the first MatrixTimelineItem.Event (so index 1, index 0 is a date)
4549
val roomCreationEventIndex = items.indexOfFirst {
4650
val stateEventContent = (it as? MatrixTimelineItem.Event)?.event?.content as? StateContent
4751
stateEventContent?.content is OtherState.RoomCreate
4852
}
4953

50-
// Find self-join event for room creator. This is usually index 1
51-
val roomCreatorUserId = (items.getOrNull(roomCreationEventIndex) as? MatrixTimelineItem.Event)?.event?.sender
54+
// If the parameter roomCreator is null, the creator is the sender of the RoomCreate Event.
55+
val roomCreatorUserId = roomCreator ?: (items.getOrNull(roomCreationEventIndex) as? MatrixTimelineItem.Event)?.event?.sender
56+
// Find self-join event for the room creator.
57+
// This is usually the second MatrixTimelineItem.Event (so index 2)
5258
val selfUserJoinedEventIndex = roomCreatorUserId?.let { creatorUserId ->
5359
items.indexOfFirst {
5460
val stateEventContent = (it as? MatrixTimelineItem.Event)?.event?.content as? RoomMembershipContent
5561
stateEventContent?.change == MembershipChange.JOINED && stateEventContent.userId == creatorUserId
5662
}
5763
} ?: -1
5864

65+
if (roomCreationEventIndex == -1 && selfUserJoinedEventIndex == -1) {
66+
return items
67+
}
5968
// Remove items at the indices we found
6069
val newItems = items.toMutableList()
6170
if (selfUserJoinedEventIndex in newItems.indices) {

libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomSummaryListProcessorTest.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ package io.element.android.libraries.matrix.impl.roomlist
1010
import com.google.common.truth.Truth.assertThat
1111
import com.sun.jna.Pointer
1212
import io.element.android.libraries.matrix.api.core.RoomId
13+
import io.element.android.libraries.matrix.api.core.UserId
1314
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
1415
import io.element.android.libraries.matrix.test.A_ROOM_ID
1516
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
@@ -215,6 +216,7 @@ private fun aRustRoomInfo(
215216
numUnreadNotifications: ULong = 0uL,
216217
numUnreadMentions: ULong = 0uL,
217218
pinnedEventIds: List<String> = listOf(),
219+
roomCreator: UserId? = null,
218220
) = RoomInfo(
219221
id = id,
220222
displayName = displayName,
@@ -245,6 +247,7 @@ private fun aRustRoomInfo(
245247
numUnreadNotifications = numUnreadNotifications,
246248
numUnreadMentions = numUnreadMentions,
247249
pinnedEventIds = pinnedEventIds,
250+
creator = roomCreator?.value,
248251
)
249252

250253
class FakeRoomListItem(

libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/timeline/postprocessor/RoomBeginningPostProcessorTest.kt

Lines changed: 123 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -22,85 +22,174 @@ import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
2222
import org.junit.Test
2323

2424
class RoomBeginningPostProcessorTest {
25+
private val roomCreateEvent = MatrixTimelineItem.Event(
26+
uniqueId = UniqueId("m.room.create"),
27+
event = anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))
28+
)
29+
private val roomCreatorJoinEvent = MatrixTimelineItem.Event(
30+
uniqueId = UniqueId("m.room.member"),
31+
event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))
32+
)
33+
private val otherMemberJoinEvent = MatrixTimelineItem.Event(
34+
uniqueId = UniqueId("m.room.member_other"),
35+
event = anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))
36+
)
37+
private val messageEvent = MatrixTimelineItem.Event(
38+
uniqueId = UniqueId("m.room.message"),
39+
event = anEventTimelineItem(content = aMessageContent("hi"))
40+
)
41+
42+
@Test
43+
fun `processor returns empty list when empty list is provided`() {
44+
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
45+
val processedItems = processor.process(
46+
items = emptyList(),
47+
isDm = true,
48+
roomCreator = A_USER_ID,
49+
hasMoreToLoadBackwards = false,
50+
)
51+
assertThat(processedItems).isEmpty()
52+
}
53+
54+
@Test
55+
fun `processor returns the provided list when it only contains a message`() {
56+
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
57+
val processedItems = processor.process(
58+
items = listOf(messageEvent),
59+
isDm = true,
60+
roomCreator = A_USER_ID,
61+
hasMoreToLoadBackwards = false,
62+
)
63+
assertThat(processedItems).isEqualTo(listOf(messageEvent))
64+
}
65+
66+
@Test
67+
fun `processor returns the provided list when it only contains a message and the roomCreator is not provided`() {
68+
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
69+
val processedItems = processor.process(
70+
items = listOf(messageEvent),
71+
isDm = true,
72+
roomCreator = null,
73+
hasMoreToLoadBackwards = false,
74+
)
75+
assertThat(processedItems).isEqualTo(listOf(messageEvent))
76+
}
77+
2578
@Test
2679
fun `processor removes room creation event and self-join event from DM timeline`() {
2780
val timelineItems = listOf(
28-
MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))),
29-
MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))),
81+
roomCreateEvent,
82+
roomCreatorJoinEvent,
3083
)
3184
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
32-
val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = false)
85+
val processedItems = processor.process(
86+
items = timelineItems,
87+
isDm = true,
88+
roomCreator = A_USER_ID,
89+
hasMoreToLoadBackwards = false,
90+
)
3391
assertThat(processedItems).isEmpty()
3492
}
3593

94+
@Test
95+
fun `processor does not remove anything with PINNED_EVENTS mode`() {
96+
val timelineItems = listOf(
97+
roomCreateEvent,
98+
roomCreatorJoinEvent,
99+
)
100+
val processor = RoomBeginningPostProcessor(Timeline.Mode.PINNED_EVENTS)
101+
val processedItems = processor.process(
102+
items = timelineItems,
103+
isDm = true,
104+
roomCreator = A_USER_ID,
105+
hasMoreToLoadBackwards = false,
106+
)
107+
assertThat(processedItems).isEqualTo(timelineItems)
108+
}
109+
36110
@Test
37111
fun `processor removes room creation event and self-join event from DM timeline even if they're not the first items`() {
38112
val timelineItems = listOf(
39-
MatrixTimelineItem.Event(
40-
UniqueId("m.room.member_other"),
41-
anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))
42-
),
43-
MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))),
44-
MatrixTimelineItem.Event(UniqueId("m.room.message"), anEventTimelineItem(content = aMessageContent("hi"))),
45-
MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))),
113+
otherMemberJoinEvent,
114+
roomCreateEvent,
115+
messageEvent,
116+
roomCreatorJoinEvent,
46117
)
47118
val expected = listOf(
48-
MatrixTimelineItem.Event(
49-
UniqueId("m.room.member_other"),
50-
anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))
51-
),
52-
MatrixTimelineItem.Event(UniqueId("m.room.message"), anEventTimelineItem(content = aMessageContent("hi"))),
119+
otherMemberJoinEvent,
120+
messageEvent,
53121
)
54122
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
55-
val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = false)
123+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = false)
56124
assertThat(processedItems).isEqualTo(expected)
57125
}
58126

59127
@Test
60128
fun `processor will add beginning of room item if it's not a DM`() {
61129
val timelineItems = listOf(
62-
MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))),
63-
MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))),
130+
roomCreateEvent,
131+
roomCreatorJoinEvent,
64132
)
65133
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
66-
val processedItems = processor.process(timelineItems, isDm = false, hasMoreToLoadBackwards = false)
134+
val processedItems = processor.process(timelineItems, isDm = false, roomCreator = A_USER_ID, hasMoreToLoadBackwards = false)
67135
assertThat(processedItems).isEqualTo(
68136
listOf(processor.createRoomBeginningItem()) + timelineItems
69137
)
70138
}
71139

72140
@Test
73-
fun `processor won't remove items if it's not at the start of the timeline`() {
141+
fun `processor will not add beginning of room item if it's not a DM but the room has more to load`() {
74142
val timelineItems = listOf(
75-
MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))),
76-
MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))),
143+
roomCreateEvent,
144+
roomCreatorJoinEvent,
77145
)
78146
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
79-
val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true)
147+
val processedItems = processor.process(timelineItems, isDm = false, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true)
80148
assertThat(processedItems).isEqualTo(timelineItems)
81149
}
82150

83151
@Test
84-
fun `processor won't remove the first member join event if it can't find the room creation event`() {
152+
fun `processor will add beginning of room item if it's not a DM, when the parameter roomCreator is null`() {
85153
val timelineItems = listOf(
86-
MatrixTimelineItem.Event(UniqueId("m.room.member"), anEventTimelineItem(content = RoomMembershipContent(A_USER_ID, null, MembershipChange.JOINED))),
154+
roomCreateEvent,
155+
roomCreatorJoinEvent,
87156
)
88157
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
89-
val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true)
90-
assertThat(processedItems).isEqualTo(timelineItems)
158+
val processedItems = processor.process(timelineItems, isDm = false, roomCreator = null, hasMoreToLoadBackwards = false)
159+
assertThat(processedItems).isEqualTo(
160+
listOf(processor.createRoomBeginningItem()) + timelineItems
161+
)
162+
}
163+
164+
@Test
165+
fun `processor removes items event it's not at the start of the timeline`() {
166+
val timelineItems = listOf(
167+
roomCreateEvent,
168+
roomCreatorJoinEvent,
169+
)
170+
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
171+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true)
172+
assertThat(processedItems).isEmpty()
173+
}
174+
175+
@Test
176+
fun `processor removes the first member join event if it matches the roomCreator parameter`() {
177+
val timelineItems = listOf(
178+
roomCreatorJoinEvent,
179+
)
180+
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
181+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true)
182+
assertThat(processedItems).isEmpty()
91183
}
92184

93185
@Test
94186
fun `processor won't remove the first member join event if it's not from the room creator`() {
95187
val timelineItems = listOf(
96-
MatrixTimelineItem.Event(UniqueId("m.room.create"), anEventTimelineItem(sender = A_USER_ID, content = StateContent("", OtherState.RoomCreate))),
97-
MatrixTimelineItem.Event(
98-
UniqueId("m.room.member"),
99-
anEventTimelineItem(content = RoomMembershipContent(A_USER_ID_2, null, MembershipChange.JOINED))
100-
),
188+
roomCreateEvent,
189+
otherMemberJoinEvent,
101190
)
102191
val processor = RoomBeginningPostProcessor(Timeline.Mode.LIVE)
103-
val processedItems = processor.process(timelineItems, isDm = true, hasMoreToLoadBackwards = true)
104-
assertThat(processedItems).isEqualTo(timelineItems)
192+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true)
193+
assertThat(processedItems).isEqualTo(listOf(otherMemberJoinEvent))
105194
}
106195
}

libraries/matrix/test/src/main/kotlin/io/element/android/libraries/matrix/test/room/FakeMatrixRoom.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ fun aRoomInfo(
523523
activeRoomCallParticipants: List<String> = emptyList(),
524524
heroes: List<MatrixUser> = emptyList(),
525525
pinnedEventIds: List<EventId> = emptyList(),
526+
roomCreator: UserId? = null,
526527
) = MatrixRoomInfo(
527528
id = id,
528529
name = name,
@@ -549,6 +550,7 @@ fun aRoomInfo(
549550
activeRoomCallParticipants = activeRoomCallParticipants.toImmutableList(),
550551
heroes = heroes.toImmutableList(),
551552
pinnedEventIds = pinnedEventIds.toImmutableList(),
553+
creator = roomCreator,
552554
)
553555

554556
fun defaultRoomPowerLevels() = MatrixRoomPowerLevels(

0 commit comments

Comments
 (0)