From 7ad1277fafbb75fd85f5570823d37450d58b96ae Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2026 09:32:39 +0200 Subject: [PATCH 1/2] Fix room list not scrollable in room select screen when the account switch is hidden The nested scroll connection of the account switch section was always attached. When the section is not displayed (single account, Forward mode, or search active), its height offset limit is never set and stays at -Float.MAX_VALUE, so the connection consumed all the scroll events and the room list could not be scrolled. Only attach the connection when the account switch section is displayed. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../roomselect/impl/RoomSelectView.kt | 9 ++++- .../roomselect/impl/RoomSelectViewTest.kt | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt index 5865d4416a..19798d854c 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt @@ -177,7 +177,14 @@ fun RoomSelectView( Modifier .padding(paddingValues) .consumeWindowInsets(paddingValues) - .nestedScroll(accountSwitchScrollBehavior.nestedScrollConnection) + .then( + // Only when the account switch section is displayed, else its unknown height would consume all the scroll events + if (state.showAccountSwitch && !state.isSearchActive) { + Modifier.nestedScroll(accountSwitchScrollBehavior.nestedScrollConnection) + } else { + Modifier + } + ) ) { SearchBar( modifier = Modifier diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectViewTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectViewTest.kt index 543d20b521..71284e6ec5 100644 --- a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectViewTest.kt +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectViewTest.kt @@ -13,8 +13,12 @@ import androidx.activity.ComponentActivity import androidx.compose.ui.test.AndroidComposeUiTest import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.assertIsNotDisplayed import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.onRoot import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performTouchInput +import androidx.compose.ui.test.swipeUp import androidx.compose.ui.test.v2.runAndroidComposeUiTest import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.core.RoomId @@ -29,6 +33,7 @@ import io.element.android.tests.testutils.EventsRecorder import io.element.android.tests.testutils.clickOn import io.element.android.tests.testutils.robolectric.RobolectricTest import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toImmutableList import org.junit.Test import org.robolectric.annotation.Config @@ -123,6 +128,33 @@ class RoomSelectViewTest : RobolectricTest() { onNodeWithText(activity!!.getString(CommonStrings.common_switch_account)).assertDoesNotExist() } + @Test + fun `the room list can be scrolled when there is no other account`() = runAndroidComposeUiTest { + setRoomSelectView( + aRoomSelectState( + mode = RoomSelectMode.Share, + resultState = SearchBarResultState.Results(aLongRoomList()), + ), + ) + onNodeWithText("Room 0").assertIsDisplayed() + onRoot().performTouchInput { swipeUp() } + onNodeWithText("Room 0").assertIsNotDisplayed() + } + + @Test + fun `the room list can be scrolled when there are other accounts`() = runAndroidComposeUiTest { + setRoomSelectView( + aRoomSelectState( + mode = RoomSelectMode.Share, + resultState = SearchBarResultState.Results(aLongRoomList()), + otherAccounts = persistentListOf(aMatrixUser(id = "@bob:example.org", displayName = "Bob")), + ), + ) + onNodeWithText("Room 0").assertIsDisplayed() + onRoot().performTouchInput { swipeUp() } + onNodeWithText("Room 0").assertIsNotDisplayed() + } + @Test fun `an error is displayed instead of the rooms if they cannot be loaded`() = runAndroidComposeUiTest { setRoomSelectView( @@ -150,3 +182,10 @@ private fun AndroidComposeUiTest.setRoomSelectView( ) } } + +private fun aLongRoomList() = List(30) { index -> + aSelectRoomInfo( + roomId = RoomId("!room$index:domain"), + name = "Room $index", + ) +}.toImmutableList() From 920e37d09706e4cb37a7672a5e646bfd5be2b0dc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 8 Oct 2026 09:35:06 +0200 Subject: [PATCH 2/2] Scroll the rooms header with the search results in room select screen Move the "Rooms" section header inside the LazyColumn of the search results, so that it scrolls with the list instead of staying fixed above it, as it is done for the room list when the search is not active. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../libraries/roomselect/impl/RoomSelectView.kt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt index 19798d854c..1c7d59eed7 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectView.kt @@ -201,16 +201,18 @@ fun RoomSelectView( resultState = state.resultState, showBackButton = false, ) { summaries -> - if (summaries.isNotEmpty()) { - ListSectionHeader( - title = stringResource(CommonStrings.common_header_rooms), - hasDivider = false, - ) - } LazyColumn( state = lazyListState, contentPadding = lazyColumnContentPadding, ) { + if (summaries.isNotEmpty()) { + item { + ListSectionHeader( + title = stringResource(CommonStrings.common_header_rooms), + hasDivider = false, + ) + } + } item { SelectedRoomsHelper( selectedRooms = state.selectedRooms,