diff --git a/features/forward/impl/src/main/kotlin/io/element/android/features/forward/impl/ForwardMessagesNode.kt b/features/forward/impl/src/main/kotlin/io/element/android/features/forward/impl/ForwardMessagesNode.kt index eb085d19c5..1c565a390a 100644 --- a/features/forward/impl/src/main/kotlin/io/element/android/features/forward/impl/ForwardMessagesNode.kt +++ b/features/forward/impl/src/main/kotlin/io/element/android/features/forward/impl/ForwardMessagesNode.kt @@ -74,7 +74,10 @@ class ForwardMessagesNode( return roomSelectEntryPoint.createNode( parentNode = this, buildContext = buildContext, - params = RoomSelectEntryPoint.Params(mode = RoomSelectMode.Forward), + params = RoomSelectEntryPoint.Params( + mode = RoomSelectMode.Forward, + maxNumberOfRooms = RoomSelectEntryPoint.DEFAULT_MAX_NUMBER_OF_ROOMS, + ), callback = callback, ) } diff --git a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/ShareNode.kt b/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/ShareNode.kt index 0597b3b678..1abac1afa6 100644 --- a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/ShareNode.kt +++ b/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/ShareNode.kt @@ -70,7 +70,10 @@ class ShareNode( return roomSelectEntryPoint.createNode( parentNode = this, buildContext = buildContext, - params = RoomSelectEntryPoint.Params(mode = RoomSelectMode.Share), + params = RoomSelectEntryPoint.Params( + mode = RoomSelectMode.Share, + maxNumberOfRooms = RoomSelectEntryPoint.DEFAULT_MAX_NUMBER_OF_ROOMS, + ), callback = callback, ) } diff --git a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt index e000c2f916..39cde68c31 100644 --- a/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt +++ b/libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/room/RoomContentForwarder.kt @@ -49,7 +49,7 @@ class RoomContentForwarder( val content = (messageLikeContent.kind as? MsgLikeKind.Message)?.content ?: throw ForwardEventException(toRoomIds) - val targetRooms = toRoomIds.mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) } + val targetRooms = toRoomIds.toSet().mapNotNull { roomId -> roomListService.roomOrNull(roomId.value) } val failedForwardingTo = mutableSetOf() targetRooms.parallelMap { room -> room.use { targetRoom -> diff --git a/libraries/roomselect/api/src/main/kotlin/io/element/android/libraries/roomselect/api/RoomSelectEntryPoint.kt b/libraries/roomselect/api/src/main/kotlin/io/element/android/libraries/roomselect/api/RoomSelectEntryPoint.kt index ba5ca79d40..3c5c5d5ac3 100644 --- a/libraries/roomselect/api/src/main/kotlin/io/element/android/libraries/roomselect/api/RoomSelectEntryPoint.kt +++ b/libraries/roomselect/api/src/main/kotlin/io/element/android/libraries/roomselect/api/RoomSelectEntryPoint.kt @@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.core.RoomId interface RoomSelectEntryPoint : FeatureEntryPoint { data class Params( val mode: RoomSelectMode, + val maxNumberOfRooms: Int, ) fun createNode( @@ -30,4 +31,8 @@ interface RoomSelectEntryPoint : FeatureEntryPoint { fun onRoomSelected(roomIds: List) fun onCancel() } + + companion object { + const val DEFAULT_MAX_NUMBER_OF_ROOMS = 10 + } } diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPoint.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPoint.kt index 4ca92663a9..ff3ba06f0d 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPoint.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPoint.kt @@ -26,7 +26,10 @@ class DefaultRoomSelectEntryPoint : RoomSelectEntryPoint { return parentNode.createNode( buildContext = buildContext, plugins = listOf( - RoomSelectNode.Inputs(mode = params.mode), + RoomSelectNode.Inputs( + mode = params.mode, + maxNumberOfRooms = params.maxNumberOfRooms, + ), callback, ) ) diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvents.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvent.kt similarity index 60% rename from libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvents.kt rename to libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvent.kt index a3512c419c..13c5bc5f8d 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvents.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectEvent.kt @@ -10,11 +10,8 @@ package io.element.android.libraries.roomselect.impl import io.element.android.libraries.matrix.ui.model.SelectRoomInfo -sealed interface RoomSelectEvents { - data class SetSelectedRoom(val room: SelectRoomInfo) : RoomSelectEvents - - // TODO remove to restore multi-selection - data object RemoveSelectedRoom : RoomSelectEvents - data object ToggleSearchActive : RoomSelectEvents - data class UpdateVisibleRange(val range: IntRange) : RoomSelectEvents +sealed interface RoomSelectEvent { + data class ToggleSelectedRoom(val room: SelectRoomInfo) : RoomSelectEvent + data object ToggleSearchActive : RoomSelectEvent + data class UpdateVisibleRange(val range: IntRange) : RoomSelectEvent } diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectNode.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectNode.kt index 943da643c6..0297f13066 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectNode.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectNode.kt @@ -35,10 +35,14 @@ class RoomSelectNode( ) : Node(buildContext, plugins = plugins) { data class Inputs( val mode: RoomSelectMode, + val maxNumberOfRooms: Int, ) : NodeInputs private val inputs: Inputs = inputs() - private val presenter = presenterFactory.create(inputs.mode) + private val presenter = presenterFactory.create( + mode = inputs.mode, + maxNumberOfRooms = inputs.maxNumberOfRooms, + ) private val stateFlow = launchMolecule { presenter.present() } private val callback: RoomSelectEntryPoint.Callback = callback() diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt index b7547b8a45..e73299126e 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt @@ -34,11 +34,15 @@ import kotlinx.coroutines.launch @AssistedInject class RoomSelectPresenter( @Assisted private val mode: RoomSelectMode, + @Assisted private val maxNumberOfRooms: Int, private val dataSourceFactory: RoomSelectSearchDataSource.Factory, ) : Presenter { @AssistedFactory fun interface Factory { - fun create(mode: RoomSelectMode): RoomSelectPresenter + fun create( + mode: RoomSelectMode, + maxNumberOfRooms: Int, + ): RoomSelectPresenter } @Composable @@ -67,21 +71,18 @@ class RoomSelectPresenter( } } - fun handleEvent(event: RoomSelectEvents) { + fun handleEvent(event: RoomSelectEvent) { when (event) { - is RoomSelectEvents.SetSelectedRoom -> { - selectedRooms = persistentListOf(event.room) - // Restore for multi-selection -// val index = selectedRooms.indexOfFirst { it.roomId == event.room.roomId } -// selectedRooms = if (index >= 0) { -// selectedRooms.removeAt(index) -// } else { -// selectedRooms.add(event.room) -// } + is RoomSelectEvent.ToggleSelectedRoom -> { + val index = selectedRooms.indexOfFirst { it.roomId == event.room.roomId } + selectedRooms = if (index >= 0) { + selectedRooms.removeAt(index) + } else { + selectedRooms.add(event.room) + } } - RoomSelectEvents.RemoveSelectedRoom -> selectedRooms = persistentListOf() - RoomSelectEvents.ToggleSearchActive -> isSearchActive = !isSearchActive - is RoomSelectEvents.UpdateVisibleRange -> coroutineScope.launch { + RoomSelectEvent.ToggleSearchActive -> isSearchActive = !isSearchActive + is RoomSelectEvent.UpdateVisibleRange -> coroutineScope.launch { dataSource.updateVisibleRange(event.range) } } @@ -89,6 +90,7 @@ class RoomSelectPresenter( return RoomSelectState( mode = mode, + maxNumberOfRooms = maxNumberOfRooms, resultState = searchResults, searchQuery = queryState, isSearchActive = isSearchActive, diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectState.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectState.kt index 927a1c02d6..aadb7c10d1 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectState.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectState.kt @@ -16,9 +16,12 @@ import kotlinx.collections.immutable.ImmutableList data class RoomSelectState( val mode: RoomSelectMode, + val maxNumberOfRooms: Int, val resultState: SearchBarResultState>, val searchQuery: TextFieldState, val isSearchActive: Boolean, val selectedRooms: ImmutableList, - val eventSink: (RoomSelectEvents) -> Unit -) + val eventSink: (RoomSelectEvent) -> Unit, +) { + val canSelectMoreRooms = selectedRooms.size < maxNumberOfRooms +} diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt index b0d18659b6..131e35429e 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectStateProvider.kt @@ -40,18 +40,26 @@ open class RoomSelectStateProvider : PreviewParameterProvider { mode = RoomSelectMode.Share, resultState = SearchBarResultState.Results(aRoomSelectRoomList()), ), + aRoomSelectState( + mode = RoomSelectMode.Share, + resultState = SearchBarResultState.Results(aRoomSelectRoomList()), + selectedRooms = aRoomSelectRoomList().subList(0, 1), + maxNumberOfRooms = 1, + ), ) } internal fun aRoomSelectState( mode: RoomSelectMode = RoomSelectMode.Forward, + maxNumberOfRooms: Int = 10, resultState: SearchBarResultState> = SearchBarResultState.Initial(), searchQuery: String = "", isSearchActive: Boolean = false, selectedRooms: ImmutableList = persistentListOf(), - eventSink: (RoomSelectEvents) -> Unit = {}, + eventSink: (RoomSelectEvent) -> Unit = {}, ) = RoomSelectState( mode = mode, + maxNumberOfRooms = maxNumberOfRooms, resultState = resultState, searchQuery = TextFieldState(initialText = searchQuery), isSearchActive = isSearchActive, 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 69f091ddc4..508fcd4fc2 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 @@ -44,8 +44,8 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarType import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.components.Checkbox import io.element.android.libraries.designsystem.theme.components.HorizontalDivider -import io.element.android.libraries.designsystem.theme.components.RadioButton import io.element.android.libraries.designsystem.theme.components.Scaffold import io.element.android.libraries.designsystem.theme.components.SearchBar import io.element.android.libraries.designsystem.theme.components.SearchBarResultState @@ -71,26 +71,30 @@ fun RoomSelectView( onSubmit: (List) -> Unit, modifier: Modifier = Modifier, ) { - @Suppress("UNUSED_PARAMETER") fun onRoomRemoved(roomInfo: SelectRoomInfo) { - // TODO toggle selection when multi-selection is enabled - state.eventSink(RoomSelectEvents.RemoveSelectedRoom) + state.eventSink(RoomSelectEvent.ToggleSelectedRoom(roomInfo)) } @Composable - fun SelectedRoomsHelper(isForwarding: Boolean, selectedRooms: ImmutableList) { - if (isForwarding) return - SelectedRooms( - selectedRooms = selectedRooms, - onRemoveRoom = ::onRoomRemoved, - modifier = Modifier.padding(vertical = 16.dp) - ) + fun SelectedRoomsHelper( + selectedRooms: ImmutableList, + showVerticalSpace: Boolean, + ) { + if (selectedRooms.isNotEmpty()) { + SelectedRooms( + selectedRooms = selectedRooms, + onRemoveRoom = ::onRoomRemoved, + modifier = Modifier.padding(vertical = 16.dp) + ) + } else if (showVerticalSpace) { + Spacer(modifier = Modifier.height(20.dp)) + } } var canHandleBack by remember { mutableStateOf(true) } fun onBackButton(state: RoomSelectState) { if (state.isSearchActive) { - state.eventSink(RoomSelectEvents.ToggleSearchActive) + state.eventSink(RoomSelectEvent.ToggleSearchActive) } else if (canHandleBack) { canHandleBack = false onDismiss() @@ -104,7 +108,7 @@ fun RoomSelectView( val lazyListState = rememberLazyListState() OnVisibleRangeChangeEffect(lazyListState) { visibleRange -> - state.eventSink(RoomSelectEvents.UpdateVisibleRange(visibleRange)) + state.eventSink(RoomSelectEvent.UpdateVisibleRange(visibleRange)) } Scaffold( @@ -141,16 +145,15 @@ fun RoomSelectView( placeHolderTitle = stringResource(CommonStrings.action_search), queryState = state.searchQuery, active = state.isSearchActive, - onActiveChange = { state.eventSink(RoomSelectEvents.ToggleSearchActive) }, + onActiveChange = { state.eventSink(RoomSelectEvent.ToggleSearchActive) }, resultState = state.resultState, showBackButton = false, ) { summaries -> LazyColumn(state = lazyListState) { item { SelectedRoomsHelper( - // TODO state.isForwarding - isForwarding = false, - selectedRooms = state.selectedRooms + selectedRooms = state.selectedRooms, + showVerticalSpace = false, ) } items(summaries, key = { it.roomId.value }) { roomSummary -> @@ -159,8 +162,9 @@ fun RoomSelectView( roomSummary, isSelected = state.selectedRooms.any { it.roomId == roomSummary.roomId }, onSelection = { roomSummary -> - state.eventSink(RoomSelectEvents.SetSelectedRoom(roomSummary)) - } + state.eventSink(RoomSelectEvent.ToggleSelectedRoom(roomSummary)) + }, + canBeSelected = state.canSelectMoreRooms, ) HorizontalDivider(modifier = Modifier.fillMaxWidth()) } @@ -169,13 +173,10 @@ fun RoomSelectView( } if (!state.isSearchActive) { - // TODO restore for multi-selection -// SelectedRoomsHelper( -// isForwarding = state.isForwarding, -// selectedRooms = state.selectedRooms -// ) - Spacer(modifier = Modifier.height(20.dp)) - + SelectedRoomsHelper( + selectedRooms = state.selectedRooms, + showVerticalSpace = true, + ) if (state.resultState is SearchBarResultState.Results) { LazyColumn(state = lazyListState) { items(state.resultState.results, key = { it.roomId.value }) { roomSummary -> @@ -184,8 +185,9 @@ fun RoomSelectView( roomSummary, isSelected = state.selectedRooms.any { it.roomId == roomSummary.roomId }, onSelection = { roomSummary -> - state.eventSink(RoomSelectEvents.SetSelectedRoom(roomSummary)) - } + state.eventSink(RoomSelectEvent.ToggleSelectedRoom(roomSummary)) + }, + canBeSelected = state.canSelectMoreRooms, ) HorizontalDivider(modifier = Modifier.fillMaxWidth()) } @@ -218,6 +220,7 @@ private fun SelectedRooms( private fun RoomSummaryView( roomInfo: SelectRoomInfo, isSelected: Boolean, + canBeSelected: Boolean, onSelection: (SelectRoomInfo) -> Unit, ) { Row( @@ -262,7 +265,11 @@ private fun RoomSummaryView( ) } } - RadioButton(selected = isSelected, onClick = { onSelection(roomInfo) }) + Checkbox( + checked = isSelected, + enabled = isSelected || canBeSelected, + onCheckedChange = { onSelection(roomInfo) }, + ) } } diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt index a99a0396c2..ab9f0b2663 100644 --- a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt @@ -33,13 +33,15 @@ class DefaultRoomSelectEntryPointTest { fun `test node builder`() = runTest { val entryPoint = DefaultRoomSelectEntryPoint() val testMode = RoomSelectMode.Share + val testMaxNumberOfRooms = 12 val parentNode = TestParentNode.create { buildContext, plugins -> RoomSelectNode( buildContext = buildContext, plugins = plugins, - presenterFactory = { mode -> + presenterFactory = { mode, maxNumberOfRooms -> assertThat(mode).isEqualTo(testMode) - createRoomSelectPresenter(mode) + assertThat(maxNumberOfRooms).isEqualTo(testMaxNumberOfRooms) + createRoomSelectPresenter(mode, maxNumberOfRooms) }, ) } @@ -47,7 +49,10 @@ class DefaultRoomSelectEntryPointTest { override fun onRoomSelected(roomIds: List) = lambdaError() override fun onCancel() = lambdaError() } - val params = RoomSelectEntryPoint.Params(testMode) + val params = RoomSelectEntryPoint.Params( + mode = testMode, + maxNumberOfRooms = testMaxNumberOfRooms, + ) val result = entryPoint.createNode( parentNode = parentNode, buildContext = BuildContext.root(null), @@ -55,7 +60,7 @@ class DefaultRoomSelectEntryPointTest { callback = callback, ) assertThat(result).isInstanceOf(RoomSelectNode::class.java) - assertThat(result.plugins).contains(RoomSelectNode.Inputs(params.mode)) + assertThat(result.plugins).contains(RoomSelectNode.Inputs(params.mode, params.maxNumberOfRooms)) assertThat(result.plugins).contains(callback) } } diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt index 67c1b52231..b5a4ccfd12 100644 --- a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt @@ -9,9 +9,6 @@ package io.element.android.libraries.roomselect.impl import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd -import app.cash.molecule.RecompositionMode -import app.cash.molecule.moleculeFlow -import app.cash.turbine.test import com.google.common.truth.Truth.assertThat import io.element.android.libraries.designsystem.theme.components.SearchBarResultState import io.element.android.libraries.matrix.api.roomlist.RoomListFilter @@ -20,10 +17,12 @@ import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.roomlist.FakeDynamicRoomList import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService import io.element.android.libraries.matrix.ui.model.toSelectRoomInfo +import io.element.android.libraries.roomselect.api.RoomSelectEntryPoint import io.element.android.libraries.roomselect.api.RoomSelectMode import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.lambdaRecorder +import io.element.android.tests.testutils.test import io.element.android.tests.testutils.testCoroutineDispatchers import kotlinx.collections.immutable.persistentListOf import kotlinx.coroutines.CoroutineScope @@ -40,26 +39,24 @@ class RoomSelectPresenterTest { @Test fun `present - initial state`() = runTest { val presenter = createRoomSelectPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() assertThat(initialState.selectedRooms).isEmpty() assertThat(initialState.resultState).isInstanceOf(SearchBarResultState.Initial::class.java) assertThat(initialState.isSearchActive).isFalse() + assertThat(initialState.maxNumberOfRooms).isEqualTo(10) + assertThat(initialState.canSelectMoreRooms).isTrue() } } @Test fun `present - toggle search active`() = runTest { val presenter = createRoomSelectPresenter() - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() - initialState.eventSink(RoomSelectEvents.ToggleSearchActive) + initialState.eventSink(RoomSelectEvent.ToggleSearchActive) assertThat(awaitItem().isSearchActive).isTrue() - initialState.eventSink(RoomSelectEvents.ToggleSearchActive) + initialState.eventSink(RoomSelectEvent.ToggleSearchActive) assertThat(awaitItem().isSearchActive).isFalse() } } @@ -76,15 +73,13 @@ class RoomSelectPresenterTest { val presenter = createRoomSelectPresenter( roomListService = roomListService ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val expectedRoomInfo = roomSummary.toSelectRoomInfo() // Do not compare the lambda because they will be different. So copy the lambda from expectedRoomSummary to result val result = (awaitItem().resultState as SearchBarResultState.Results).results assertThat(result).isEqualTo(listOf(expectedRoomInfo)) - initialState.eventSink(RoomSelectEvents.ToggleSearchActive) + initialState.eventSink(RoomSelectEvent.ToggleSearchActive) skipItems(1) initialState.searchQuery.setTextAndPlaceCursorAtEnd("string not contained") assertThat( @@ -110,17 +105,22 @@ class RoomSelectPresenterTest { createRoomListLambda = { roomList } ) val presenter = createRoomSelectPresenter( + maxNumberOfRooms = 1, roomListService = roomListService, ) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() val roomInfo = roomSummary.toSelectRoomInfo() - initialState.eventSink(RoomSelectEvents.SetSelectedRoom(roomInfo)) - assertThat(awaitItem().selectedRooms).isEqualTo(persistentListOf(roomInfo)) - initialState.eventSink(RoomSelectEvents.RemoveSelectedRoom) - assertThat(awaitItem().selectedRooms).isEmpty() + initialState.eventSink(RoomSelectEvent.ToggleSelectedRoom(roomInfo)) + awaitItem().let { + assertThat(it.selectedRooms).isEqualTo(persistentListOf(roomInfo)) + assertThat(it.canSelectMoreRooms).isFalse() + it.eventSink(RoomSelectEvent.ToggleSelectedRoom(roomInfo)) + } + awaitItem().let { + assertThat(it.selectedRooms).isEmpty() + assertThat(it.canSelectMoreRooms).isTrue() + } cancel() } } @@ -136,9 +136,7 @@ class RoomSelectPresenterTest { createRoomListLambda = { roomList } ) val presenter = createRoomSelectPresenter(roomListService = roomListService) - moleculeFlow(RecompositionMode.Immediate) { - presenter.present() - }.test { + presenter.test { val initialState = awaitItem() // Post some rooms to simulate loaded content val rooms = (1..10).map { aRoomSummary() } @@ -146,7 +144,7 @@ class RoomSelectPresenterTest { skipItems(1) // UpdateVisibleRange near end should trigger loadMore - initialState.eventSink(RoomSelectEvents.UpdateVisibleRange(IntRange(0, 9))) + initialState.eventSink(RoomSelectEvent.UpdateVisibleRange(IntRange(0, 9))) // Give time for the coroutine to complete testScheduler.advanceUntilIdle() @@ -157,9 +155,11 @@ class RoomSelectPresenterTest { internal fun TestScope.createRoomSelectPresenter( mode: RoomSelectMode = RoomSelectMode.Forward, + maxNumberOfRooms: Int = RoomSelectEntryPoint.DEFAULT_MAX_NUMBER_OF_ROOMS, roomListService: RoomListService = FakeRoomListService(), ) = RoomSelectPresenter( mode = mode, + maxNumberOfRooms = maxNumberOfRooms, dataSourceFactory = object : RoomSelectSearchDataSource.Factory { override fun create(coroutineScope: CoroutineScope): RoomSelectSearchDataSource { return RoomSelectSearchDataSource( diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_2_en.png index 051db89ece..3ae01ed93b 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d06e84c695086a799c8377bcf48869675b98dcadd1b5320e685d775589ac40c7 -size 30950 +oid sha256:2a93b747f763fc0613c3fa5fdb492be034426916a4b3761a61f4c1d5fc655440 +size 28772 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_3_en.png index ddde486abc..683ee8e120 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3825e3c312d75a865545745ee00b64d8c2259e515dc45fad64236963e91f2427 -size 28999 +oid sha256:feaf2f316024a21d49c7b71b1e3df892e60924a715fc892871ee1f06006145ab +size 26657 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_4_en.png index 821a37d7c0..817e4d44d2 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7b0f7e2b97a343d0e1bedd9595a1057a03a4429c3fa72613451ac86a7146392a -size 33382 +oid sha256:19f984bbf1f12dc3774b24c4fbadaae40c024cc876c8bf172af29a22429b43e0 +size 31248 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_5_en.png index c19c6f4fbb..4dc0de9f33 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cccff3215bc81e2a6491f3b0da3f4d8997179b54c698f962eb245f535e6cc9fc -size 28655 +oid sha256:c3ff0ef8dc9adc1378bef8a87479aed5a4cc1d43050851f516e9de17ef7201ee +size 26450 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_6_en.png new file mode 100644 index 0000000000..c9f8f4a0ea --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Day_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1dd54a38725d9fdc035a73aebfbe9447377970e1b9e33dd512f0d41e2a11ec1 +size 30975 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_2_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_2_en.png index 97ff3939e2..67d226b286 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_2_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_2_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b38450dc7cc24e6f9a0db829aa11058d10ae45d433945afd534627534f362554 -size 30261 +oid sha256:c3545c6c2b173b70bfba5dd571ea23db31ca7c2e64554131ba5cdbbb0555ea35 +size 28229 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_3_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_3_en.png index 1c3dfb9480..8b6772b858 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_3_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_3_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1b36608e269c7572c93c6f10cddeaf42bfeba404c6699a6e050144bc28bc55e -size 28569 +oid sha256:947bb1138d11180f6174db8b9fadf51cec8d8d2947f0f47db148b479fa1f4d86 +size 26340 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_4_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_4_en.png index c4689af159..5d252a9af5 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_4_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_4_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96f198461d8d60d8610f337c3dbe90bebd8c98f32a4739310532d629ca336a1f -size 33113 +oid sha256:e035e0c89cf000340d17257a9ad0e3e2ea1937f7408664742d9c4ba0c5b8c2c3 +size 31149 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_5_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_5_en.png index 5301142de1..4c905ad8d9 100644 --- a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_5_en.png +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_5_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:12350783e27c09074bdaba2e74ac445b643ff6a13251c13a7cdf98999274325d -size 27915 +oid sha256:f0159ba2e298d8c3c7663ed0fdb4dca4ae179e00d40e5fdec8223ca597adbe6a +size 25871 diff --git a/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_6_en.png b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_6_en.png new file mode 100644 index 0000000000..42d6e7a45f --- /dev/null +++ b/tests/uitests/src/test/snapshots/images/libraries.roomselect.impl_RoomSelectView_Night_6_en.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:42ff2caf57dc21ea2681423082d91592091ad062ba350e91a7bbd10500768d58 +size 30515