Merge pull request #7266 from element-hq/feature/fga/searchbar-result-state-refactor

Refactor SearchBarResultState.Initial/NoResultsFound to data objects
This commit is contained in:
ganfra
2026-07-24 09:58:15 +02:00
committed by GitHub
15 changed files with 38 additions and 54 deletions
@@ -88,7 +88,7 @@ class DefaultInvitePeoplePresenter(
override fun present(): InvitePeopleState { override fun present(): InvitePeopleState {
val roomMembers = remember { mutableStateOf<AsyncData<ImmutableList<RoomMember>>>(AsyncData.Loading()) } val roomMembers = remember { mutableStateOf<AsyncData<ImmutableList<RoomMember>>>(AsyncData.Loading()) }
val selectedUsers = remember { mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf()) } val selectedUsers = remember { mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf()) }
val searchResults = remember { mutableStateOf<SearchBarResultState<ImmutableList<InvitableUser>>>(SearchBarResultState.Initial()) } val searchResults = remember { mutableStateOf<SearchBarResultState<ImmutableList<InvitableUser>>>(SearchBarResultState.Initial) }
val queryState = rememberTextFieldState() val queryState = rememberTextFieldState()
var searchActive by rememberSaveable { mutableStateOf(false) } var searchActive by rememberSaveable { mutableStateOf(false) }
val showSearchLoader = rememberSaveable { mutableStateOf(false) } val showSearchLoader = rememberSaveable { mutableStateOf(false) }
@@ -332,15 +332,15 @@ class DefaultInvitePeoplePresenter(
showSearchLoader: MutableState<Boolean>, showSearchLoader: MutableState<Boolean>,
searchQuery: String, searchQuery: String,
) = withContext(coroutineDispatchers.io) { ) = withContext(coroutineDispatchers.io) {
searchResults.value = SearchBarResultState.Initial() searchResults.value = SearchBarResultState.Initial
showSearchLoader.value = false showSearchLoader.value = false
val joinedMembers = roomMembers.value.dataOrNull().orEmpty() val joinedMembers = roomMembers.value.dataOrNull().orEmpty()
userRepository.search(searchQuery).onEach { state -> userRepository.search(searchQuery).onEach { state ->
showSearchLoader.value = state.isSearching showSearchLoader.value = state.isSearching
searchResults.value = when { searchResults.value = when {
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial() state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound() state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound
else -> SearchBarResultState.Results(state.results.map { result -> else -> SearchBarResultState.Results(state.results.map { result ->
val existingMembership = joinedMembers.firstOrNull { j -> j.userId == result.matrixUser.userId }?.membership val existingMembership = joinedMembers.firstOrNull { j -> j.userId == result.matrixUser.userId }?.membership
val isJoined = existingMembership == RoomMembershipState.JOIN val isJoined = existingMembership == RoomMembershipState.JOIN
@@ -33,7 +33,7 @@ internal class DefaultInvitePeopleStateProvider : PreviewParameterProvider<Defau
aDefaultInvitePeopleState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()), aDefaultInvitePeopleState(canInvite = true, selectedUsers = aMatrixUserList().toImmutableList()),
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query"), aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query"),
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()), aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", selectedUsers = aMatrixUserList().toImmutableList()),
aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResultsFound()), aDefaultInvitePeopleState(isSearchActive = true, searchQuery = "some query", searchResults = SearchBarResultState.NoResultsFound),
aDefaultInvitePeopleState( aDefaultInvitePeopleState(
isSearchActive = true, isSearchActive = true,
canInvite = true, canInvite = true,
@@ -115,7 +115,7 @@ private fun aDefaultInvitePeopleState(
room: AsyncData<Unit> = AsyncData.Success(Unit), room: AsyncData<Unit> = AsyncData.Success(Unit),
canInvite: Boolean = false, canInvite: Boolean = false,
searchQuery: String = "", searchQuery: String = "",
searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.Initial(), searchResults: SearchBarResultState<ImmutableList<InvitableUser>> = SearchBarResultState.Initial,
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(), selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
isSearchActive: Boolean = false, isSearchActive: Boolean = false,
showSearchLoader: Boolean = false, showSearchLoader: Boolean = false,
@@ -95,7 +95,7 @@ internal class DefaultInvitePeoplePresenterTest {
resultState.searchQuery.setTextAndPlaceCursorAtEnd("some query") resultState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
assertThat(awaitItemAsDefault().searchQuery.text.toString()).isEqualTo("some query") assertThat(awaitItemAsDefault().searchQuery.text.toString()).isEqualTo("some query")
resultState.eventSink(InvitePeopleEvents.CloseSearch) resultState.eventSink(InvitePeopleEvents.CloseSearch)
skipItems(2) skipItems(1)
awaitItemAsDefault().also { awaitItemAsDefault().also {
assertThat(it.isSearchActive).isFalse() assertThat(it.isSearchActive).isFalse()
assertThat(it.searchQuery.text.toString()).isEmpty() assertThat(it.searchQuery.text.toString()).isEmpty()
@@ -116,7 +116,7 @@ internal class DefaultInvitePeoplePresenterTest {
initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query") initialState.searchQuery.setTextAndPlaceCursorAtEnd("some query")
assertThat(repository.providedQuery).isEqualTo("some query") assertThat(repository.providedQuery).isEqualTo("some query")
repository.emitState(UserSearchResultState(results = emptyList(), isSearching = true)) repository.emitState(UserSearchResultState(results = emptyList(), isSearching = true))
skipItems(3) skipItems(2)
awaitItemAsDefault().also { state -> awaitItemAsDefault().also { state ->
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
assertThat(state.showSearchLoader).isTrue() assertThat(state.showSearchLoader).isTrue()
@@ -145,7 +145,6 @@ internal class DefaultInvitePeoplePresenterTest {
assertThat(repository.providedQuery).isEqualTo("some query") assertThat(repository.providedQuery).isEqualTo("some query")
repository.emitStateWithUsers(users = aMatrixUserList()) repository.emitStateWithUsers(users = aMatrixUserList())
skipItems(1)
val resultState = awaitItemAsDefault() val resultState = awaitItemAsDefault()
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
@@ -198,7 +197,6 @@ internal class DefaultInvitePeoplePresenterTest {
assertThat(repository.providedQuery).isEqualTo("some query") assertThat(repository.providedQuery).isEqualTo("some query")
repository.emitStateWithUsers(users = aMatrixUserList()) repository.emitStateWithUsers(users = aMatrixUserList())
skipItems(1)
val resultState = awaitItemAsDefault() val resultState = awaitItemAsDefault()
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
@@ -265,7 +263,6 @@ internal class DefaultInvitePeoplePresenterTest {
it it
) )
}) })
skipItems(1)
val resultState = awaitItemAsDefault() val resultState = awaitItemAsDefault()
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
@@ -329,7 +326,7 @@ internal class DefaultInvitePeoplePresenterTest {
assertThat(repository.providedQuery).isEqualTo("some query") assertThat(repository.providedQuery).isEqualTo("some query")
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser) repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
skipItems(2) skipItems(1)
val resultState = awaitItemAsDefault() val resultState = awaitItemAsDefault()
assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) assertThat(resultState.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
@@ -366,7 +363,6 @@ internal class DefaultInvitePeoplePresenterTest {
assertThat(repository.providedQuery).isEqualTo("some query") assertThat(repository.providedQuery).isEqualTo("some query")
repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser) repository.emitStateWithUsers(users = aMatrixUserList() + selectedUser)
skipItems(1)
awaitItemAsDefault().also { state -> awaitItemAsDefault().also { state ->
// selectedUser is not selected // selectedUser is not selected
assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Results::class.java) assertThat(state.searchResults).isInstanceOf(SearchBarResultState.Results::class.java)
@@ -732,7 +728,7 @@ internal class DefaultInvitePeoplePresenterTest {
isSearching = true isSearching = true
) )
) )
skipItems(3) skipItems(2)
awaitItemAsDefault().run { awaitItemAsDefault().run {
assertThat(selectedUsers).containsExactly(alice, bob, charlie) assertThat(selectedUsers).containsExactly(alice, bob, charlie)
@@ -77,7 +77,7 @@ class ChangeRolesPresenter(
val queryState = rememberTextFieldState() val queryState = rememberTextFieldState()
var searchActive by rememberSaveable { mutableStateOf(false) } var searchActive by rememberSaveable { mutableStateOf(false) }
var searchResults by remember { var searchResults by remember {
mutableStateOf<SearchBarResultState<MembersByRole>>(SearchBarResultState.Initial()) mutableStateOf<SearchBarResultState<MembersByRole>>(SearchBarResultState.Initial)
} }
val selectedUsers = remember { val selectedUsers = remember {
mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf()) mutableStateOf<ImmutableList<MatrixUser>>(persistentListOf())
@@ -118,7 +118,7 @@ class ChangeRolesPresenter(
.groupedByRole() .groupedByRole()
searchResults = if (results.isEmpty()) { searchResults = if (results.isEmpty()) {
SearchBarResultState.NoResultsFound() SearchBarResultState.NoResultsFound
} else { } else {
SearchBarResultState.Results(results) SearchBarResultState.Results(results)
} }
@@ -68,7 +68,7 @@ internal fun aChangeRolesState(
role: RoomMember.Role = RoomMember.Role.Admin, role: RoomMember.Role = RoomMember.Role.Admin,
searchQuery: String = "", searchQuery: String = "",
isSearchActive: Boolean = false, isSearchActive: Boolean = false,
searchResults: SearchBarResultState<MembersByRole> = SearchBarResultState.NoResultsFound(), searchResults: SearchBarResultState<MembersByRole> = SearchBarResultState.NoResultsFound,
selectedUsers: ImmutableList<MatrixUser> = persistentListOf(), selectedUsers: ImmutableList<MatrixUser> = persistentListOf(),
hasPendingChanges: Boolean = false, hasPendingChanges: Boolean = false,
savingState: AsyncAction<Boolean> = AsyncAction.Uninitialized, savingState: AsyncAction<Boolean> = AsyncAction.Uninitialized,
@@ -66,8 +66,8 @@ class AddRoomToSpacePresenter(
derivedStateOf { derivedStateOf {
when { when {
filteredRooms.isNotEmpty() -> SearchBarResultState.Results(filteredRooms) filteredRooms.isNotEmpty() -> SearchBarResultState.Results(filteredRooms)
isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound<ImmutableList<SelectRoomInfo>>() isSearchActive && searchQuery.text.isNotEmpty() -> SearchBarResultState.NoResultsFound
else -> SearchBarResultState.Initial<ImmutableList<SelectRoomInfo>>() else -> SearchBarResultState.Initial
} }
} }
} }
@@ -40,7 +40,7 @@ internal class AddRoomToSpaceStateProvider : PreviewParameterProvider<AddRoomToS
anAddRoomToSpaceState( anAddRoomToSpaceState(
isSearchActive = true, isSearchActive = true,
searchQuery = "unknown", searchQuery = "unknown",
searchResults = SearchBarResultState.NoResultsFound(), searchResults = SearchBarResultState.NoResultsFound,
), ),
// With selected rooms // With selected rooms
anAddRoomToSpaceState( anAddRoomToSpaceState(
@@ -62,7 +62,7 @@ internal class AddRoomToSpaceStateProvider : PreviewParameterProvider<AddRoomToS
internal fun anAddRoomToSpaceState( internal fun anAddRoomToSpaceState(
searchQuery: String = "", searchQuery: String = "",
searchResults: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial(), searchResults: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial,
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(), selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),
isSearchActive: Boolean = false, isSearchActive: Boolean = false,
saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized, saveAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
@@ -67,19 +67,19 @@ class DefaultUserListPresenter(
val selectedUsers by userListDataStore.selectedUsers.collectAsState(emptyList()) val selectedUsers by userListDataStore.selectedUsers.collectAsState(emptyList())
val queryState = rememberTextFieldState() val queryState = rememberTextFieldState()
var searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> by remember { var searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> by remember {
mutableStateOf(SearchBarResultState.Initial()) mutableStateOf(SearchBarResultState.Initial)
} }
var showSearchLoader by remember { mutableStateOf(false) } var showSearchLoader by remember { mutableStateOf(false) }
val searchQuery = queryState.text.toString() val searchQuery = queryState.text.toString()
LaunchedEffect(searchQuery) { LaunchedEffect(searchQuery) {
searchResults = SearchBarResultState.Initial() searchResults = SearchBarResultState.Initial
showSearchLoader = false showSearchLoader = false
userRepository.search(searchQuery).onEach { state -> userRepository.search(searchQuery).onEach { state ->
showSearchLoader = state.isSearching showSearchLoader = state.isSearching
searchResults = when { searchResults = when {
state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial() state.results.isEmpty() && state.isSearching -> SearchBarResultState.Initial
state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound() state.results.isEmpty() && !state.isSearching -> SearchBarResultState.NoResultsFound
else -> SearchBarResultState.Results(state.results.toImmutableList()) else -> SearchBarResultState.Results(state.results.toImmutableList())
} }
}.launchIn(this) }.launchIn(this)
@@ -47,7 +47,7 @@ open class UserListStateProvider : PreviewParameterProvider<UserListState> {
aUserListState( aUserListState(
isSearchActive = true, isSearchActive = true,
searchQuery = "something-with-no-results", searchQuery = "something-with-no-results",
searchResults = SearchBarResultState.NoResultsFound() searchResults = SearchBarResultState.NoResultsFound
), ),
aUserListState( aUserListState(
isSearchActive = true, isSearchActive = true,
@@ -63,7 +63,7 @@ open class UserListStateProvider : PreviewParameterProvider<UserListState> {
fun aUserListState( fun aUserListState(
searchQuery: String = "", searchQuery: String = "",
isSearchActive: Boolean = false, isSearchActive: Boolean = false,
searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> = SearchBarResultState.Initial(), searchResults: SearchBarResultState<ImmutableList<UserSearchResult>> = SearchBarResultState.Initial,
selectedUsers: List<MatrixUser> = emptyList(), selectedUsers: List<MatrixUser> = emptyList(),
showSearchLoader: Boolean = false, showSearchLoader: Boolean = false,
selectionMode: SelectionMode = SelectionMode.Single, selectionMode: SelectionMode = SelectionMode.Single,
@@ -40,7 +40,6 @@ class DefaultUserListPresenterTest {
FakeMatrixClient(), FakeMatrixClient(),
) )
presenter.test { presenter.test {
skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.searchQuery.text.toString()).isEmpty() assertThat(initialState.searchQuery.text.toString()).isEmpty()
assertThat(initialState.isMultiSelectionEnabled).isFalse() assertThat(initialState.isMultiSelectionEnabled).isFalse()
@@ -60,7 +59,6 @@ class DefaultUserListPresenterTest {
FakeMatrixClient(), FakeMatrixClient(),
) )
presenter.test { presenter.test {
skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
assertThat(initialState.searchQuery.text.toString()).isEmpty() assertThat(initialState.searchQuery.text.toString()).isEmpty()
assertThat(initialState.isMultiSelectionEnabled).isTrue() assertThat(initialState.isMultiSelectionEnabled).isTrue()
@@ -80,7 +78,6 @@ class DefaultUserListPresenterTest {
FakeMatrixClient(), FakeMatrixClient(),
) )
presenter.test { presenter.test {
skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
initialState.eventSink(UserListEvents.OnSearchActiveChanged(true)) initialState.eventSink(UserListEvents.OnSearchActiveChanged(true))
@@ -90,13 +87,11 @@ class DefaultUserListPresenterTest {
initialState.searchQuery.setTextAndPlaceCursorAtEnd(matrixIdQuery) initialState.searchQuery.setTextAndPlaceCursorAtEnd(matrixIdQuery)
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(matrixIdQuery) assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(matrixIdQuery)
assertThat(userRepository.providedQuery).isEqualTo(matrixIdQuery) assertThat(userRepository.providedQuery).isEqualTo(matrixIdQuery)
skipItems(1)
val notMatrixIdQuery = "name" val notMatrixIdQuery = "name"
initialState.searchQuery.setTextAndPlaceCursorAtEnd(notMatrixIdQuery) initialState.searchQuery.setTextAndPlaceCursorAtEnd(notMatrixIdQuery)
assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(notMatrixIdQuery) assertThat(awaitItem().searchQuery.text.toString()).isEqualTo(notMatrixIdQuery)
assertThat(userRepository.providedQuery).isEqualTo(notMatrixIdQuery) assertThat(userRepository.providedQuery).isEqualTo(notMatrixIdQuery)
skipItems(1)
initialState.eventSink(UserListEvents.OnSearchActiveChanged(false)) initialState.eventSink(UserListEvents.OnSearchActiveChanged(false))
assertThat(awaitItem().isSearchActive).isFalse() assertThat(awaitItem().isSearchActive).isFalse()
@@ -115,13 +110,12 @@ class DefaultUserListPresenterTest {
FakeMatrixClient(), FakeMatrixClient(),
) )
presenter.test { presenter.test {
skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice") initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
assertThat(userRepository.providedQuery).isEqualTo("alice") assertThat(userRepository.providedQuery).isEqualTo("alice")
skipItems(2) skipItems(1)
// When the user repository emits a result, it's copied to the state // When the user repository emits a result, it's copied to the state
val result = UserSearchResultState( val result = UserSearchResultState(
@@ -166,13 +160,12 @@ class DefaultUserListPresenterTest {
FakeMatrixClient(), FakeMatrixClient(),
) )
presenter.test { presenter.test {
skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice") initialState.searchQuery.setTextAndPlaceCursorAtEnd("alice")
assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java) assertThat(initialState.searchResults).isInstanceOf(SearchBarResultState.Initial::class.java)
assertThat(userRepository.providedQuery).isEqualTo("alice") assertThat(userRepository.providedQuery).isEqualTo("alice")
skipItems(2) skipItems(1)
// When the results list is empty, the state is set to NoResults // When the results list is empty, the state is set to NoResults
userRepository.emitState(UserSearchResultState(results = emptyList(), isSearching = false)) userRepository.emitState(UserSearchResultState(results = emptyList(), isSearching = false))
@@ -190,7 +183,6 @@ class DefaultUserListPresenterTest {
FakeMatrixClient(), FakeMatrixClient(),
) )
presenter.test { presenter.test {
skipItems(1)
val initialState = awaitItem() val initialState = awaitItem()
val userA = aMatrixUser("@userA:domain", "A") val userA = aMatrixUser("@userA:domain", "A")
@@ -59,7 +59,7 @@ fun <T> SearchBar(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
enabled: Boolean = true, enabled: Boolean = true,
showBackButton: Boolean = true, showBackButton: Boolean = true,
resultState: SearchBarResultState<T> = SearchBarResultState.Initial(), resultState: SearchBarResultState<T> = SearchBarResultState.Initial,
shape: Shape = SearchBarDefaults.inputFieldShape, shape: Shape = SearchBarDefaults.inputFieldShape,
tonalElevation: Dp = SearchBarDefaults.TonalElevation, tonalElevation: Dp = SearchBarDefaults.TonalElevation,
windowInsets: WindowInsets = SearchBarDefaults.windowInsets, windowInsets: WindowInsets = SearchBarDefaults.windowInsets,
@@ -134,7 +134,7 @@ fun <T> SearchBar(
resultHandler(resultState.results) resultHandler(resultState.results)
} }
is SearchBarResultState.NoResultsFound<T> -> { is SearchBarResultState.NoResultsFound -> {
// No results found, show a message // No results found, show a message
Spacer(Modifier.size(80.dp)) Spacer(Modifier.size(80.dp))
@@ -200,12 +200,12 @@ object ElementSearchBarDefaults {
} }
@Immutable @Immutable
sealed interface SearchBarResultState<in T> { sealed interface SearchBarResultState<out T> {
/** No search results are available yet (e.g. because the user hasn't entered a search term). */ /** No search results are available yet (e.g. because the user hasn't entered a search term). */
class Initial<T> : SearchBarResultState<T> data object Initial : SearchBarResultState<Nothing>
/** The search has completed, but no results were found. */ /** The search has completed, but no results were found. */
class NoResultsFound<T> : SearchBarResultState<T> data object NoResultsFound : SearchBarResultState<Nothing>
/** The search has completed, and some matching users were found. */ /** The search has completed, and some matching users were found. */
data class Results<T>(val results: T) : SearchBarResultState<T> data class Results<T>(val results: T) : SearchBarResultState<T>
@@ -249,7 +249,7 @@ internal fun SearchBarActiveWithNoResultsPreview() = ElementThemedPreview {
ContentToPreview( ContentToPreview(
initialQuery = "search term", initialQuery = "search term",
active = true, active = true,
resultState = SearchBarResultState.NoResultsFound<String>(), resultState = SearchBarResultState.NoResultsFound,
) )
} }
@@ -293,7 +293,7 @@ private fun ContentToPreview(
initialQuery: String = "", initialQuery: String = "",
active: Boolean = false, active: Boolean = false,
showBackButton: Boolean = true, showBackButton: Boolean = true,
resultState: SearchBarResultState<String> = SearchBarResultState.Initial(), resultState: SearchBarResultState<String> = SearchBarResultState.Initial,
contentPrefix: @Composable ColumnScope.() -> Unit = {}, contentPrefix: @Composable ColumnScope.() -> Unit = {},
contentSuffix: @Composable ColumnScope.() -> Unit = {}, contentSuffix: @Composable ColumnScope.() -> Unit = {},
resultHandler: @Composable ColumnScope.(String) -> Unit = {}, resultHandler: @Composable ColumnScope.(String) -> Unit = {},
@@ -55,7 +55,7 @@ class DefaultEmojiPickerPresenter(
override fun present(): EmojiPickerState { override fun present(): EmojiPickerState {
val queryState = rememberTextFieldState() val queryState = rememberTextFieldState()
var isSearchActive by remember { mutableStateOf(false) } var isSearchActive by remember { mutableStateOf(false) }
var emojiResults by remember { mutableStateOf<SearchBarResultState<ImmutableList<Emoji>>>(SearchBarResultState.Initial()) } var emojiResults by remember { mutableStateOf<SearchBarResultState<ImmutableList<Emoji>>>(SearchBarResultState.Initial) }
val data by produceState(EmojiPickerData.Empty) { val data by produceState(EmojiPickerData.Empty) {
val storeDeferred = async { emojibaseProvider.getStore() } val storeDeferred = async { emojibaseProvider.getStore() }
@@ -93,11 +93,7 @@ class DefaultEmojiPickerPresenter(
val searchQuery = queryState.text.toString() val searchQuery = queryState.text.toString()
LaunchedEffect(searchQuery, data) { LaunchedEffect(searchQuery, data) {
if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) { if (searchQuery.isEmpty() || data.allEmojis.isEmpty()) {
// `SearchBarResultState.Initial` has no `equals` override, so reassigning a new instance emojiResults = SearchBarResultState.Initial
// would trigger a redundant emission each time this effect re-runs while the query is empty.
if (emojiResults !is SearchBarResultState.Initial) {
emojiResults = SearchBarResultState.Initial()
}
return@LaunchedEffect return@LaunchedEffect
} }
delay(100.milliseconds) delay(100.milliseconds)
@@ -62,7 +62,7 @@ internal fun aDefaultEmojiPickerState(
}.toImmutableList(), }.toImmutableList(),
searchQuery: String = "", searchQuery: String = "",
isSearchActive: Boolean = false, isSearchActive: Boolean = false,
searchResults: SearchBarResultState<ImmutableList<Emoji>> = SearchBarResultState.Initial(), searchResults: SearchBarResultState<ImmutableList<Emoji>> = SearchBarResultState.Initial,
eventSink: (EmojiPickerEvent) -> Unit = {}, eventSink: (EmojiPickerEvent) -> Unit = {},
) = DefaultEmojiPickerState( ) = DefaultEmojiPickerState(
categories = categories, categories = categories,
@@ -65,8 +65,8 @@ class RoomSelectPresenter(
derivedStateOf { derivedStateOf {
when { when {
roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList()) roomSummaryDetailsList.isNotEmpty() -> SearchBarResultState.Results(roomSummaryDetailsList.toImmutableList())
isSearchActive -> SearchBarResultState.NoResultsFound() isSearchActive -> SearchBarResultState.NoResultsFound
else -> SearchBarResultState.Initial() else -> SearchBarResultState.Initial
} }
} }
} }
@@ -52,7 +52,7 @@ open class RoomSelectStateProvider : PreviewParameterProvider<RoomSelectState> {
internal fun aRoomSelectState( internal fun aRoomSelectState(
mode: RoomSelectMode = RoomSelectMode.Forward, mode: RoomSelectMode = RoomSelectMode.Forward,
maxNumberOfRooms: Int = 10, maxNumberOfRooms: Int = 10,
resultState: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial(), resultState: SearchBarResultState<ImmutableList<SelectRoomInfo>> = SearchBarResultState.Initial,
searchQuery: String = "", searchQuery: String = "",
isSearchActive: Boolean = false, isSearchActive: Boolean = false,
selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(), selectedRooms: ImmutableList<SelectRoomInfo> = persistentListOf(),