From db424b6e41dfe663402b8e1eab777a9a1fc3bdbc Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 2 Oct 2025 16:15:33 +0200 Subject: [PATCH 1/3] feature(space) : ensure RoomSummaryRow can display space invites --- .../features/home/impl/components/RoomSummaryRow.kt | 12 ++++++++---- .../impl/datasource/RoomListRoomSummaryFactory.kt | 1 + .../features/home/impl/model/RoomListRoomSummary.kt | 1 + .../home/impl/model/RoomListRoomSummaryProvider.kt | 11 +++++++++++ .../home/impl/model/RoomListBaseRoomSummaryTest.kt | 2 ++ 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt index 3036865eea..c5e1798baa 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/components/RoomSummaryRow.kt @@ -189,10 +189,14 @@ private fun RoomSummaryScaffoldRow( ) { Avatar( avatarData = room.avatarData, - avatarType = AvatarType.Room( - heroes = room.heroes, - isTombstoned = room.isTombstoned, - ), + avatarType = if (room.isSpace) { + AvatarType.Space(isTombstoned = room.isTombstoned) + } else { + AvatarType.Room( + heroes = room.heroes, + isTombstoned = room.isTombstoned, + ) + }, hideImage = hideAvatarImage, ) Spacer(modifier = Modifier.width(16.dp)) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt index b6f908fd5d..ffd6f640ac 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/datasource/RoomListRoomSummaryFactory.kt @@ -69,6 +69,7 @@ class RoomListRoomSummaryFactory( user.getAvatarData(size = AvatarSize.RoomListItem) }.toImmutableList(), isTombstoned = roomInfo.successorRoom != null, + isSpace = roomInfo.isSpace, ) } } diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt index 3f166a66b4..8af359d3e5 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummary.kt @@ -38,6 +38,7 @@ data class RoomListRoomSummary( val inviteSender: InviteSender?, val isTombstoned: Boolean, val heroes: ImmutableList, + val isSpace: Boolean, ) { val isHighlighted = userDefinedNotificationMode != RoomNotificationMode.MUTE && (numberOfUnreadNotifications > 0 || numberOfUnreadMentions > 0) || diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt index f06e5a1a27..1e763843af 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/model/RoomListRoomSummaryProvider.kt @@ -102,6 +102,15 @@ open class RoomListRoomSummaryProvider : PreviewParameterProvider = emptyList(), isTombstoned: Boolean = false, + isSpace: Boolean = false, ) = RoomListRoomSummary( id = id, roomId = RoomId(id), @@ -172,4 +182,5 @@ internal fun aRoomListRoomSummary( canonicalAlias = canonicalAlias, heroes = heroes.toImmutableList(), isTombstoned = isTombstoned, + isSpace = isSpace ) diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt index 55b3f1ffee..4f9b047990 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/model/RoomListBaseRoomSummaryTest.kt @@ -85,6 +85,7 @@ internal fun createRoomListRoomSummary( heroes: List = emptyList(), timestamp: String? = null, isTombstoned: Boolean = false, + isSpace: Boolean = false, ) = RoomListRoomSummary( id = A_ROOM_ID.value, roomId = A_ROOM_ID, @@ -106,4 +107,5 @@ internal fun createRoomListRoomSummary( isDm = false, heroes = heroes.toPersistentList(), isTombstoned = isTombstoned, + isSpace = isSpace ) From 576429b183c5ae9015955c88b1a720557078bf59 Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 2 Oct 2025 17:38:47 +0200 Subject: [PATCH 2/3] feature(space) : filter space manually so we can show space invites --- .../matrix/api/roomlist/RoomListFilter.kt | 3 +- .../matrix/impl/roomlist/RoomListFactory.kt | 1 - .../matrix/impl/roomlist/RoomListFilter.kt | 44 +++++++++++++------ .../impl/roomlist/RoomListFilterTest.kt | 28 ++++++++---- 4 files changed, 51 insertions(+), 25 deletions(-) diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListFilter.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListFilter.kt index 8b9b84eb18..405906a185 100644 --- a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListFilter.kt +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/roomlist/RoomListFilter.kt @@ -58,11 +58,12 @@ sealed interface RoomListFilter { data object Invite : RoomListFilter /** - * A filter that matches either Group or People rooms. + * A filter that matches either Group,People rooms or Space. */ sealed interface Category : RoomListFilter { data object Group : Category data object People : Category + data object Space : Category } /** diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt index 15ba644fcf..53b8127ab8 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFactory.kt @@ -29,7 +29,6 @@ import org.matrix.rustcomponents.sdk.RoomList as InnerRoomList private val ROOM_LIST_RUST_FILTERS = listOf( RoomListEntriesDynamicFilterKind.NonLeft, - RoomListEntriesDynamicFilterKind.NonSpace, RoomListEntriesDynamicFilterKind.DeduplicateVersions ) diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilter.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilter.kt index 1e4a3fad3e..3fc59d7c44 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilter.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilter.kt @@ -15,41 +15,57 @@ import io.element.android.libraries.matrix.api.roomlist.RoomSummary val RoomListFilter.predicate get() = when (this) { - is RoomListFilter.All -> { _: RoomSummary -> true } - is RoomListFilter.Any -> { _: RoomSummary -> true } - RoomListFilter.None -> { _: RoomSummary -> false } + is RoomListFilter.All -> { roomSummary -> NonSpacePredicate(roomSummary) || IsInvitedPredicate(roomSummary) } + is RoomListFilter.Any -> { roomSummary -> NonSpacePredicate(roomSummary) || IsInvitedPredicate(roomSummary) } + RoomListFilter.None -> { _ -> false } RoomListFilter.Category.Group -> { roomSummary: RoomSummary -> - !roomSummary.info.isDm && !roomSummary.isInvited() + !roomSummary.info.isDm && NonInvitedPredicate(roomSummary) && NonSpacePredicate(roomSummary) } RoomListFilter.Category.People -> { roomSummary: RoomSummary -> - roomSummary.info.isDm && !roomSummary.isInvited() + roomSummary.info.isDm && NonInvitedPredicate(roomSummary) && NonSpacePredicate(roomSummary) } + RoomListFilter.Category.Space -> IsSpacePredicate RoomListFilter.Favorite -> { roomSummary: RoomSummary -> - roomSummary.info.isFavorite && !roomSummary.isInvited() + roomSummary.info.isFavorite && NonInvitedPredicate(roomSummary) && NonSpacePredicate(roomSummary) } RoomListFilter.Unread -> { roomSummary: RoomSummary -> - !roomSummary.isInvited() && (roomSummary.info.numUnreadNotifications > 0 || roomSummary.info.isMarkedUnread) + NonInvitedPredicate(roomSummary) && + NonSpacePredicate(roomSummary) && + (roomSummary.info.numUnreadNotifications > 0 || roomSummary.info.isMarkedUnread) } is RoomListFilter.NormalizedMatchRoomName -> { roomSummary: RoomSummary -> - roomSummary.info.name?.withoutAccents().orEmpty().contains(normalizedPattern, ignoreCase = true) - } - RoomListFilter.Invite -> { roomSummary: RoomSummary -> - roomSummary.isInvited() + roomSummary.info.name?.withoutAccents().orEmpty().contains(normalizedPattern, ignoreCase = true) && + (NonSpacePredicate(roomSummary) || IsInvitedPredicate(roomSummary)) } + RoomListFilter.Invite -> IsInvitedPredicate } fun List.filter(filter: RoomListFilter): List { return when (filter) { is RoomListFilter.All -> { - val predicates = filter.filters.map { it.predicate } + val predicates = if (filter.filters.isNotEmpty()) { + filter.filters.map { it.predicate } + } else { + listOf(filter.predicate) + } filter { roomSummary -> predicates.all { it(roomSummary) } } } is RoomListFilter.Any -> { - val predicates = filter.filters.map { it.predicate } + val predicates = if (filter.filters.isNotEmpty()) { + filter.filters.map { it.predicate } + } else { + listOf(filter.predicate) + } filter { roomSummary -> predicates.any { it(roomSummary) } } } else -> filter(filter.predicate) } } -private fun RoomSummary.isInvited() = info.currentUserMembership == CurrentUserMembership.INVITED +private val IsSpacePredicate = { roomSummary: RoomSummary -> roomSummary.info.isSpace } + +private val NonSpacePredicate = { roomSummary: RoomSummary -> !IsSpacePredicate(roomSummary) } + +private val IsInvitedPredicate = { roomSummary: RoomSummary -> roomSummary.info.currentUserMembership == CurrentUserMembership.INVITED } + +private val NonInvitedPredicate = { roomSummary: RoomSummary -> !IsInvitedPredicate(roomSummary) } diff --git a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilterTest.kt b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilterTest.kt index ff4e5b29e5..932f9ba6be 100644 --- a/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilterTest.kt +++ b/libraries/matrix/impl/src/test/kotlin/io/element/android/libraries/matrix/impl/roomlist/RoomListFilterTest.kt @@ -41,6 +41,14 @@ class RoomListFilterTest { currentUserMembership = CurrentUserMembership.INVITED ) + private val space = aRoomSummary( + isSpace = true + ) + private val invitedSpace = aRoomSummary( + isSpace = true, + currentUserMembership = CurrentUserMembership.INVITED + ) + private val roomSummaries = listOf( regularRoom, dmRoom, @@ -49,13 +57,15 @@ class RoomListFilterTest { unreadNotificationRoom, roomToSearch, roomWithAccent, - invitedRoom + invitedRoom, + space, + invitedSpace, ) @Test fun `Room list filter all empty`() = runTest { val filter = RoomListFilter.all() - assertThat(roomSummaries.filter(filter)).isEqualTo(roomSummaries) + assertThat(roomSummaries.filter(filter)).isEqualTo(roomSummaries - space) } @Test @@ -83,6 +93,12 @@ class RoomListFilterTest { ) } + @Test + fun `Room list filter space`() = runTest { + val filter = RoomListFilter.Category.Space + assertThat(roomSummaries.filter(filter)).containsExactly(space, invitedSpace) + } + @Test fun `Room list filter favorite`() = runTest { val filter = RoomListFilter.Favorite @@ -98,7 +114,7 @@ class RoomListFilterTest { @Test fun `Room list filter invites`() = runTest { val filter = RoomListFilter.Invite - assertThat(roomSummaries.filter(filter)).containsExactly(invitedRoom) + assertThat(roomSummaries.filter(filter)).containsExactly(invitedRoom, invitedSpace) } @Test @@ -136,10 +152,4 @@ class RoomListFilterTest { ) assertThat(roomSummaries.filter(filter)).isEmpty() } - - @Test - fun `Room list filter all with empty list`() = runTest { - val filter = RoomListFilter.all() - assertThat(roomSummaries.filter(filter)).isEqualTo(roomSummaries) - } } From 7cdb44832609019cc29f3ca2cb1a78210be7c144 Mon Sep 17 00:00:00 2001 From: ElementBot Date: Thu, 2 Oct 2025 15:59:35 +0000 Subject: [PATCH 3/3] Update screenshots --- ...features.home.impl.components_RoomSummaryRow_Day_32_en.png | 4 ++-- ...features.home.impl.components_RoomSummaryRow_Day_33_en.png | 4 ++-- ...features.home.impl.components_RoomSummaryRow_Day_34_en.png | 4 ++-- ...features.home.impl.components_RoomSummaryRow_Day_35_en.png | 3 +++ ...atures.home.impl.components_RoomSummaryRow_Night_32_en.png | 4 ++-- ...atures.home.impl.components_RoomSummaryRow_Night_33_en.png | 4 ++-- ...atures.home.impl.components_RoomSummaryRow_Night_34_en.png | 4 ++-- ...atures.home.impl.components_RoomSummaryRow_Night_35_en.png | 3 +++ 8 files changed, 18 insertions(+), 12 deletions(-) create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_35_en.png create mode 100644 tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_35_en.png diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_32_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_32_en.png index 172695b6b2..89cf315b42 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_32_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_32_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ad2d62e2ce270b8548ddf611c3b192e756be0896627ccad28fff84c4ce5e2a1 -size 11938 +oid sha256:98d4e9152dee861cc7afdb3efe57b086c3d9d58d38eeb1345749d31debbf6017 +size 21266 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_33_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_33_en.png index 5430afc3cc..172695b6b2 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_33_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_33_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:541b4210ff0acaf6451a0ce9c6cdc4f120c460086e036fc27e319daa23c7082b -size 17393 +oid sha256:1ad2d62e2ce270b8548ddf611c3b192e756be0896627ccad28fff84c4ce5e2a1 +size 11938 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_34_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_34_en.png index ddd04d3eda..5430afc3cc 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_34_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_34_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:697513adb4fa43d68e8a4477f248e68f64ba305f0ecb6a2e681b8a8b04ceee2b -size 14823 +oid sha256:541b4210ff0acaf6451a0ce9c6cdc4f120c460086e036fc27e319daa23c7082b +size 17393 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_35_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_35_en.png new file mode 100644 index 0000000000..ddd04d3eda --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Day_35_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:697513adb4fa43d68e8a4477f248e68f64ba305f0ecb6a2e681b8a8b04ceee2b +size 14823 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_32_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_32_en.png index b24babae66..c7a3fd69f5 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_32_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_32_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f0c73cab66c885e528bd8723b14cfe28356f0843fd360164c2d6163833a9576b -size 11999 +oid sha256:c24a3b08afe224e9919dd3818c72bd2ff8dd3f38663a6465a10b301ad91e8787 +size 20377 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_33_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_33_en.png index 50455e8053..b24babae66 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_33_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_33_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:71e4c4f995456a5502fb057bbb37cebcb9b92af6edf315cff63f92b3541a30a2 -size 17234 +oid sha256:f0c73cab66c885e528bd8723b14cfe28356f0843fd360164c2d6163833a9576b +size 11999 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_34_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_34_en.png index 0ef7d945d7..50455e8053 100644 --- a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_34_en.png +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_34_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:466ff5436718dd1871635330108c592ff28727c1628368c11387a9b1f5c73642 -size 14204 +oid sha256:71e4c4f995456a5502fb057bbb37cebcb9b92af6edf315cff63f92b3541a30a2 +size 17234 diff --git a/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_35_en.png b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_35_en.png new file mode 100644 index 0000000000..0ef7d945d7 --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/features.home.impl.components_RoomSummaryRow_Night_35_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:466ff5436718dd1871635330108c592ff28727c1628368c11387a9b1f5c73642 +size 14204