Skip to content

Commit 20d5a41

Browse files
committed
Filter membership/profile/topic events in public rooms
1 parent b88be24 commit 20d5a41

4 files changed

Lines changed: 73 additions & 7 deletions

File tree

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,12 @@ class RustTimeline(
216216
_timelineItems,
217217
backwardPaginationStatus,
218218
forwardPaginationStatus,
219-
joinedRoom.roomInfoFlow.map { it.creators to it.isDm }.distinctUntilChanged(),
219+
joinedRoom.roomInfoFlow.map { Triple(it.creators, it.isDm, it.isPublic) }.distinctUntilChanged(),
220220
) {
221221
timelineItems,
222222
backwardPaginationStatus,
223223
forwardPaginationStatus,
224-
(roomCreators, isDm),
224+
(roomCreators, isDm, isPublic),
225225
->
226226
withContext(dispatcher) {
227227
timelineItems
@@ -230,6 +230,7 @@ class RustTimeline(
230230
items = items,
231231
isDm = isDm,
232232
roomCreator = roomCreators.firstOrNull(),
233+
isPublic = isPublic,
233234
hasMoreToLoadBackwards = backwardPaginationStatus.hasMoreToLoad,
234235
)
235236
}

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,43 @@ import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
1313
import io.element.android.libraries.matrix.api.timeline.Timeline
1414
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
1515
import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
16+
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
1617
import io.element.android.libraries.matrix.api.timeline.item.event.RoomMembershipContent
1718
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
1819

1920
/**
2021
* This timeline post-processor removes the room creation event and the self-join event from the timeline for DMs
21-
* or add the RoomBeginning item.
22+
* or add the RoomBeginning item. For public rooms, it also removes membership and profile change events.
2223
*/
2324
class RoomBeginningPostProcessor(private val mode: Timeline.Mode) {
2425
fun process(
2526
items: List<MatrixTimelineItem>,
2627
isDm: Boolean,
2728
roomCreator: UserId?,
29+
isPublic: Boolean?,
2830
hasMoreToLoadBackwards: Boolean,
2931
): List<MatrixTimelineItem> {
3032
return when {
3133
items.isEmpty() -> items
3234
mode == Timeline.Mode.PinnedEvents -> items
35+
isPublic == true -> filterPublicRoomEvents(items)
3336
isDm -> processForDM(items, roomCreator)
3437
hasMoreToLoadBackwards -> items
3538
else -> processForRoom(items)
3639
}
3740
}
3841

42+
private fun filterPublicRoomEvents(items: List<MatrixTimelineItem>): List<MatrixTimelineItem> {
43+
return items.filter { item ->
44+
val eventContent = (item as? MatrixTimelineItem.Event)?.event?.content
45+
when (eventContent) {
46+
is RoomMembershipContent -> false
47+
is ProfileChangeContent -> false
48+
else -> true
49+
}
50+
}
51+
}
52+
3953
private fun processForRoom(items: List<MatrixTimelineItem>): List<MatrixTimelineItem> {
4054
// No changes needed, timeline start item is already added by the SDK
4155
return items

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ import io.element.android.libraries.matrix.api.core.UniqueId
1212
import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem
1313
import io.element.android.libraries.matrix.api.timeline.item.event.MembershipChange
1414
import io.element.android.libraries.matrix.api.timeline.item.event.OtherState
15+
import io.element.android.libraries.matrix.api.timeline.item.event.ProfileChangeContent
1516
import io.element.android.libraries.matrix.api.timeline.item.event.StateContent
1617
import io.element.android.libraries.matrix.api.timeline.item.virtual.VirtualTimelineItem
1718
import io.element.android.libraries.matrix.test.A_USER_ID
1819
import io.element.android.libraries.matrix.test.A_USER_ID_2
1920
import io.element.android.libraries.matrix.test.timeline.aMessageContent
2021
import io.element.android.libraries.matrix.test.timeline.anEventTimelineItem
22+
import io.element.android.libraries.matrix.test.timeline.aProfileChangeMessageContent
2123
import io.element.android.libraries.matrix.test.timeline.item.event.aRoomMembershipContent
2224

2325
internal val timelineStartEvent = MatrixTimelineItem.Virtual(
@@ -36,6 +38,14 @@ internal val otherMemberJoinEvent = MatrixTimelineItem.Event(
3638
uniqueId = UniqueId("m.room.member_other"),
3739
event = anEventTimelineItem(content = aRoomMembershipContent(userId = A_USER_ID_2, change = MembershipChange.JOINED))
3840
)
41+
internal val otherMemberLeaveEvent = MatrixTimelineItem.Event(
42+
uniqueId = UniqueId("m.room.member_leave"),
43+
event = anEventTimelineItem(content = aRoomMembershipContent(userId = A_USER_ID_2, change = MembershipChange.LEFT))
44+
)
45+
internal val profileChangeEvent = MatrixTimelineItem.Event(
46+
uniqueId = UniqueId("m.room.member_profile"),
47+
event = anEventTimelineItem(content = aProfileChangeMessageContent(displayName = "New Name", prevDisplayName = "Old Name"))
48+
)
3949
internal val messageEvent = MatrixTimelineItem.Event(
4050
uniqueId = UniqueId("m.room.message"),
4151
event = anEventTimelineItem(content = aMessageContent("hi"))

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

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class RoomBeginningPostProcessorTest {
2121
items = emptyList(),
2222
isDm = true,
2323
roomCreator = A_USER_ID,
24+
isPublic = null,
2425
hasMoreToLoadBackwards = false,
2526
)
2627
assertThat(processedItems).isEmpty()
@@ -33,6 +34,7 @@ class RoomBeginningPostProcessorTest {
3334
items = listOf(messageEvent),
3435
isDm = true,
3536
roomCreator = A_USER_ID,
37+
isPublic = null,
3638
hasMoreToLoadBackwards = false,
3739
)
3840
assertThat(processedItems).isEqualTo(listOf(messageEvent))
@@ -45,6 +47,7 @@ class RoomBeginningPostProcessorTest {
4547
items = listOf(messageEvent),
4648
isDm = true,
4749
roomCreator = null,
50+
isPublic = null,
4851
hasMoreToLoadBackwards = false,
4952
)
5053
assertThat(processedItems).isEqualTo(listOf(messageEvent))
@@ -62,6 +65,7 @@ class RoomBeginningPostProcessorTest {
6265
items = timelineItems,
6366
isDm = true,
6467
roomCreator = A_USER_ID,
68+
isPublic = null,
6569
hasMoreToLoadBackwards = false,
6670
)
6771
assertThat(processedItems).containsExactly(timelineStartEvent)
@@ -78,6 +82,7 @@ class RoomBeginningPostProcessorTest {
7882
items = timelineItems,
7983
isDm = true,
8084
roomCreator = A_USER_ID,
85+
isPublic = null,
8186
hasMoreToLoadBackwards = false,
8287
)
8388
assertThat(processedItems).isEqualTo(timelineItems)
@@ -96,7 +101,7 @@ class RoomBeginningPostProcessorTest {
96101
messageEvent,
97102
)
98103
val processor = RoomBeginningPostProcessor(Timeline.Mode.Live)
99-
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = false)
104+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, isPublic = null, hasMoreToLoadBackwards = false)
100105
assertThat(processedItems).isEqualTo(expected)
101106
}
102107

@@ -107,7 +112,7 @@ class RoomBeginningPostProcessorTest {
107112
roomCreatorJoinEvent,
108113
)
109114
val processor = RoomBeginningPostProcessor(Timeline.Mode.Live)
110-
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true)
115+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, isPublic = null, hasMoreToLoadBackwards = true)
111116
assertThat(processedItems).isEmpty()
112117
}
113118

