From 36ba06c9b933f1ae6c8f936ae87cc3feaf8a32fa Mon Sep 17 00:00:00 2001 From: enki Date: Thu, 30 Jul 2026 08:13:53 -0700 Subject: [PATCH] Selecting a container space recurses into sub-spaces like desktop mautrix-discord nests server/DM spaces inside a top-level Discord space; filtering on the container's direct children matched no rooms, so the rail tap looked dead. The selection filter now walks child spaces recursively (cycle-guarded), matching element-web's SpaceStore behavior. Co-Authored-By: Claude Fable 5 --- .../home/impl/roomlist/RoomListPresenter.kt | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt index 572484bfb3..7254b7b88b 100644 --- a/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt +++ b/features/home/impl/src/main/kotlin/io/element/android/features/home/impl/roomlist/RoomListPresenter.kt @@ -156,7 +156,6 @@ class RoomListPresenter( } } } - val blapSpaceChildIds = blapSpaceChildren[selectedSpaceId].orEmpty() // Blap: union of everything owned by any space (real children + SDK descendants), // persisted so Home is clean right away on cold start. Grows immediately as spaces // report in; replaced exactly once every space has reported (so rooms removed from @@ -333,12 +332,29 @@ class RoomListPresenter( } } - LaunchedEffect(filtersState.filterSelectionStates, spaceFiltersState.selectedFilter(), blapSpaceChildIds) { + LaunchedEffect(filtersState.filterSelectionStates, spaceFiltersState.selectedFilter(), blapSpaceChildren, spaceFilters) { val selectedFilters = filtersState.selectedFilters().map { filter -> filter.into() } // Blap: union the space's real child list into the SDK's descendants — bridge // spaces whose children are DM portals (mautrix-telegram) otherwise come up empty. + // Expansion is RECURSIVE like desktop's SpaceStore: container spaces (mautrix-discord + // nests server/DM spaces inside a top space) contribute their sub-spaces' rooms too, + // otherwise selecting the container matches no rooms at all. val selectedSpaceFilter = spaceFiltersState.selectedFilter()?.let { filter -> - RoomListFilter.Identifiers((filter.descendants.toSet() + blapSpaceChildIds).toList()) + val descendantsBySpace = spaceFilters.associate { it.spaceRoom.roomId to it.descendants } + val ids = mutableSetOf() + val visited = mutableSetOf() + val queue = ArrayDeque(listOf(filter.spaceRoom.roomId)) + while (queue.isNotEmpty()) { + val spaceId = queue.removeFirst() + if (!visited.add(spaceId)) continue + val direct = blapSpaceChildren[spaceId].orEmpty() + descendantsBySpace[spaceId].orEmpty() + for (id in direct) { + ids += id + // Known space → recurse into its children as well. + if (id in blapSpaceChildren || id in descendantsBySpace) queue += id + } + } + RoomListFilter.Identifiers(ids.toList()) } val allFilters = RoomListFilter.All(selectedFilters + listOfNotNull(selectedSpaceFilter)) roomListDataSource.updateFilter(allFilters)