diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt index f25e00e9cab..12b62f37885 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllPeopleScreen.kt @@ -16,16 +16,15 @@ * along with this program. If not, see http://www.gnu.org/licenses/. */ +@file:Suppress("TooManyFunctions") + package com.wire.android.ui.home.conversations.search -import androidx.annotation.StringRes import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn @@ -36,31 +35,34 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp import com.wire.android.R import com.wire.android.model.Clickable import com.wire.android.model.ItemActionType import com.wire.android.ui.common.button.WireSecondaryButton import com.wire.android.ui.common.dimensions -import com.wire.android.ui.common.progress.WireCircularProgressIndicator +import com.wire.android.ui.common.progress.CenteredCircularProgressBarIndicator import com.wire.android.ui.home.conversations.search.widget.SearchFailureBox +import com.wire.android.ui.home.conversationslist.model.Membership import com.wire.android.ui.home.newconversation.model.Contact import com.wire.android.ui.theme.WireTheme import com.wire.android.util.extension.folderWithElements import com.wire.android.util.ui.PreviewMultipleThemes +import com.wire.kalium.logic.data.user.ConnectionState import com.wire.kalium.logic.data.user.UserId import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableSet +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.persistentSetOf +import kotlinx.collections.immutable.toPersistentList +import kotlinx.collections.immutable.toPersistentSet private const val DEFAULT_SEARCH_RESULT_ITEM_SIZE = 4 @Composable fun SearchAllPeopleScreen( searchQuery: String, - noneSearchSucceed: Boolean, contactsSearchResult: ImmutableList, publicSearchResult: ImmutableList, contactsAddedToGroup: ImmutableSet, @@ -71,27 +73,25 @@ fun SearchAllPeopleScreen( onOpenUserProfile: (Contact) -> Unit, lazyListState: LazyListState = rememberLazyListState() ) { - if (contactsSearchResult.isEmpty() && publicSearchResult.isEmpty()) { - EmptySearchQueryScreen() - } else { - if (noneSearchSucceed) { - SearchFailureBox(R.string.label_no_results_found) - } else { - Column { - SearchResult( - searchQuery = searchQuery, - publicSearchResult = publicSearchResult, - contactsSearchResult = contactsSearchResult, - contactsAddedToGroup = contactsAddedToGroup, - onChecked = onChecked, - onOpenUserProfile = onOpenUserProfile, - lazyListState = lazyListState, - isSearchActive = isSearchActive, - isLoading = isLoading, - actionType = actionType, - ) - } - } + val emptyResults = contactsSearchResult.isEmpty() && publicSearchResult.isEmpty() + when { + isLoading -> CenteredCircularProgressBarIndicator() + + searchQuery.isBlank() && emptyResults -> EmptySearchQueryScreen() + + searchQuery.isNotBlank() && emptyResults -> SearchFailureBox(R.string.label_no_results_found) + + else -> SearchResult( + searchQuery = searchQuery, + publicSearchResult = publicSearchResult, + contactsSearchResult = contactsSearchResult, + contactsAddedToGroup = contactsAddedToGroup, + onChecked = onChecked, + onOpenUserProfile = onOpenUserProfile, + lazyListState = lazyListState, + isSearchActive = isSearchActive, + actionType = actionType, + ) } } @@ -100,7 +100,6 @@ private fun SearchResult( searchQuery: String, contactsSearchResult: ImmutableList, publicSearchResult: ImmutableList, - isLoading: Boolean, isSearchActive: Boolean, actionType: ItemActionType, contactsAddedToGroup: ImmutableSet, @@ -124,8 +123,7 @@ private fun SearchResult( searchQuery = searchQuery, contactsAddedToGroup = contactsAddedToGroup, onChecked = onChecked, - isLoading = isLoading, - contactSearchResult = contactsSearchResult, + searchResult = contactsSearchResult, allItemsVisible = !isSearchActive || searchPeopleScreenState.contactsAllResultsCollapsed, showMoreOrLessButtonVisible = isSearchActive, onShowAllButtonClicked = searchPeopleScreenState::toggleShowAllContactsResult, @@ -138,8 +136,7 @@ private fun SearchResult( externalSearchResults( searchTitle = context.getString(R.string.label_public_wire), searchQuery = searchQuery, - contactSearchResult = publicSearchResult, - isLoading = isLoading, + searchResult = publicSearchResult, allItemsVisible = searchPeopleScreenState.publicResultsCollapsed, showMoreOrLessButtonVisible = isSearchActive, onShowAllButtonClicked = searchPeopleScreenState::toggleShowAllPublicResult, @@ -152,72 +149,6 @@ private fun SearchResult( @Suppress("LongParameterList") private fun LazyListScope.internalSearchResults( - searchTitle: String, - searchQuery: String, - contactsAddedToGroup: ImmutableSet, - onChecked: (Boolean, Contact) -> Unit, - actionType: ItemActionType, - isLoading: Boolean, - contactSearchResult: ImmutableList, - allItemsVisible: Boolean, - showMoreOrLessButtonVisible: Boolean, - onShowAllButtonClicked: () -> Unit, - onOpenUserProfile: (Contact) -> Unit -) { - when { - isLoading -> { - inProgressItem() - } - - else -> { - internalSuccessItem( - searchTitle = searchTitle, - allItemsVisible = allItemsVisible, - showMoreOrLessButtonVisible = showMoreOrLessButtonVisible, - contactsAddedToGroup = contactsAddedToGroup, - onChecked = onChecked, - searchResult = contactSearchResult, - searchQuery = searchQuery, - onShowAllButtonClicked = onShowAllButtonClicked, - onOpenUserProfile = onOpenUserProfile, - actionType = actionType, - ) - } - } -} - -@Suppress("LongParameterList") -private fun LazyListScope.externalSearchResults( - searchTitle: String, - searchQuery: String, - contactSearchResult: ImmutableList, - isLoading: Boolean, - allItemsVisible: Boolean, - showMoreOrLessButtonVisible: Boolean, - onShowAllButtonClicked: () -> Unit, - onOpenUserProfile: (Contact) -> Unit, -) { - when { - isLoading -> { - inProgressItem() - } - - else -> { - externalSuccessItem( - searchTitle = searchTitle, - allItemsVisible = allItemsVisible, - showMoreOrLessButtonVisible = showMoreOrLessButtonVisible, - searchResult = contactSearchResult, - searchQuery = searchQuery, - onShowAllButtonClicked = onShowAllButtonClicked, - onOpenUserProfile = onOpenUserProfile, - ) - } - } -} - -@Suppress("LongParameterList") -private fun LazyListScope.internalSuccessItem( searchTitle: String, allItemsVisible: Boolean, showMoreOrLessButtonVisible: Boolean, @@ -274,7 +205,7 @@ private fun LazyListScope.internalSuccessItem( } @Suppress("LongParameterList") -private fun LazyListScope.externalSuccessItem( +private fun LazyListScope.externalSearchResults( searchTitle: String, allItemsVisible: Boolean, showMoreOrLessButtonVisible: Boolean, @@ -323,30 +254,6 @@ private fun LazyListScope.externalSuccessItem( } } -fun LazyListScope.inProgressItem() { - item { - Box( - Modifier - .fillMaxWidth() - .height(224.dp) - ) { - WireCircularProgressIndicator( - progressColor = Color.Black, - modifier = Modifier.align( - Alignment.Center - ) - ) - } - } -} - -fun LazyListScope.failureItem(@StringRes failureMessage: Int) { - item { - SearchFailureBox(failureMessage) - } -} - -@OptIn(ExperimentalAnimationApi::class) @Composable private fun ShowButton( isShownAll: Boolean, @@ -373,3 +280,116 @@ fun PreviewShowButton() { ShowButton(isShownAll = false, onShowButtonClicked = {}) } } + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllPeopleScreen_Loading() = WireTheme { + SearchAllPeopleScreen( + searchQuery = "", + contactsSearchResult = persistentListOf(), + publicSearchResult = persistentListOf(), + contactsAddedToGroup = persistentSetOf(), + isLoading = true, + isSearchActive = false, + actionType = ItemActionType.CHECK, + onChecked = { _, _ -> }, + onOpenUserProfile = {} + ) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllPeopleScreen_InitialResults() = WireTheme { + val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true).toPersistentList() + SearchAllPeopleScreen( + searchQuery = "", + contactsSearchResult = contacts, + publicSearchResult = persistentListOf(), + contactsAddedToGroup = persistentSetOf(), + isLoading = false, + isSearchActive = false, + actionType = ItemActionType.CHECK, + onChecked = { _, _ -> }, + onOpenUserProfile = {} + ) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllPeopleScreen_EmptyInitialResults() = WireTheme { + SearchAllPeopleScreen( + searchQuery = "", + contactsSearchResult = persistentListOf(), + publicSearchResult = persistentListOf(), + contactsAddedToGroup = persistentSetOf(), + isLoading = false, + isSearchActive = false, + actionType = ItemActionType.CHECK, + onChecked = { _, _ -> }, + onOpenUserProfile = {} + ) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllPeopleScreen_SearchResults_TypeClick() = WireTheme { + val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true).toPersistentList() + val public = previewContactsList(count = 10, startIndex = 10, isContact = false).toPersistentList() + SearchAllPeopleScreen( + searchQuery = "Con", + contactsSearchResult = contacts, + publicSearchResult = public, + contactsAddedToGroup = persistentSetOf(), + isLoading = false, + isSearchActive = true, + actionType = ItemActionType.CLICK, + onChecked = { _, _ -> }, + onOpenUserProfile = {} + ) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllPeopleScreen_SearchResults_TypeCheck() = WireTheme { + val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true).toPersistentList() + val public = previewContactsList(count = 10, startIndex = 10, isContact = false).toPersistentList() + val selectedContacts = contacts.filterIndexed { index, _ -> index % 3 == 0 }.toPersistentSet() + SearchAllPeopleScreen( + searchQuery = "Con", + contactsSearchResult = contacts, + publicSearchResult = public, + contactsAddedToGroup = selectedContacts, + isLoading = false, + isSearchActive = true, + actionType = ItemActionType.CHECK, + onChecked = { _, _ -> }, + onOpenUserProfile = {} + ) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllPeopleScreen_EmptySearchResults() = WireTheme { + SearchAllPeopleScreen( + searchQuery = "Con", + contactsSearchResult = persistentListOf(), + publicSearchResult = persistentListOf(), + contactsAddedToGroup = persistentSetOf(), + isLoading = false, + isSearchActive = true, + actionType = ItemActionType.CLICK, + onChecked = { _, _ -> }, + onOpenUserProfile = {} + ) +} + +private fun previewContact(index: Int, isContact: Boolean) = Contact( + id = index.toString(), + domain = "wire.com", + name = "Contact nr $index", + connectionState = if (isContact) ConnectionState.ACCEPTED else ConnectionState.NOT_CONNECTED, + membership = Membership.Standard, +) + +private fun previewContactsList(count: Int, startIndex: Int = 0, isContact: Boolean): List = + buildList { repeat(count) { index -> add(previewContact(startIndex + index, isContact)) } } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt index 2edcc97e832..0c8bfabbde7 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchAllServicesScreen.kt @@ -38,8 +38,14 @@ import com.wire.android.ui.common.UserProfileAvatar import com.wire.android.ui.common.dimensions import com.wire.android.ui.common.progress.CenteredCircularProgressBarIndicator import com.wire.android.ui.home.conversations.search.widget.SearchFailureBox +import com.wire.android.ui.home.conversationslist.model.Membership import com.wire.android.ui.home.newconversation.model.Contact +import com.wire.android.ui.theme.WireTheme +import com.wire.android.util.ui.PreviewMultipleThemes +import com.wire.kalium.logic.data.user.ConnectionState import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList @Composable fun SearchAllServicesScreen( @@ -57,7 +63,6 @@ fun SearchAllServicesScreen( onServiceClicked = onServiceClicked, result = searchServicesViewModel.state.result, lazyListState = lazyState, - error = searchServicesViewModel.state.error, isLoading = searchServicesViewModel.state.isLoading ) } @@ -67,27 +72,23 @@ private fun SearchAllServicesContent( searchQuery: String, result: ImmutableList, isLoading: Boolean, - error: Boolean, onServiceClicked: (Contact) -> Unit, lazyListState: LazyListState = rememberLazyListState() ) { when { isLoading -> CenteredCircularProgressBarIndicator() - error -> SearchFailureBox(failureMessage = R.string.label_general_error) // TODO(user experience): what to do when user team has no services? - result.isEmpty() -> { - EmptySearchQueryScreen() - } + searchQuery.isBlank() && result.isEmpty() -> EmptySearchQueryScreen() - else -> { - SuccessServicesList( - searchQuery = searchQuery, - onServiceClicked = onServiceClicked, - services = result, - lazyListState = lazyListState - ) - } + searchQuery.isNotBlank() && result.isEmpty() -> SearchFailureBox(R.string.label_no_results_found) + + else -> SuccessServicesList( + searchQuery = searchQuery, + onServiceClicked = onServiceClicked, + services = result, + lazyListState = lazyListState + ) } } @@ -139,3 +140,45 @@ private fun SuccessServicesList( } } } + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllServicesScreen_Loading() = WireTheme { + SearchAllServicesContent("", persistentListOf(), true, {}) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllServicesScreen_InitialResults() = WireTheme { + SearchAllServicesContent("", previewServiceList(count = 10).toPersistentList(), false, {}) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllServicesScreen_EmptyInitialResults() = WireTheme { + SearchAllServicesContent("", persistentListOf(), false, {}) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllServicesScreen_SearchResults() = WireTheme { + SearchAllServicesContent("Serv", previewServiceList(count = 10).toPersistentList(), false, {}) +} + +@PreviewMultipleThemes +@Composable +fun PreviewSearchAllServicesScreen_EmptySearchResults() = WireTheme { + SearchAllServicesContent("Serv", persistentListOf(), false, {}) +} + +private fun previewService(index: Int) = Contact( + id = index.toString(), + domain = "wire.com", + name = "Service nr $index", + connectionState = ConnectionState.NOT_CONNECTED, + membership = Membership.Service, +) + +private fun previewServiceList(count: Int): List = buildList { + repeat(count) { index -> add(previewService(index)) } +} diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt index 2b26681bbc2..99b47b31a42 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt @@ -173,7 +173,6 @@ fun SearchUsersAndServicesScreen( onOpenUserProfile = onOpenUserProfile, onContactChecked = onContactChecked, isSearchActive = isSearchActive, - isLoading = false, // TODO: update correctly actionType = actionType, ) } @@ -194,7 +193,6 @@ fun SearchUsersAndServicesScreen( onContactChecked = onContactChecked, onOpenUserProfile = onOpenUserProfile, isSearchActive = isSearchActive, - isLoading = false, // TODO: update correctly actionType = actionType, ) } @@ -254,7 +252,6 @@ enum class SearchPeopleScreenType { private fun SearchAllPeopleOrContactsScreen( searchQuery: String, contactsAddedToGroup: ImmutableSet, - isLoading: Boolean, isSearchActive: Boolean, actionType: ItemActionType, onOpenUserProfile: (Contact) -> Unit, @@ -268,8 +265,7 @@ private fun SearchAllPeopleOrContactsScreen( val lazyState = rememberLazyListState() SearchAllPeopleScreen( - searchQuery = searchQuery, - noneSearchSucceed = searchUserViewModel.state.noneSearchSucceeded, + searchQuery = searchUserViewModel.state.searchQuery, contactsSearchResult = searchUserViewModel.state.contactsResult, publicSearchResult = searchUserViewModel.state.publicResult, contactsAddedToGroup = contactsAddedToGroup, @@ -277,7 +273,7 @@ private fun SearchAllPeopleOrContactsScreen( onOpenUserProfile = onOpenUserProfile, lazyListState = lazyState, isSearchActive = isSearchActive, - isLoading = isLoading, + isLoading = searchUserViewModel.state.isLoading, actionType = actionType, ) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchServicesViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchServicesViewModel.kt index 1cab63cb0c7..0b0aa87535c 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchServicesViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchServicesViewModel.kt @@ -20,7 +20,6 @@ package com.wire.android.ui.home.conversations.search import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.wire.android.mapper.ContactMapper @@ -41,28 +40,23 @@ class SearchServicesViewModel @Inject constructor( private val contactMapper: ContactMapper, private val searchServicesByName: SearchServicesByNameUseCase, ) : ViewModel() { - var state: SearchServicesState by mutableStateOf(SearchServicesState()) + var state: SearchServicesState by mutableStateOf(SearchServicesState(isLoading = true)) private set fun search(query: String) { viewModelScope.launch { - if (query.isEmpty()) { - getAllServices().first().also { services -> - state = state.copy(result = services.map(contactMapper::fromService).toImmutableList()) - } + val result = if (query.isEmpty()) { + getAllServices().first() } else { - searchServicesByName(query).first().also { services -> - state = state.copy(result = services.map(contactMapper::fromService).toImmutableList()) - } + searchServicesByName(query).first() } + state = state.copy(isLoading = false, searchQuery = query, result = result.map(contactMapper::fromService).toImmutableList()) } } } data class SearchServicesState( val result: ImmutableList = persistentListOf(), - val searchQuery: TextFieldValue = TextFieldValue(), - val noneSearchSucceeded: Boolean = false, + val searchQuery: String = "", val isLoading: Boolean = false, - val error: Boolean = false ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUserViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUserViewModel.kt index d55b187d847..8df20210dbf 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUserViewModel.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUserViewModel.kt @@ -56,7 +56,7 @@ class SearchUserViewModel @Inject constructor( null } - var state: SearchUserState by mutableStateOf(SearchUserState()) + var state: SearchUserState by mutableStateOf(SearchUserState(isLoading = true)) private set fun search(query: String) = viewModelScope.launch { @@ -82,6 +82,8 @@ class SearchUserViewModel @Inject constructor( customDomain = domain ).also { userSearchEntities -> state = state.copy( + isLoading = false, + searchQuery = searchTerm, contactsResult = userSearchEntities.connected.map(contactMapper::fromSearchUserResult).toImmutableList(), publicResult = userSearchEntities.notConnected.map(contactMapper::fromSearchUserResult).toImmutableList() ) @@ -95,6 +97,8 @@ class SearchUserViewModel @Inject constructor( customDomain = domain ).also { userSearchEntities -> state = state.copy( + isLoading = false, + searchQuery = searchTerm, contactsResult = userSearchEntities.connected.map(contactMapper::fromSearchUserResult).toImmutableList(), publicResult = userSearchEntities.notConnected.map(contactMapper::fromSearchUserResult).toImmutableList() ) @@ -105,6 +109,6 @@ class SearchUserViewModel @Inject constructor( data class SearchUserState( val contactsResult: ImmutableList = persistentListOf(), val publicResult: ImmutableList = persistentListOf(), - val includeServices: Boolean = false, - val noneSearchSucceeded: Boolean = false + val searchQuery: String = "", + val isLoading: Boolean = false, ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/widget/SearchFailureWidget.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/widget/SearchFailureWidget.kt index 3765144738d..fadffceff3c 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/widget/SearchFailureWidget.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/widget/SearchFailureWidget.kt @@ -20,26 +20,21 @@ package com.wire.android.ui.home.conversations.search.widget import androidx.annotation.StringRes import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp +import com.wire.android.ui.theme.WireTheme import com.wire.android.ui.theme.wireColorScheme import com.wire.android.ui.theme.wireTypography +import com.wire.android.util.ui.PreviewMultipleThemes @Composable fun SearchFailureBox(@StringRes failureMessage: Int) { - Box( - Modifier - .fillMaxWidth() - .height(224.dp) - ) { + Box(Modifier.fillMaxSize()) { Text( stringResource(id = failureMessage), modifier = Modifier.align(Alignment.Center), @@ -48,8 +43,8 @@ fun SearchFailureBox(@StringRes failureMessage: Int) { } } -@Preview +@PreviewMultipleThemes @Composable -fun SearchFailureBoxPreview() { +fun SearchFailureBoxPreview() = WireTheme { SearchFailureBox(failureMessage = com.wire.android.R.string.label_no_results_found) }