@@ -117,7 +122,7 @@ class RoomBeginningPostProcessorTest {
117122
roomCreatorJoinEvent,
118123
)
119124
val processor = RoomBeginningPostProcessor(Timeline.Mode.Live)
120-
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true)
125+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, isPublic = null, hasMoreToLoadBackwards = true)
121126
assertThat(processedItems).isEmpty()
122127
}
123128

@@ -128,7 +133,43 @@ class RoomBeginningPostProcessorTest {
128133
otherMemberJoinEvent,
129134
)
130135
val processor = RoomBeginningPostProcessor(Timeline.Mode.Live)
131-
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, hasMoreToLoadBackwards = true)
136+
val processedItems = processor.process(timelineItems, isDm = true, roomCreator = A_USER_ID, isPublic = null, hasMoreToLoadBackwards = true)
132137
assertThat(processedItems).isEqualTo(listOf(otherMemberJoinEvent))
133138
}
139+
140+
@Test
141+
fun `processor removes all membership events in public rooms`() {
142+
val timelineItems = listOf(
143+
roomCreateEvent,
144+
roomCreatorJoinEvent,
145+
otherMemberJoinEvent,
146+
messageEvent,
147+
otherMemberLeaveEvent,
148+
profileChangeEvent,
149+
topicEvent,
150+
)
151+
val expected = listOf(
152+
roomCreateEvent,
153+
messageEvent,
154+
)
155+
val processor = RoomBeginningPostProcessor(Timeline.Mode.Live)
156+
val processedItems = processor.process(timelineItems, isDm = false, roomCreator = A_USER_ID, isPublic = true, hasMoreToLoadBackwards = false)
157+
assertThat(processedItems).isEqualTo(expected)
158+
}
159+
160+
@Test
161+
fun `processor keeps membership events in non-public rooms`() {
162+
val timelineItems = listOf(
163+
roomCreateEvent,
164+
roomCreatorJoinEvent,
165+
otherMemberJoinEvent,
166+
messageEvent,
167+
otherMemberLeaveEvent,
168+
profileChangeEvent,
169+
topicEvent,
170+
)
171+
val processor = RoomBeginningPostProcessor(Timeline.Mode.Live)
172+
val processedItems = processor.process(timelineItems, isDm = false, roomCreator = A_USER_ID, isPublic = false, hasMoreToLoadBackwards = false)
173+
assertThat(processedItems).isEqualTo(timelineItems)
174+
}
134175
}

0 commit comments

Comments
 (0)