From 10c2a13a4101d68064ecff8608f41cc0b2bd34e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Saleniuk?= <30429749+saleniuk@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:15:43 +0000 Subject: [PATCH 1/3] Commit with unresolved merge conflicts outside of submodules --- .../search/SearchAllPeopleScreen.kt | 112 +++++++- .../search/SearchAllServicesScreen.kt | 75 +++++- .../search/SearchPeopleRouter.kt | 253 ++++++++++++++++++ .../search/SearchServicesViewModel.kt | 17 +- .../search/SearchUserViewModel.kt | 33 +++ .../search/widget/SearchFailureWidget.kt | 17 +- .../SendConnectionRequestViewModel.kt | 58 ++++ 7 files changed, 537 insertions(+), 28 deletions(-) create mode 100644 app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt create mode 100644 app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt 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 a1f22068e10..db67224eb03 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 @@ -25,7 +25,6 @@ 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 @@ -37,22 +36,37 @@ import androidx.compose.runtime.SideEffect 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.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource +<<<<<<< HEAD import androidx.compose.ui.unit.dp +======= +import androidx.hilt.navigation.compose.hiltViewModel +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) 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 +<<<<<<< HEAD import com.wire.android.ui.common.progress.WireCircularProgressIndicator import com.wire.android.ui.home.conversationslist.model.Membership +======= +import com.wire.android.ui.common.progress.CenteredCircularProgressBarIndicator +import com.wire.android.ui.common.snackbar.LocalSnackbarHostState +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.SendConnectionRequestViewModel +import com.wire.android.ui.home.newconversation.SendConnectionRequestViewModelImpl +import com.wire.android.ui.home.newconversation.SendConnectionRequestViewModelPreview +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) import com.wire.android.ui.home.newconversation.model.Contact import com.wire.android.ui.theme.WireTheme import com.wire.android.util.extension.FolderType import com.wire.android.util.extension.folderWithElements import com.wire.android.util.ui.PreviewMultipleThemes +<<<<<<< HEAD import com.wire.android.util.ui.keepOnTopWhenNotScrolled import com.wire.kalium.logic.data.user.ConnectionState import com.wire.kalium.logic.data.user.UserId @@ -60,6 +74,16 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList +======= +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.coroutines.launch +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private const val DEFAULT_SEARCH_RESULT_ITEM_SIZE = 4 @@ -82,6 +106,7 @@ fun SearchAllPeopleScreen( onPublicResultsExpansionChanged: (Boolean) -> Unit = {}, lazyListState: LazyListState = rememberLazyListState() ) { +<<<<<<< HEAD if (contactsSearchResult.isEmpty() && publicSearchResult.isEmpty()) { EmptySearchQueryScreen() } else { @@ -90,10 +115,26 @@ fun SearchAllPeopleScreen( publicSearchResult = publicSearchResult, contactsSearchResult = contactsSearchResult, contactsSelectedSearchResult = contactsSelectedSearchResult, +======= + 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, +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) onChecked = onChecked, onOpenUserProfile = onOpenUserProfile, lazyListState = lazyListState, isSearchActive = isSearchActive, +<<<<<<< HEAD isLoading = isLoading, actionType = actionType, selectedContactResultsExpanded = selectedContactResultsExpanded, @@ -102,6 +143,8 @@ fun SearchAllPeopleScreen( onContactResultsExpansionChanged = onContactResultsExpansionChanged, publicResultsExpanded = publicResultsExpanded, onPublicResultsExpansionChanged = onPublicResultsExpansionChanged, +======= +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) ) } } @@ -111,18 +154,27 @@ private fun SearchResult( searchQuery: String, contactsSearchResult: ImmutableList, publicSearchResult: ImmutableList, +<<<<<<< HEAD contactsSelectedSearchResult: ImmutableList, isLoading: Boolean, +======= +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) isSearchActive: Boolean, actionType: ItemActionType, onChecked: (Boolean, Contact) -> Unit, onOpenUserProfile: (Contact) -> Unit, +<<<<<<< HEAD selectedContactResultsExpanded: Boolean, onSelectedContactResultsExpansionChanged: (Boolean) -> Unit, contactResultsExpanded: Boolean, onContactResultsExpansionChanged: (Boolean) -> Unit, publicResultsExpanded: Boolean, onPublicResultsExpansionChanged: (Boolean) -> Unit, +======= + sendConnectionRequestViewModel: SendConnectionRequestViewModel = + if (LocalInspectionMode.current) SendConnectionRequestViewModelPreview + else hiltViewModel(), +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) lazyListState: LazyListState = rememberLazyListState() ) { val searchPeopleScreenState = rememberSearchPeopleScreenState() @@ -140,10 +192,16 @@ private fun SearchResult( searchTitle = context.getString(R.string.label_selected) + " (${contactsSelectedSearchResult.size})", searchQuery = searchQuery, onChecked = onChecked, +<<<<<<< HEAD isLoading = isLoading, contactSearchResult = contactsSelectedSearchResult.map { it to true }.toImmutableList(), allItemsVisible = true, // for selected contacts we always show all items showMoreOrLessButtonVisible = false, +======= + searchResult = contactsSearchResult, + contactsAddedToGroup = contactsAddedToGroup, + showAllItems = !isSearchActive || searchPeopleScreenState.contactsAllResultsCollapsed, +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) onShowAllButtonClicked = searchPeopleScreenState::toggleShowAllContactsResult, onOpenUserProfile = onOpenUserProfile, actionType = actionType, @@ -173,10 +231,15 @@ private fun SearchResult( externalSearchResults( searchTitle = context.getString(R.string.label_public_wire), searchQuery = searchQuery, +<<<<<<< HEAD contactSearchResult = publicSearchResult, isLoading = isLoading, allItemsVisible = searchPeopleScreenState.publicResultsCollapsed, showMoreOrLessButtonVisible = isSearchActive, +======= + searchResult = publicSearchResult, + showAllItems = searchPeopleScreenState.publicResultsCollapsed, +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) onShowAllButtonClicked = searchPeopleScreenState::toggleShowAllPublicResult, onOpenUserProfile = onOpenUserProfile, expanded = publicResultsExpanded, @@ -194,6 +257,7 @@ private fun SearchResult( @Suppress("LongParameterList") private fun LazyListScope.internalSearchResults( searchTitle: String, +<<<<<<< HEAD searchQuery: String, onChecked: (Boolean, Contact) -> Unit, actionType: ItemActionType, @@ -269,6 +333,10 @@ private fun LazyListScope.internalSuccessItem( allItemsVisible: Boolean, showMoreOrLessButtonVisible: Boolean, actionType: ItemActionType, +======= + showAllItems: Boolean, + contactsAddedToGroup: ImmutableSet, +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) onChecked: (Boolean, Contact) -> Unit, searchResult: ImmutableList>, searchQuery: String, @@ -330,7 +398,7 @@ private fun LazyListScope.internalSuccessItem( } @Suppress("LongParameterList") -private fun LazyListScope.externalSuccessItem( +private fun LazyListScope.externalSearchResults( searchTitle: String, allItemsVisible: Boolean, showMoreOrLessButtonVisible: Boolean, @@ -383,6 +451,7 @@ private fun LazyListScope.externalSuccessItem( } } +<<<<<<< HEAD fun LazyListScope.inProgressItem() { item { Box( @@ -400,6 +469,8 @@ fun LazyListScope.inProgressItem() { } } +======= +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) @Composable private fun ShowButton( isShownAll: Boolean, @@ -430,6 +501,7 @@ fun PreviewShowButton() { @PreviewMultipleThemes @Composable fun PreviewSearchAllPeopleScreen_Loading() = WireTheme { +<<<<<<< HEAD SearchAllPeopleScreen( searchQuery = "Search query", contactsSearchResult = persistentListOf(), @@ -441,10 +513,14 @@ fun PreviewSearchAllPeopleScreen_Loading() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) +======= + SearchAllPeopleScreen("Search query", persistentListOf(), persistentListOf(), persistentSetOf(), true, false, { _, _ -> }, {}) +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable +<<<<<<< HEAD fun PreviewSearchAllPeopleScreen_EmptyList() = WireTheme { SearchAllPeopleScreen( searchQuery = "Search query", @@ -457,10 +533,16 @@ fun PreviewSearchAllPeopleScreen_EmptyList() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) +======= +fun PreviewSearchAllPeopleScreen_InitialResults() = WireTheme { + val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true).toPersistentList() + SearchAllPeopleScreen("", contacts, persistentListOf(), persistentSetOf(), false, false, { _, _ -> }, {}) +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable +<<<<<<< HEAD fun PreviewSearchAllPeopleScreen_NoSearch() = WireTheme { val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true) SearchAllPeopleScreen( @@ -474,10 +556,15 @@ fun PreviewSearchAllPeopleScreen_NoSearch() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) +======= +fun PreviewSearchAllPeopleScreen_EmptyInitialResults() = WireTheme { + SearchAllPeopleScreen("", persistentListOf(), persistentListOf(), persistentSetOf(), false, false, { _, _ -> }, {}) +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable +<<<<<<< HEAD fun PreviewSearchAllPeopleScreen_SearchResults_TypeClick() = WireTheme { val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true) val public = previewContactsList(count = 10, startIndex = 10, isContact = false) @@ -492,10 +579,17 @@ fun PreviewSearchAllPeopleScreen_SearchResults_TypeClick() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) +======= +fun PreviewSearchAllPeopleScreen_SearchResults() = WireTheme { + val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true).toPersistentList() + val public = previewContactsList(count = 10, startIndex = 10, isContact = false).toPersistentList() + SearchAllPeopleScreen("Con", contacts, public, persistentSetOf(), false, true, { _, _ -> }, {}) +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable +<<<<<<< HEAD fun PreviewSearchAllPeopleScreen_SearchResults_TypeCheck() = WireTheme { val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true) val public = previewContactsList(count = 10, startIndex = 10, isContact = false) @@ -512,17 +606,29 @@ fun PreviewSearchAllPeopleScreen_SearchResults_TypeCheck() = WireTheme { onOpenUserProfile = { }, selectedContactResultsExpanded = true, ) +======= +fun PreviewSearchAllPeopleScreen_EmptySearchResults() = WireTheme { + SearchAllPeopleScreen("Con", persistentListOf(), persistentListOf(), persistentSetOf(), false, true, { _, _ -> }, {}) +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } private fun previewContact(index: Int, isContact: Boolean) = Contact( id = index.toString(), domain = "wire.com", name = "Contact nr $index", +<<<<<<< HEAD handle = "contact_$index", +======= +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) connectionState = if (isContact) ConnectionState.ACCEPTED else ConnectionState.NOT_CONNECTED, membership = Membership.Standard, ) +<<<<<<< HEAD private fun previewContactsList(count: Int, startIndex: Int = 0, isContact: Boolean): ImmutableList = buildList { repeat(count) { index -> add(previewContact(startIndex + index, isContact)) } }.toPersistentList() +======= +private fun previewContactsList(count: Int, startIndex: Int = 0, isContact: Boolean): List = + buildList { repeat(count) { index -> add(previewContact(startIndex + index, isContact)) } } +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) 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 a9d0a1aafec..741702d0303 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 @@ -39,9 +39,18 @@ 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 +<<<<<<< HEAD import com.wire.android.util.extension.folderWithElements +======= +import com.wire.android.ui.theme.WireTheme +import com.wire.android.util.ui.PreviewMultipleThemes +import com.wire.kalium.logic.data.user.ConnectionState +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.persistentListOf +import kotlinx.collections.immutable.toPersistentList @Composable fun SearchAllServicesScreen( @@ -58,8 +67,12 @@ fun SearchAllServicesScreen( searchQuery = searchServicesViewModel.state.searchQuery, onServiceClicked = onServiceClicked, result = searchServicesViewModel.state.result, +<<<<<<< HEAD lazyListState = lazyListState, error = searchServicesViewModel.state.error, +======= + lazyListState = lazyState, +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) isLoading = searchServicesViewModel.state.isLoading ) } @@ -69,27 +82,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 + ) } } @@ -141,3 +150,43 @@ 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 new file mode 100644 index 00000000000..da91a870c5c --- /dev/null +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt @@ -0,0 +1,253 @@ +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ + +package com.wire.android.ui.home.conversations.search + +import androidx.activity.compose.BackHandler +import androidx.annotation.StringRes +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.Crossfade +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.LocalOverscrollConfiguration +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.State +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.TextFieldValue +import androidx.hilt.navigation.compose.hiltViewModel +import com.wire.android.R +import com.wire.android.ui.common.CollapsingTopBarScaffold +import com.wire.android.ui.common.TabItem +import com.wire.android.ui.common.WireTabRow +import com.wire.android.ui.common.calculateCurrentTab +import com.wire.android.ui.common.topappbar.NavigationIconType +import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar +import com.wire.android.ui.common.topappbar.search.SearchTopBar +import com.wire.android.ui.common.topappbar.search.rememberSearchbarState +import com.wire.android.ui.home.newconversation.common.SelectParticipantsButtonsAlwaysEnabled +import com.wire.android.ui.home.newconversation.common.SelectParticipantsButtonsRow +import com.wire.android.ui.home.newconversation.model.Contact +import kotlinx.collections.immutable.ImmutableSet +import kotlinx.coroutines.launch + +@Suppress("ComplexMethod") +@OptIn( + ExperimentalComposeUiApi::class, + ExperimentalFoundationApi::class +) +@Composable +fun SearchUsersAndServicesScreen( + searchState: SearchState, + searchTitle: String, + actionButtonTitle: String, + userSearchSignal: State, + serviceSearchSignal: State, + selectedContacts: ImmutableSet, + onServicesSearchQueryChanged: (TextFieldValue) -> Unit, + onUsersSearchQueryChanged: (TextFieldValue) -> Unit, + onGroupSelectionSubmitAction: () -> Unit, + onContactChecked: (Boolean, Contact) -> Unit, + onOpenUserProfile: (Contact) -> Unit, + onServiceClicked: (Contact) -> Unit, + onClose: () -> Unit, + screenType: SearchPeopleScreenType +) { + val searchBarState = rememberSearchbarState() + val scope = rememberCoroutineScope() + val initialPageIndex = SearchPeopleTabItem.PEOPLE.ordinal + val pagerState = rememberPagerState( + initialPage = initialPageIndex, + pageCount = { if (searchState.isServicesAllowed) SearchPeopleTabItem.entries.size else 1 }) + val currentTabState by remember { derivedStateOf { pagerState.calculateCurrentTab() } } + + CollapsingTopBarScaffold( + topBarHeader = { elevation -> + AnimatedVisibility( + visible = !searchBarState.isSearchActive, + enter = expandVertically(), + exit = shrinkVertically(), + ) { + Box(modifier = Modifier.wrapContentSize()) { + WireCenterAlignedTopAppBar( + elevation = elevation, + title = searchTitle, + navigationIconType = NavigationIconType.Close, + onNavigationPressed = onClose + ) + } + } + }, + topBarCollapsing = { + val query = when (currentTabState) { + SearchPeopleTabItem.PEOPLE.ordinal -> searchState.userSearchQuery + SearchPeopleTabItem.SERVICES.ordinal -> searchState.serviceSearchQuery + else -> error("Unknown tab index $currentTabState") + } + + val onQueryChanged: (TextFieldValue) -> Unit = when (currentTabState) { + SearchPeopleTabItem.PEOPLE.ordinal -> onUsersSearchQueryChanged + SearchPeopleTabItem.SERVICES.ordinal -> onServicesSearchQueryChanged + else -> error("Unknown tab index $currentTabState") + } + + SearchTopBar( + isSearchActive = searchBarState.isSearchActive, + searchBarHint = stringResource(R.string.label_search_people), + searchQuery = query, + onSearchQueryChanged = onQueryChanged, + onActiveChanged = searchBarState::searchActiveChanged, + ) { + if (screenType == SearchPeopleScreenType.CONVERSATION_DETAILS + && searchState.isServicesAllowed + ) { + WireTabRow( + tabs = SearchPeopleTabItem.entries, + selectedTabIndex = currentTabState, + onTabChange = { scope.launch { pagerState.animateScrollToPage(it) } }, + divider = {} // no divider + ) + } + } + }, + content = { + Crossfade( + targetState = searchBarState.isSearchActive, label = "" + ) { isSearchActive -> + var focusedTabIndex: Int by remember { mutableStateOf(initialPageIndex) } + val keyboardController = LocalSoftwareKeyboardController.current + val focusManager = LocalFocusManager.current + + if (screenType == SearchPeopleScreenType.CONVERSATION_DETAILS) { + CompositionLocalProvider(LocalOverscrollConfiguration provides null) { + HorizontalPager( + state = pagerState, + modifier = Modifier + .fillMaxWidth() + ) { pageIndex -> + when (SearchPeopleTabItem.entries[pageIndex]) { + SearchPeopleTabItem.PEOPLE -> { + SearchAllPeopleOrContactsScreen( + searchQuery = userSearchSignal.value, + contactsAddedToGroup = selectedContacts, + onOpenUserProfile = onOpenUserProfile, + onContactChecked = onContactChecked, + isSearchActive = isSearchActive, + ) + } + + SearchPeopleTabItem.SERVICES -> { + SearchAllServicesScreen( + searchQuery = serviceSearchSignal.value, + onServiceClicked = onServiceClicked, + ) + } + } + } + } + } else { + SearchAllPeopleOrContactsScreen( + searchQuery = userSearchSignal.value, + contactsAddedToGroup = selectedContacts, + onContactChecked = onContactChecked, + onOpenUserProfile = onOpenUserProfile, + isSearchActive = isSearchActive, + ) + } + } + BackHandler(enabled = searchBarState.isSearchActive) { + searchBarState.closeSearch() + } + }, + bottomBar = { + if (searchState.isGroupCreationContext) { + SelectParticipantsButtonsAlwaysEnabled( + count = selectedContacts.size, + mainButtonText = actionButtonTitle, + onMainButtonClick = onGroupSelectionSubmitAction + ) + } else { + if (pagerState.currentPage != SearchPeopleTabItem.SERVICES.ordinal) { + SelectParticipantsButtonsRow( + selectedParticipantsCount = selectedContacts.size, + mainButtonText = actionButtonTitle, + onMainButtonClick = onGroupSelectionSubmitAction + ) + } + } + }, + snapOnFling = false, + keepElevationWhenCollapsed = true + ) +} + +enum class SearchPeopleTabItem(@StringRes override val titleResId: Int) : TabItem { + PEOPLE(R.string.label_add_member_people), + SERVICES(R.string.label_add_member_services); +} + +enum class SearchPeopleScreenType { + NEW_CONVERSATION, + CONVERSATION_DETAILS +} + +@Composable +private fun SearchAllPeopleOrContactsScreen( + searchQuery: String, + contactsAddedToGroup: ImmutableSet, + isSearchActive: Boolean, + onOpenUserProfile: (Contact) -> Unit, + onContactChecked: (Boolean, Contact) -> Unit, + searchUserViewModel: SearchUserViewModel = hiltViewModel(), +) { + + LaunchedEffect(key1 = searchQuery) { + searchUserViewModel.search(searchQuery) + } + + val lazyState = rememberLazyListState() + SearchAllPeopleScreen( + searchQuery = searchUserViewModel.state.searchQuery, + contactsSearchResult = searchUserViewModel.state.contactsResult, + publicSearchResult = searchUserViewModel.state.publicResult, + contactsAddedToGroup = contactsAddedToGroup, + onChecked = onContactChecked, + onOpenUserProfile = onOpenUserProfile, + lazyListState = lazyState, + isSearchActive = isSearchActive, + isLoading = searchUserViewModel.state.isLoading, + ) +} 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 31aef8992f5..9934b879c8d 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 @@ -45,8 +45,12 @@ class SearchServicesViewModel @Inject constructor( private val contactMapper: ContactMapper, private val searchServicesByName: SearchServicesByNameUseCase, ) : ViewModel() { +<<<<<<< HEAD private val searchQueryTextFlow = MutableStateFlow(String.EMPTY) var state: SearchServicesState by mutableStateOf(SearchServicesState()) +======= + var state: SearchServicesState by mutableStateOf(SearchServicesState(isLoading = true)) +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private set init { @@ -68,6 +72,7 @@ class SearchServicesViewModel @Inject constructor( private fun search(query: String) { viewModelScope.launch { +<<<<<<< HEAD if (query.isEmpty()) { getAllServices().first().also { services -> state = state.copy(result = services.map(contactMapper::fromService).toImmutableList(), searchQuery = query) @@ -76,14 +81,24 @@ class SearchServicesViewModel @Inject constructor( searchServicesByName(query).first().also { services -> state = state.copy(result = services.map(contactMapper::fromService).toImmutableList(), searchQuery = query) } +======= + val result = if (query.isEmpty()) { + getAllServices().first() + } else { + searchServicesByName(query).first() +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } + state = state.copy(isLoading = false, searchQuery = query, result = result.map(contactMapper::fromService).toImmutableList()) } } } data class SearchServicesState( val result: ImmutableList = persistentListOf(), +<<<<<<< HEAD val searchQuery: String = String.EMPTY, +======= + val searchQuery: String = "", +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) 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 f0d221fd2ac..e7ad49fe531 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 @@ -71,9 +71,13 @@ class SearchUserViewModel @Inject constructor( null } +<<<<<<< HEAD private val searchQueryTextFlow = MutableStateFlow(String.EMPTY) private val selectedContactsFlow = MutableStateFlow>(persistentSetOf()) var state: SearchUserState by mutableStateOf(SearchUserState()) +======= + var state: SearchUserState by mutableStateOf(SearchUserState(isLoading = true)) +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private set init { @@ -165,20 +169,49 @@ class SearchUserViewModel @Inject constructor( searchTerm, excludingConversation = addMembersSearchNavArgs?.conversationId, customDomain = domain +<<<<<<< HEAD ) +======= + ).also { userSearchEntities -> + state = state.copy( + isLoading = false, + searchQuery = searchTerm, + contactsResult = userSearchEntities.connected.map(contactMapper::fromSearchUserResult).toImmutableList(), + publicResult = userSearchEntities.notConnected.map(contactMapper::fromSearchUserResult).toImmutableList() + ) + } + } +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private suspend fun searchByName(searchTerm: String, domain: String?): SearchUserResult = searchUserUseCase( searchTerm, excludingMembersOfConversation = addMembersSearchNavArgs?.conversationId, customDomain = domain +<<<<<<< HEAD ) +======= + ).also { userSearchEntities -> + state = state.copy( + isLoading = false, + searchQuery = searchTerm, + contactsResult = userSearchEntities.connected.map(contactMapper::fromSearchUserResult).toImmutableList(), + publicResult = userSearchEntities.notConnected.map(contactMapper::fromSearchUserResult).toImmutableList() + ) + } + } +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } data class SearchUserState( val contactsResult: ImmutableList = persistentListOf(), val publicResult: ImmutableList = persistentListOf(), +<<<<<<< HEAD val selectedResult: ImmutableList = persistentListOf(), val searchQuery: String = String.EMPTY, val isOtherDomainAllowed: Boolean = false +======= + val searchQuery: String = "", + val isLoading: Boolean = false, +>>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) ) 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) } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt new file mode 100644 index 00000000000..64817283d6c --- /dev/null +++ b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt @@ -0,0 +1,58 @@ +/* + * Wire + * Copyright (C) 2023 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +package com.wire.android.ui.home.newconversation + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.wire.android.appLogger +import com.wire.kalium.logger.obfuscateId +import com.wire.kalium.logic.data.user.UserId +import com.wire.kalium.logic.feature.connection.SendConnectionRequestResult +import com.wire.kalium.logic.feature.connection.SendConnectionRequestUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.async +import javax.inject.Inject + +interface SendConnectionRequestViewModel { + fun addContact(userId: UserId): Deferred +} + +object SendConnectionRequestViewModelPreview : SendConnectionRequestViewModel { + override fun addContact(userId: UserId): Deferred = TODO() +} + +@HiltViewModel +class SendConnectionRequestViewModelImpl @Inject constructor( + private val sendConnectionRequest: SendConnectionRequestUseCase, +) : ViewModel(), SendConnectionRequestViewModel { + + override fun addContact(userId: UserId): Deferred = + viewModelScope.async { + when (sendConnectionRequest(userId)) { + is SendConnectionRequestResult.Success -> { + true + } + + is SendConnectionRequestResult.Failure -> { + appLogger.d(("Couldn't send a connect request to user ${userId.value.obfuscateId()}")) + false + } + } + } +} From 5bedbb2b4584ef7bac2ef8a5d9535f8dbc9b02c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Saleniuk?= Date: Thu, 7 Nov 2024 14:36:49 +0100 Subject: [PATCH 2/3] conflicts resolved --- .../search/SearchAllPeopleScreen.kt | 232 ++-------------- .../search/SearchAllServicesScreen.kt | 9 +- .../search/SearchPeopleRouter.kt | 253 ------------------ .../search/SearchServicesViewModel.kt | 19 -- .../search/SearchUserViewModel.kt | 37 +-- .../search/SearchUsersAndServicesScreen.kt | 4 +- .../SendConnectionRequestViewModel.kt | 58 ---- 7 files changed, 31 insertions(+), 581 deletions(-) delete mode 100644 app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt delete mode 100644 app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt 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 db67224eb03..7f4d4676784 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 @@ -37,36 +37,20 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalInspectionMode import androidx.compose.ui.res.stringResource -<<<<<<< HEAD -import androidx.compose.ui.unit.dp -======= -import androidx.hilt.navigation.compose.hiltViewModel ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) 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 -<<<<<<< HEAD -import com.wire.android.ui.common.progress.WireCircularProgressIndicator -import com.wire.android.ui.home.conversationslist.model.Membership -======= import com.wire.android.ui.common.progress.CenteredCircularProgressBarIndicator -import com.wire.android.ui.common.snackbar.LocalSnackbarHostState 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.SendConnectionRequestViewModel -import com.wire.android.ui.home.newconversation.SendConnectionRequestViewModelImpl -import com.wire.android.ui.home.newconversation.SendConnectionRequestViewModelPreview ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) import com.wire.android.ui.home.newconversation.model.Contact import com.wire.android.ui.theme.WireTheme import com.wire.android.util.extension.FolderType import com.wire.android.util.extension.folderWithElements import com.wire.android.util.ui.PreviewMultipleThemes -<<<<<<< HEAD import com.wire.android.util.ui.keepOnTopWhenNotScrolled import com.wire.kalium.logic.data.user.ConnectionState import com.wire.kalium.logic.data.user.UserId @@ -74,16 +58,6 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.collections.immutable.toPersistentList -======= -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.coroutines.launch ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private const val DEFAULT_SEARCH_RESULT_ITEM_SIZE = 4 @@ -106,16 +80,6 @@ fun SearchAllPeopleScreen( onPublicResultsExpansionChanged: (Boolean) -> Unit = {}, lazyListState: LazyListState = rememberLazyListState() ) { -<<<<<<< HEAD - if (contactsSearchResult.isEmpty() && publicSearchResult.isEmpty()) { - EmptySearchQueryScreen() - } else { - SearchResult( - searchQuery = searchQuery, - publicSearchResult = publicSearchResult, - contactsSearchResult = contactsSearchResult, - contactsSelectedSearchResult = contactsSelectedSearchResult, -======= val emptyResults = contactsSearchResult.isEmpty() && publicSearchResult.isEmpty() when { isLoading -> CenteredCircularProgressBarIndicator() @@ -128,14 +92,11 @@ fun SearchAllPeopleScreen( searchQuery = searchQuery, publicSearchResult = publicSearchResult, contactsSearchResult = contactsSearchResult, - contactsAddedToGroup = contactsAddedToGroup, ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) + contactsSelectedSearchResult = contactsSelectedSearchResult, onChecked = onChecked, onOpenUserProfile = onOpenUserProfile, lazyListState = lazyListState, isSearchActive = isSearchActive, -<<<<<<< HEAD - isLoading = isLoading, actionType = actionType, selectedContactResultsExpanded = selectedContactResultsExpanded, onSelectedContactResultsExpansionChanged = onSelectedContactResultsExpansionChanged, @@ -143,8 +104,6 @@ fun SearchAllPeopleScreen( onContactResultsExpansionChanged = onContactResultsExpansionChanged, publicResultsExpanded = publicResultsExpanded, onPublicResultsExpansionChanged = onPublicResultsExpansionChanged, -======= ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) ) } } @@ -154,27 +113,17 @@ private fun SearchResult( searchQuery: String, contactsSearchResult: ImmutableList, publicSearchResult: ImmutableList, -<<<<<<< HEAD contactsSelectedSearchResult: ImmutableList, - isLoading: Boolean, -======= ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) isSearchActive: Boolean, actionType: ItemActionType, onChecked: (Boolean, Contact) -> Unit, onOpenUserProfile: (Contact) -> Unit, -<<<<<<< HEAD selectedContactResultsExpanded: Boolean, onSelectedContactResultsExpansionChanged: (Boolean) -> Unit, contactResultsExpanded: Boolean, onContactResultsExpansionChanged: (Boolean) -> Unit, publicResultsExpanded: Boolean, onPublicResultsExpansionChanged: (Boolean) -> Unit, -======= - sendConnectionRequestViewModel: SendConnectionRequestViewModel = - if (LocalInspectionMode.current) SendConnectionRequestViewModelPreview - else hiltViewModel(), ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) lazyListState: LazyListState = rememberLazyListState() ) { val searchPeopleScreenState = rememberSearchPeopleScreenState() @@ -192,16 +141,9 @@ private fun SearchResult( searchTitle = context.getString(R.string.label_selected) + " (${contactsSelectedSearchResult.size})", searchQuery = searchQuery, onChecked = onChecked, -<<<<<<< HEAD - isLoading = isLoading, - contactSearchResult = contactsSelectedSearchResult.map { it to true }.toImmutableList(), + searchResult = contactsSelectedSearchResult.map { it to true }.toImmutableList(), allItemsVisible = true, // for selected contacts we always show all items showMoreOrLessButtonVisible = false, -======= - searchResult = contactsSearchResult, - contactsAddedToGroup = contactsAddedToGroup, - showAllItems = !isSearchActive || searchPeopleScreenState.contactsAllResultsCollapsed, ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) onShowAllButtonClicked = searchPeopleScreenState::toggleShowAllContactsResult, onOpenUserProfile = onOpenUserProfile, actionType = actionType, @@ -215,8 +157,7 @@ private fun SearchResult( searchTitle = context.getString(R.string.label_contacts), searchQuery = searchQuery, onChecked = onChecked, - isLoading = isLoading, - contactSearchResult = contactsSearchResult.map { it to false }.toImmutableList(), + searchResult = contactsSearchResult.map { it to false }.toImmutableList(), allItemsVisible = !isSearchActive || searchPeopleScreenState.contactsAllResultsCollapsed, showMoreOrLessButtonVisible = isSearchActive, onShowAllButtonClicked = searchPeopleScreenState::toggleShowAllContactsResult, @@ -231,15 +172,9 @@ private fun SearchResult( externalSearchResults( searchTitle = context.getString(R.string.label_public_wire), searchQuery = searchQuery, -<<<<<<< HEAD - contactSearchResult = publicSearchResult, - isLoading = isLoading, + searchResult = publicSearchResult, allItemsVisible = searchPeopleScreenState.publicResultsCollapsed, showMoreOrLessButtonVisible = isSearchActive, -======= - searchResult = publicSearchResult, - showAllItems = searchPeopleScreenState.publicResultsCollapsed, ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) onShowAllButtonClicked = searchPeopleScreenState::toggleShowAllPublicResult, onOpenUserProfile = onOpenUserProfile, expanded = publicResultsExpanded, @@ -257,86 +192,9 @@ private fun SearchResult( @Suppress("LongParameterList") private fun LazyListScope.internalSearchResults( searchTitle: String, -<<<<<<< HEAD - searchQuery: String, - onChecked: (Boolean, Contact) -> Unit, - actionType: ItemActionType, - isLoading: Boolean, - contactSearchResult: ImmutableList>, - allItemsVisible: Boolean, - showMoreOrLessButtonVisible: Boolean, - onShowAllButtonClicked: () -> Unit, - onOpenUserProfile: (Contact) -> Unit, - expanded: Boolean, - onExpansionChanged: (Boolean) -> Unit, -) { - when { - isLoading -> { - inProgressItem() - } - - else -> { - internalSuccessItem( - searchTitle = searchTitle, - allItemsVisible = allItemsVisible, - showMoreOrLessButtonVisible = showMoreOrLessButtonVisible, - onChecked = onChecked, - searchResult = contactSearchResult, - searchQuery = searchQuery, - onShowAllButtonClicked = onShowAllButtonClicked, - onOpenUserProfile = onOpenUserProfile, - actionType = actionType, - expanded = expanded, - onExpansionChanged = onExpansionChanged, - ) - } - } -} - -@Suppress("LongParameterList") -private fun LazyListScope.externalSearchResults( - searchTitle: String, - searchQuery: String, - contactSearchResult: ImmutableList, - isLoading: Boolean, - allItemsVisible: Boolean, - showMoreOrLessButtonVisible: Boolean, - onShowAllButtonClicked: () -> Unit, - onOpenUserProfile: (Contact) -> Unit, - expanded: Boolean, - onExpansionChanged: (Boolean) -> Unit, -) { - when { - isLoading -> { - inProgressItem() - } - - else -> { - externalSuccessItem( - searchTitle = searchTitle, - allItemsVisible = allItemsVisible, - showMoreOrLessButtonVisible = showMoreOrLessButtonVisible, - searchResult = contactSearchResult, - searchQuery = searchQuery, - onShowAllButtonClicked = onShowAllButtonClicked, - onOpenUserProfile = onOpenUserProfile, - expanded = expanded, - onExpansionChanged = onExpansionChanged, - ) - } - } -} - -@Suppress("LongParameterList") -private fun LazyListScope.internalSuccessItem( - searchTitle: String, allItemsVisible: Boolean, showMoreOrLessButtonVisible: Boolean, actionType: ItemActionType, -======= - showAllItems: Boolean, - contactsAddedToGroup: ImmutableSet, ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) onChecked: (Boolean, Contact) -> Unit, searchResult: ImmutableList>, searchQuery: String, @@ -451,26 +309,6 @@ private fun LazyListScope.externalSearchResults( } } -<<<<<<< HEAD -fun LazyListScope.inProgressItem() { - item { - Box( - Modifier - .fillMaxWidth() - .height(224.dp) - ) { - WireCircularProgressIndicator( - progressColor = Color.Black, - modifier = Modifier.align( - Alignment.Center - ) - ) - } - } -} - -======= ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) @Composable private fun ShowButton( isShownAll: Boolean, @@ -501,7 +339,6 @@ fun PreviewShowButton() { @PreviewMultipleThemes @Composable fun PreviewSearchAllPeopleScreen_Loading() = WireTheme { -<<<<<<< HEAD SearchAllPeopleScreen( searchQuery = "Search query", contactsSearchResult = persistentListOf(), @@ -513,18 +350,15 @@ fun PreviewSearchAllPeopleScreen_Loading() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) -======= - SearchAllPeopleScreen("Search query", persistentListOf(), persistentListOf(), persistentSetOf(), true, false, { _, _ -> }, {}) ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable -<<<<<<< HEAD -fun PreviewSearchAllPeopleScreen_EmptyList() = WireTheme { +fun PreviewSearchAllPeopleScreen_InitialResults() = WireTheme { + val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true) SearchAllPeopleScreen( - searchQuery = "Search query", - contactsSearchResult = persistentListOf(), + searchQuery = "", + contactsSearchResult = contacts, publicSearchResult = persistentListOf(), contactsSelectedSearchResult = persistentListOf(), isLoading = false, @@ -533,21 +367,14 @@ fun PreviewSearchAllPeopleScreen_EmptyList() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) -======= -fun PreviewSearchAllPeopleScreen_InitialResults() = WireTheme { - val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true).toPersistentList() - SearchAllPeopleScreen("", contacts, persistentListOf(), persistentSetOf(), false, false, { _, _ -> }, {}) ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable -<<<<<<< HEAD -fun PreviewSearchAllPeopleScreen_NoSearch() = WireTheme { - val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true) +fun PreviewSearchAllPeopleScreen_EmptyInitialResults() = WireTheme { SearchAllPeopleScreen( searchQuery = "", - contactsSearchResult = contacts, + contactsSearchResult = persistentListOf(), publicSearchResult = persistentListOf(), contactsSelectedSearchResult = persistentListOf(), isLoading = false, @@ -556,15 +383,10 @@ fun PreviewSearchAllPeopleScreen_NoSearch() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) -======= -fun PreviewSearchAllPeopleScreen_EmptyInitialResults() = WireTheme { - SearchAllPeopleScreen("", persistentListOf(), persistentListOf(), persistentSetOf(), false, false, { _, _ -> }, {}) ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable -<<<<<<< HEAD fun PreviewSearchAllPeopleScreen_SearchResults_TypeClick() = WireTheme { val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true) val public = previewContactsList(count = 10, startIndex = 10, isContact = false) @@ -579,17 +401,10 @@ fun PreviewSearchAllPeopleScreen_SearchResults_TypeClick() = WireTheme { onChecked = { _, _ -> }, onOpenUserProfile = { }, ) -======= -fun PreviewSearchAllPeopleScreen_SearchResults() = WireTheme { - val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true).toPersistentList() - val public = previewContactsList(count = 10, startIndex = 10, isContact = false).toPersistentList() - SearchAllPeopleScreen("Con", contacts, public, persistentSetOf(), false, true, { _, _ -> }, {}) ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } @PreviewMultipleThemes @Composable -<<<<<<< HEAD fun PreviewSearchAllPeopleScreen_SearchResults_TypeCheck() = WireTheme { val contacts = previewContactsList(count = 10, startIndex = 0, isContact = true) val public = previewContactsList(count = 10, startIndex = 10, isContact = false) @@ -606,29 +421,34 @@ fun PreviewSearchAllPeopleScreen_SearchResults_TypeCheck() = WireTheme { onOpenUserProfile = { }, selectedContactResultsExpanded = true, ) -======= +} + +@PreviewMultipleThemes +@Composable fun PreviewSearchAllPeopleScreen_EmptySearchResults() = WireTheme { - SearchAllPeopleScreen("Con", persistentListOf(), persistentListOf(), persistentSetOf(), false, true, { _, _ -> }, {}) ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) + SearchAllPeopleScreen( + searchQuery = "Con", + contactsSearchResult = persistentListOf(), + publicSearchResult = persistentListOf(), + contactsSelectedSearchResult = persistentListOf(), + isLoading = false, + isSearchActive = true, + actionType = ItemActionType.CLICK, + onChecked = { _, _ -> }, + onOpenUserProfile = {}, + selectedContactResultsExpanded = true, + ) } private fun previewContact(index: Int, isContact: Boolean) = Contact( id = index.toString(), domain = "wire.com", name = "Contact nr $index", -<<<<<<< HEAD handle = "contact_$index", -======= ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) connectionState = if (isContact) ConnectionState.ACCEPTED else ConnectionState.NOT_CONNECTED, membership = Membership.Standard, ) -<<<<<<< HEAD private fun previewContactsList(count: Int, startIndex: Int = 0, isContact: Boolean): ImmutableList = buildList { repeat(count) { index -> add(previewContact(startIndex + index, isContact)) } }.toPersistentList() -======= -private fun previewContactsList(count: Int, startIndex: Int = 0, isContact: Boolean): List = - buildList { repeat(count) { index -> add(previewContact(startIndex + index, isContact)) } } ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) 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 741702d0303..3457992a7f6 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 @@ -41,13 +41,10 @@ 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 -<<<<<<< HEAD import com.wire.android.util.extension.folderWithElements -======= import com.wire.android.ui.theme.WireTheme import com.wire.android.util.ui.PreviewMultipleThemes import com.wire.kalium.logic.data.user.ConnectionState ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList @@ -67,12 +64,7 @@ fun SearchAllServicesScreen( searchQuery = searchServicesViewModel.state.searchQuery, onServiceClicked = onServiceClicked, result = searchServicesViewModel.state.result, -<<<<<<< HEAD lazyListState = lazyListState, - error = searchServicesViewModel.state.error, -======= - lazyListState = lazyState, ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) isLoading = searchServicesViewModel.state.isLoading ) } @@ -185,6 +177,7 @@ private fun previewService(index: Int) = Contact( id = index.toString(), domain = "wire.com", name = "Service nr $index", + handle = "service_$index", connectionState = ConnectionState.NOT_CONNECTED, membership = Membership.Service, ) 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 deleted file mode 100644 index da91a870c5c..00000000000 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchPeopleRouter.kt +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Wire - * Copyright (C) 2024 Wire Swiss GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - */ - -package com.wire.android.ui.home.conversations.search - -import androidx.activity.compose.BackHandler -import androidx.annotation.StringRes -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.Crossfade -import androidx.compose.animation.expandVertically -import androidx.compose.animation.shrinkVertically -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.LocalOverscrollConfiguration -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.pager.HorizontalPager -import androidx.compose.foundation.pager.rememberPagerState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.ExperimentalComposeUiApi -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.input.TextFieldValue -import androidx.hilt.navigation.compose.hiltViewModel -import com.wire.android.R -import com.wire.android.ui.common.CollapsingTopBarScaffold -import com.wire.android.ui.common.TabItem -import com.wire.android.ui.common.WireTabRow -import com.wire.android.ui.common.calculateCurrentTab -import com.wire.android.ui.common.topappbar.NavigationIconType -import com.wire.android.ui.common.topappbar.WireCenterAlignedTopAppBar -import com.wire.android.ui.common.topappbar.search.SearchTopBar -import com.wire.android.ui.common.topappbar.search.rememberSearchbarState -import com.wire.android.ui.home.newconversation.common.SelectParticipantsButtonsAlwaysEnabled -import com.wire.android.ui.home.newconversation.common.SelectParticipantsButtonsRow -import com.wire.android.ui.home.newconversation.model.Contact -import kotlinx.collections.immutable.ImmutableSet -import kotlinx.coroutines.launch - -@Suppress("ComplexMethod") -@OptIn( - ExperimentalComposeUiApi::class, - ExperimentalFoundationApi::class -) -@Composable -fun SearchUsersAndServicesScreen( - searchState: SearchState, - searchTitle: String, - actionButtonTitle: String, - userSearchSignal: State, - serviceSearchSignal: State, - selectedContacts: ImmutableSet, - onServicesSearchQueryChanged: (TextFieldValue) -> Unit, - onUsersSearchQueryChanged: (TextFieldValue) -> Unit, - onGroupSelectionSubmitAction: () -> Unit, - onContactChecked: (Boolean, Contact) -> Unit, - onOpenUserProfile: (Contact) -> Unit, - onServiceClicked: (Contact) -> Unit, - onClose: () -> Unit, - screenType: SearchPeopleScreenType -) { - val searchBarState = rememberSearchbarState() - val scope = rememberCoroutineScope() - val initialPageIndex = SearchPeopleTabItem.PEOPLE.ordinal - val pagerState = rememberPagerState( - initialPage = initialPageIndex, - pageCount = { if (searchState.isServicesAllowed) SearchPeopleTabItem.entries.size else 1 }) - val currentTabState by remember { derivedStateOf { pagerState.calculateCurrentTab() } } - - CollapsingTopBarScaffold( - topBarHeader = { elevation -> - AnimatedVisibility( - visible = !searchBarState.isSearchActive, - enter = expandVertically(), - exit = shrinkVertically(), - ) { - Box(modifier = Modifier.wrapContentSize()) { - WireCenterAlignedTopAppBar( - elevation = elevation, - title = searchTitle, - navigationIconType = NavigationIconType.Close, - onNavigationPressed = onClose - ) - } - } - }, - topBarCollapsing = { - val query = when (currentTabState) { - SearchPeopleTabItem.PEOPLE.ordinal -> searchState.userSearchQuery - SearchPeopleTabItem.SERVICES.ordinal -> searchState.serviceSearchQuery - else -> error("Unknown tab index $currentTabState") - } - - val onQueryChanged: (TextFieldValue) -> Unit = when (currentTabState) { - SearchPeopleTabItem.PEOPLE.ordinal -> onUsersSearchQueryChanged - SearchPeopleTabItem.SERVICES.ordinal -> onServicesSearchQueryChanged - else -> error("Unknown tab index $currentTabState") - } - - SearchTopBar( - isSearchActive = searchBarState.isSearchActive, - searchBarHint = stringResource(R.string.label_search_people), - searchQuery = query, - onSearchQueryChanged = onQueryChanged, - onActiveChanged = searchBarState::searchActiveChanged, - ) { - if (screenType == SearchPeopleScreenType.CONVERSATION_DETAILS - && searchState.isServicesAllowed - ) { - WireTabRow( - tabs = SearchPeopleTabItem.entries, - selectedTabIndex = currentTabState, - onTabChange = { scope.launch { pagerState.animateScrollToPage(it) } }, - divider = {} // no divider - ) - } - } - }, - content = { - Crossfade( - targetState = searchBarState.isSearchActive, label = "" - ) { isSearchActive -> - var focusedTabIndex: Int by remember { mutableStateOf(initialPageIndex) } - val keyboardController = LocalSoftwareKeyboardController.current - val focusManager = LocalFocusManager.current - - if (screenType == SearchPeopleScreenType.CONVERSATION_DETAILS) { - CompositionLocalProvider(LocalOverscrollConfiguration provides null) { - HorizontalPager( - state = pagerState, - modifier = Modifier - .fillMaxWidth() - ) { pageIndex -> - when (SearchPeopleTabItem.entries[pageIndex]) { - SearchPeopleTabItem.PEOPLE -> { - SearchAllPeopleOrContactsScreen( - searchQuery = userSearchSignal.value, - contactsAddedToGroup = selectedContacts, - onOpenUserProfile = onOpenUserProfile, - onContactChecked = onContactChecked, - isSearchActive = isSearchActive, - ) - } - - SearchPeopleTabItem.SERVICES -> { - SearchAllServicesScreen( - searchQuery = serviceSearchSignal.value, - onServiceClicked = onServiceClicked, - ) - } - } - } - } - } else { - SearchAllPeopleOrContactsScreen( - searchQuery = userSearchSignal.value, - contactsAddedToGroup = selectedContacts, - onContactChecked = onContactChecked, - onOpenUserProfile = onOpenUserProfile, - isSearchActive = isSearchActive, - ) - } - } - BackHandler(enabled = searchBarState.isSearchActive) { - searchBarState.closeSearch() - } - }, - bottomBar = { - if (searchState.isGroupCreationContext) { - SelectParticipantsButtonsAlwaysEnabled( - count = selectedContacts.size, - mainButtonText = actionButtonTitle, - onMainButtonClick = onGroupSelectionSubmitAction - ) - } else { - if (pagerState.currentPage != SearchPeopleTabItem.SERVICES.ordinal) { - SelectParticipantsButtonsRow( - selectedParticipantsCount = selectedContacts.size, - mainButtonText = actionButtonTitle, - onMainButtonClick = onGroupSelectionSubmitAction - ) - } - } - }, - snapOnFling = false, - keepElevationWhenCollapsed = true - ) -} - -enum class SearchPeopleTabItem(@StringRes override val titleResId: Int) : TabItem { - PEOPLE(R.string.label_add_member_people), - SERVICES(R.string.label_add_member_services); -} - -enum class SearchPeopleScreenType { - NEW_CONVERSATION, - CONVERSATION_DETAILS -} - -@Composable -private fun SearchAllPeopleOrContactsScreen( - searchQuery: String, - contactsAddedToGroup: ImmutableSet, - isSearchActive: Boolean, - onOpenUserProfile: (Contact) -> Unit, - onContactChecked: (Boolean, Contact) -> Unit, - searchUserViewModel: SearchUserViewModel = hiltViewModel(), -) { - - LaunchedEffect(key1 = searchQuery) { - searchUserViewModel.search(searchQuery) - } - - val lazyState = rememberLazyListState() - SearchAllPeopleScreen( - searchQuery = searchUserViewModel.state.searchQuery, - contactsSearchResult = searchUserViewModel.state.contactsResult, - publicSearchResult = searchUserViewModel.state.publicResult, - contactsAddedToGroup = contactsAddedToGroup, - onChecked = onContactChecked, - onOpenUserProfile = onOpenUserProfile, - lazyListState = lazyState, - isSearchActive = isSearchActive, - isLoading = searchUserViewModel.state.isLoading, - ) -} 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 9934b879c8d..16b345f61ad 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 @@ -45,12 +45,8 @@ class SearchServicesViewModel @Inject constructor( private val contactMapper: ContactMapper, private val searchServicesByName: SearchServicesByNameUseCase, ) : ViewModel() { -<<<<<<< HEAD private val searchQueryTextFlow = MutableStateFlow(String.EMPTY) - var state: SearchServicesState by mutableStateOf(SearchServicesState()) -======= var state: SearchServicesState by mutableStateOf(SearchServicesState(isLoading = true)) ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private set init { @@ -72,21 +68,10 @@ class SearchServicesViewModel @Inject constructor( private fun search(query: String) { viewModelScope.launch { -<<<<<<< HEAD - if (query.isEmpty()) { - getAllServices().first().also { services -> - state = state.copy(result = services.map(contactMapper::fromService).toImmutableList(), searchQuery = query) - } - } else { - searchServicesByName(query).first().also { services -> - state = state.copy(result = services.map(contactMapper::fromService).toImmutableList(), searchQuery = query) - } -======= val result = if (query.isEmpty()) { getAllServices().first() } else { searchServicesByName(query).first() ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } state = state.copy(isLoading = false, searchQuery = query, result = result.map(contactMapper::fromService).toImmutableList()) } @@ -95,10 +80,6 @@ class SearchServicesViewModel @Inject constructor( data class SearchServicesState( val result: ImmutableList = persistentListOf(), -<<<<<<< HEAD val searchQuery: String = String.EMPTY, -======= - val searchQuery: String = "", ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) val isLoading: 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 e7ad49fe531..d40a68298d4 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 @@ -71,13 +71,9 @@ class SearchUserViewModel @Inject constructor( null } -<<<<<<< HEAD private val searchQueryTextFlow = MutableStateFlow(String.EMPTY) private val selectedContactsFlow = MutableStateFlow>(persistentSetOf()) - var state: SearchUserState by mutableStateOf(SearchUserState()) -======= var state: SearchUserState by mutableStateOf(SearchUserState(isLoading = true)) ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private set init { @@ -118,7 +114,8 @@ class SearchUserViewModel @Inject constructor( contactsResult = newState.contactsResult, publicResult = newState.publicResult, selectedResult = newState.selectedResult, - searchQuery = newState.searchQuery + searchQuery = newState.searchQuery, + isLoading = false, ) } } @@ -169,49 +166,21 @@ class SearchUserViewModel @Inject constructor( searchTerm, excludingConversation = addMembersSearchNavArgs?.conversationId, customDomain = domain -<<<<<<< HEAD ) -======= - ).also { userSearchEntities -> - state = state.copy( - isLoading = false, - searchQuery = searchTerm, - contactsResult = userSearchEntities.connected.map(contactMapper::fromSearchUserResult).toImmutableList(), - publicResult = userSearchEntities.notConnected.map(contactMapper::fromSearchUserResult).toImmutableList() - ) - } - } ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) private suspend fun searchByName(searchTerm: String, domain: String?): SearchUserResult = searchUserUseCase( searchTerm, excludingMembersOfConversation = addMembersSearchNavArgs?.conversationId, customDomain = domain -<<<<<<< HEAD ) -======= - ).also { userSearchEntities -> - state = state.copy( - isLoading = false, - searchQuery = searchTerm, - contactsResult = userSearchEntities.connected.map(contactMapper::fromSearchUserResult).toImmutableList(), - publicResult = userSearchEntities.notConnected.map(contactMapper::fromSearchUserResult).toImmutableList() - ) - } - } ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) } data class SearchUserState( val contactsResult: ImmutableList = persistentListOf(), val publicResult: ImmutableList = persistentListOf(), -<<<<<<< HEAD val selectedResult: ImmutableList = persistentListOf(), val searchQuery: String = String.EMPTY, - val isOtherDomainAllowed: Boolean = false -======= - val searchQuery: String = "", + val isOtherDomainAllowed: Boolean = false, val isLoading: Boolean = false, ->>>>>>> 0b3dc07e6 (fix: show proper empty user search screens [WPB-6257] (#3589)) ) diff --git a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt index 4223f71d9b7..ff3801d6bf9 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/conversations/search/SearchUsersAndServicesScreen.kt @@ -166,7 +166,6 @@ fun SearchUsersAndServicesScreen( onOpenUserProfile = onOpenUserProfile, onContactChecked = onContactChecked, isSearchActive = searchBarState.isSearchActive, - isLoading = false, // TODO: update correctly actionType = actionType, lazyListState = lazyListStates[pageIndex], ) @@ -237,7 +236,6 @@ enum class SearchPeopleScreenType { private fun SearchAllPeopleOrContactsScreen( searchQuery: String, contactsSelected: ImmutableSet, - isLoading: Boolean, isSearchActive: Boolean, actionType: ItemActionType, onOpenUserProfile: (Contact) -> Unit, @@ -270,7 +268,7 @@ private fun SearchAllPeopleOrContactsScreen( onOpenUserProfile = onOpenUserProfile, lazyListState = lazyListState, isSearchActive = isSearchActive, - isLoading = isLoading, + isLoading = searchUserViewModel.state.isLoading, actionType = actionType, selectedContactResultsExpanded = selectedContactResultsExpanded, onSelectedContactResultsExpansionChanged = remember { { selectedContactResultsExpanded = it } }, diff --git a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt b/app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt deleted file mode 100644 index 64817283d6c..00000000000 --- a/app/src/main/kotlin/com/wire/android/ui/home/newconversation/SendConnectionRequestViewModel.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Wire - * Copyright (C) 2023 Wire Swiss GmbH - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see http://www.gnu.org/licenses/. - */ -package com.wire.android.ui.home.newconversation - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.wire.android.appLogger -import com.wire.kalium.logger.obfuscateId -import com.wire.kalium.logic.data.user.UserId -import com.wire.kalium.logic.feature.connection.SendConnectionRequestResult -import com.wire.kalium.logic.feature.connection.SendConnectionRequestUseCase -import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.async -import javax.inject.Inject - -interface SendConnectionRequestViewModel { - fun addContact(userId: UserId): Deferred -} - -object SendConnectionRequestViewModelPreview : SendConnectionRequestViewModel { - override fun addContact(userId: UserId): Deferred = TODO() -} - -@HiltViewModel -class SendConnectionRequestViewModelImpl @Inject constructor( - private val sendConnectionRequest: SendConnectionRequestUseCase, -) : ViewModel(), SendConnectionRequestViewModel { - - override fun addContact(userId: UserId): Deferred = - viewModelScope.async { - when (sendConnectionRequest(userId)) { - is SendConnectionRequestResult.Success -> { - true - } - - is SendConnectionRequestResult.Failure -> { - appLogger.d(("Couldn't send a connect request to user ${userId.value.obfuscateId()}")) - false - } - } - } -} From cde1b27e0e1fb55ac83fc6dbbdada9d593214c28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Saleniuk?= Date: Thu, 7 Nov 2024 14:56:29 +0100 Subject: [PATCH 3/3] detekt --- .../ui/home/conversations/search/SearchAllServicesScreen.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 3457992a7f6..1c7221ac7aa 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 @@ -182,4 +182,6 @@ private fun previewService(index: Int) = Contact( membership = Membership.Service, ) -private fun previewServiceList(count: Int): List = buildList { repeat(count) { index -> add(previewService(index)) } } +private fun previewServiceList(count: Int): List = buildList { + repeat(count) { index -> add(previewService(index)) } +}