change(room directory) : move the the room directory entry from room list filter to start chat screen.

This commit is contained in:
ganfra 2025-03-03 16:25:15 +01:00
parent 908fc43a91
commit 6af226dc00
24 changed files with 91 additions and 158 deletions

View file

@ -82,10 +82,6 @@ class RoomListNode @AssistedInject constructor(
}
}
private fun onRoomDirectorySearchClick() {
plugins<RoomListEntryPoint.Callback>().forEach { it.onRoomDirectorySearchClick() }
}
@Composable
override fun View(modifier: Modifier) {
val state = presenter.present()
@ -100,7 +96,6 @@ class RoomListNode @AssistedInject constructor(
onConfirmRecoveryKeyClick = this::onSessionConfirmRecoveryKeyClick,
onRoomSettingsClick = this::onRoomSettingsClick,
onMenuActionClick = { onMenuActionClick(activity, it) },
onRoomDirectorySearchClick = this::onRoomDirectorySearchClick,
modifier = modifier,
) {
acceptDeclineInviteView.Render(

View file

@ -49,7 +49,6 @@ fun RoomListView(
onCreateRoomClick: () -> Unit,
onRoomSettingsClick: (roomId: RoomId) -> Unit,
onMenuActionClick: (RoomListMenuAction) -> Unit,
onRoomDirectorySearchClick: () -> Unit,
modifier: Modifier = Modifier,
acceptDeclineInviteView: @Composable () -> Unit,
) {
@ -83,7 +82,6 @@ fun RoomListView(
state = state.searchState,
eventSink = state.eventSink,
onRoomClick = onRoomClick,
onRoomDirectorySearchClick = onRoomDirectorySearchClick,
modifier = Modifier
.statusBarsPadding()
.padding(top = topPadding)
@ -177,7 +175,6 @@ internal fun RoomListViewPreview(@PreviewParameter(RoomListStateProvider::class)
onCreateRoomClick = {},
onRoomSettingsClick = {},
onMenuActionClick = {},
onRoomDirectorySearchClick = {},
acceptDeclineInviteView = {},
)
}

View file

@ -15,14 +15,11 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import kotlinx.collections.immutable.persistentListOf
import javax.inject.Inject
class RoomListSearchPresenter @Inject constructor(
private val dataSource: RoomListSearchDataSource,
private val featureFlagService: FeatureFlagService,
) : Presenter<RoomListSearchState> {
@Composable
override fun present(): RoomListSearchState {
@ -57,14 +54,12 @@ class RoomListSearchPresenter @Inject constructor(
}
}
val isRoomDirectorySearchEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.RoomDirectorySearch).collectAsState(initial = false)
val searchResults by dataSource.roomSummaries.collectAsState(initial = persistentListOf())
return RoomListSearchState(
isSearchActive = isSearchActive,
query = searchQuery,
results = searchResults,
isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled,
eventSink = ::handleEvents
)
}

View file

@ -14,8 +14,5 @@ data class RoomListSearchState(
val isSearchActive: Boolean,
val query: String,
val results: ImmutableList<RoomListRoomSummary>,
val isRoomDirectorySearchEnabled: Boolean,
val eventSink: (RoomListSearchEvents) -> Unit
) {
val displayRoomDirectorySearch = query.isEmpty() && isRoomDirectorySearchEnabled
}
)

View file

@ -17,7 +17,6 @@ class RoomListSearchStateProvider : PreviewParameterProvider<RoomListSearchState
override val values: Sequence<RoomListSearchState>
get() = sequenceOf(
aRoomListSearchState(),
aRoomListSearchState(isRoomDirectorySearchEnabled = true),
aRoomListSearchState(
isSearchActive = true,
query = "Test",
@ -30,12 +29,10 @@ fun aRoomListSearchState(
isSearchActive: Boolean = false,
query: String = "",
results: ImmutableList<RoomListRoomSummary> = persistentListOf(),
isRoomDirectorySearchEnabled: Boolean = false,
eventSink: (RoomListSearchEvents) -> Unit = { },
) = RoomListSearchState(
isSearchActive = isSearchActive,
query = query,
results = results,
isRoomDirectorySearchEnabled = isRoomDirectorySearchEnabled,
eventSink = eventSink,
)

View file

@ -12,12 +12,9 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.ExperimentalMaterial3Api
@ -26,7 +23,6 @@ import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.focus.FocusRequester
@ -38,22 +34,18 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.tokens.generated.CompoundIcons
import io.element.android.features.roomlist.impl.R
import io.element.android.features.roomlist.impl.RoomListEvents
import io.element.android.features.roomlist.impl.components.RoomSummaryRow
import io.element.android.features.roomlist.impl.contentType
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.button.SuperButton
import io.element.android.libraries.designsystem.modifiers.applyIf
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.ButtonSize
import io.element.android.libraries.designsystem.theme.components.FilledTextField
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.IconButton
import io.element.android.libraries.designsystem.theme.components.Scaffold
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.copy
import io.element.android.libraries.matrix.api.core.RoomId
@ -64,7 +56,6 @@ internal fun RoomListSearchView(
state: RoomListSearchState,
eventSink: (RoomListEvents) -> Unit,
onRoomClick: (RoomId) -> Unit,
onRoomDirectorySearchClick: () -> Unit,
modifier: Modifier = Modifier,
) {
BackHandler(enabled = state.isSearchActive) {
@ -91,7 +82,6 @@ internal fun RoomListSearchView(
state = state,
onRoomClick = onRoomClick,
eventSink = eventSink,
onRoomDirectorySearchClick = onRoomDirectorySearchClick,
)
}
}
@ -104,7 +94,6 @@ private fun RoomListSearchContent(
state: RoomListSearchState,
eventSink: (RoomListEvents) -> Unit,
onRoomClick: (RoomId) -> Unit,
onRoomDirectorySearchClick: () -> Unit,
) {
val borderColor = MaterialTheme.colorScheme.tertiary
val strokeWidth = 1.dp
@ -175,14 +164,6 @@ private fun RoomListSearchContent(
.padding(padding)
.consumeWindowInsets(padding)
) {
if (state.displayRoomDirectorySearch) {
RoomDirectorySearchButton(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 24.dp, horizontal = 16.dp),
onClick = onRoomDirectorySearchClick
)
}
LazyColumn(
modifier = Modifier.weight(1f),
) {
@ -201,31 +182,6 @@ private fun RoomListSearchContent(
}
}
@Composable
private fun RoomDirectorySearchButton(
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
SuperButton(
onClick = onClick,
modifier = modifier,
buttonSize = ButtonSize.Large,
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = CompoundIcons.ListBulleted(),
contentDescription = null,
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = stringResource(R.string.screen_roomlist_room_directory_button_title),
)
}
}
}
@PreviewsDayNight
@Composable
internal fun RoomListSearchContentPreview(@PreviewParameter(RoomListSearchStateProvider::class) state: RoomListSearchState) = ElementPreview {
@ -233,6 +189,5 @@ internal fun RoomListSearchContentPreview(@PreviewParameter(RoomListSearchStateP
state = state,
onRoomClick = {},
eventSink = {},
onRoomDirectorySearchClick = {},
)
}

View file

@ -240,7 +240,6 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
onCreateRoomClick: () -> Unit = EnsureNeverCalled(),
onRoomSettingsClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
onMenuActionClick: (RoomListMenuAction) -> Unit = EnsureNeverCalledWithParam(),
onRoomDirectorySearchClick: () -> Unit = EnsureNeverCalled(),
) {
setContent {
RoomListView(
@ -252,7 +251,6 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomL
onCreateRoomClick = onCreateRoomClick,
onRoomSettingsClick = onRoomSettingsClick,
onMenuActionClick = onMenuActionClick,
onRoomDirectorySearchClick = onRoomDirectorySearchClick,
acceptDeclineInviteView = { },
)
}

View file

@ -14,9 +14,6 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.features.roomlist.impl.datasource.aRoomListRoomSummaryFactory
import io.element.android.libraries.dateformatter.test.FakeDateFormatter
import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter
import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.roomlist.RoomListFilter
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.test.room.aRoomSummary
@ -118,26 +115,10 @@ class RoomListSearchPresenterTest {
}
}
}
@Test
fun `present - room directory search`() = runTest {
val featureFlagService = FakeFeatureFlagService()
featureFlagService.setFeatureEnabled(FeatureFlags.RoomDirectorySearch, true)
val presenter = createRoomListSearchPresenter(featureFlagService = featureFlagService)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
skipItems(1)
awaitItem().let { state ->
assertThat(state.isRoomDirectorySearchEnabled).isTrue()
}
}
}
}
fun TestScope.createRoomListSearchPresenter(
roomListService: RoomListService = FakeRoomListService(),
featureFlagService: FeatureFlagService = FakeFeatureFlagService(),
): RoomListSearchPresenter {
return RoomListSearchPresenter(
dataSource = RoomListSearchDataSource(
@ -148,6 +129,5 @@ fun TestScope.createRoomListSearchPresenter(
),
coroutineDispatchers = testCoroutineDispatchers(),
),
featureFlagService = featureFlagService,
)
}

View file

@ -1,62 +0,0 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.features.roomlist.impl.search
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.features.roomlist.impl.R
import io.element.android.features.roomlist.impl.RoomListEvents
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.tests.testutils.EnsureNeverCalled
import io.element.android.tests.testutils.EnsureNeverCalledWithParam
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.ensureCalledOnce
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class RoomListSearchViewTest {
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `clicking on 'Browse all rooms' invokes the expected callback`() {
val eventsRecorder = EventsRecorder<RoomListSearchEvents>(expectEvents = false)
ensureCalledOnce {
rule.setRoomListSearchView(
aRoomListSearchState(
isSearchActive = true,
isRoomDirectorySearchEnabled = true,
eventSink = eventsRecorder,
),
onRoomDirectorySearchClick = it,
)
rule.clickOn(R.string.screen_roomlist_room_directory_button_title)
}
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRoomListSearchView(
state: RoomListSearchState,
eventSink: (RoomListEvents) -> Unit = EventsRecorder(expectEvents = false),
onRoomClick: (RoomId) -> Unit = EnsureNeverCalledWithParam(),
onRoomDirectorySearchClick: () -> Unit = EnsureNeverCalled(),
) {
setContent {
RoomListSearchView(
state = state,
eventSink = eventSink,
onRoomClick = onRoomClick,
onRoomDirectorySearchClick = onRoomDirectorySearchClick,
)
}
}