From 9cd342ceb459e5aae251c5818c7fa28475c911f4 Mon Sep 17 00:00:00 2001 From: Jonatan Rhodin Date: Tue, 8 Oct 2024 16:36:53 +0200 Subject: [PATCH] Implement multihop --- android/CHANGELOG.md | 2 + .../compose/screen/ConnectScreenTest.kt | 1 + .../screen/CustomListLocationsScreenTest.kt | 7 +- .../compose/screen/SettingsScreenTest.kt | 2 + .../location/SearchLocationScreenTest.kt | 105 ++ .../SelectLocationScreenTest.kt | 183 ++-- .../compose/button/MullvadSegmentedButton.kt | 107 ++ .../mullvadvpn/compose/cell/FilterRow.kt | 47 +- .../compose/cell/RelayLocationCell.kt | 30 +- .../compose/component/LocationsEmptyText.kt | 40 +- .../connectioninfo/FeatureIndicatorsPanel.kt | 1 + .../preview/RelayListItemPreviewData.kt | 113 +++ ...ocationsUiStatePreviewParameterProvider.kt | 29 + ...ocationsUiStatePreviewParameterProvider.kt | 76 +- ...SettingsUiStatePreviewParameterProvider.kt | 2 + .../compose/screen/ConnectScreen.kt | 7 +- .../compose/screen/MultihopScreen.kt | 89 ++ .../compose/screen/SelectLocationScreen.kt | 938 ------------------ .../compose/screen/SettingsScreen.kt | 57 +- .../screen/location/LocationBottomSheet.kt | 426 ++++++++ .../screen/location/RelayListContent.kt | 196 ++++ .../screen/location/SearchLocationScreen.kt | 401 ++++++++ .../screen/location/SelectLocationList.kt | 114 +++ .../screen/location/SelectLocationScreen.kt | 352 +++++++ .../mullvadvpn/compose/state/FilterChip.kt | 1 + .../mullvadvpn/compose/state/RelayListItem.kt | 89 ++ .../mullvadvpn/compose/state/RelayListType.kt | 6 + .../compose/state/SearchLocationUiState.kt | 21 + .../state/SelectLocationListUiState.kt | 13 + .../compose/state/SelectLocationUiState.kt | 105 +- .../compose/state/SettingsUiState.kt | 1 + .../net/mullvad/mullvadvpn/di/UiModule.kt | 39 +- .../relaylist/RelayItemExtensions.kt | 23 +- .../WireguardConstraintsRepository.kt | 20 +- .../mullvadvpn/usecase/FilterChipUseCase.kt | 103 ++ .../usecase/FilteredRelayListUseCase.kt | 24 +- .../usecase/SelectedLocationUseCase.kt | 27 + .../FilterCustomListsRelayItemUseCase.kt | 24 +- .../net/mullvad/mullvadvpn/util/Daita.kt | 12 + .../net/mullvad/mullvadvpn/util/FlowUtils.kt | 25 + .../mullvadvpn/viewmodel/MultihopViewModel.kt | 26 + .../viewmodel/SelectLocationViewModel.kt | 436 -------- .../mullvadvpn/viewmodel/SettingsViewModel.kt | 12 +- .../viewmodel/location/CustomListEdit.kt | 75 ++ .../mullvadvpn/viewmodel/location/Expand.kt | 21 + .../location/RelayItemListCreator.kt | 355 +++++++ .../location/SearchLocationViewModel.kt | 211 ++++ .../location/SelectLocationListViewModel.kt | 89 ++ .../location/SelectLocationViewModel.kt | 145 +++ .../viewmodel/location/SelectRelay.kt | 21 + .../usecase/FilterChipUseCaseTest.kt | 146 +++ .../usecase/SelectedLocationUseCaseTest.kt | 71 ++ .../viewmodel/MultihopViewModelTest.kt | 68 ++ .../viewmodel/SettingsViewModelTest.kt | 26 + .../viewmodel/VpnSettingsViewModelTest.kt | 2 +- .../location/SearchLocationViewModelTest.kt | 161 +++ .../SelectLocationListViewModelTest.kt | 158 +++ .../SelectLocationViewModelTest.kt | 240 ++--- .../lib/daemon/grpc/ManagementService.kt | 22 +- .../lib/daemon/grpc/mapper/FromDomain.kt | 2 +- .../lib/daemon/grpc/mapper/ToDomain.kt | 4 +- .../mullvadvpn/lib/model/FeatureIndicator.kt | 2 +- .../lib/model/RelayItemSelection.kt | 12 + .../lib/model/WireguardConstraints.kt | 2 +- .../drawable-hdpi/multihop_illustration.png | Bin 0 -> 45568 bytes .../drawable-mdpi/multihop_illustration.png | Bin 0 -> 24763 bytes .../drawable-xhdpi/multihop_illustration.png | Bin 0 -> 71127 bytes .../drawable-xxhdpi/multihop_illustration.png | Bin 0 -> 136698 bytes .../multihop_illustration.png | Bin 0 -> 220713 bytes .../src/main/res/values-da/strings.xml | 8 +- .../src/main/res/values-de/strings.xml | 8 +- .../src/main/res/values-es/strings.xml | 8 +- .../src/main/res/values-fi/strings.xml | 8 +- .../src/main/res/values-fr/strings.xml | 8 +- .../src/main/res/values-it/strings.xml | 8 +- .../src/main/res/values-ja/strings.xml | 8 +- .../src/main/res/values-ko/strings.xml | 8 +- .../src/main/res/values-my/strings.xml | 8 +- .../src/main/res/values-nb/strings.xml | 8 +- .../src/main/res/values-nl/strings.xml | 8 +- .../src/main/res/values-pl/strings.xml | 8 +- .../src/main/res/values-pt/strings.xml | 8 +- .../src/main/res/values-ru/strings.xml | 8 +- .../src/main/res/values-sv/strings.xml | 8 +- .../src/main/res/values-th/strings.xml | 8 +- .../src/main/res/values-tr/strings.xml | 8 +- .../src/main/res/values-zh-rCN/strings.xml | 8 +- .../src/main/res/values-zh-rTW/strings.xml | 8 +- .../resource/src/main/res/values/strings.xml | 18 +- .../lib/theme/dimensions/Dimensions.kt | 2 + .../mullvadvpn/lib/theme/shape/Shape.kt | 6 - .../packages/mullvad-vpn/locales/messages.pot | 21 + 92 files changed, 4367 insertions(+), 1997 deletions(-) create mode 100644 android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreenTest.kt rename android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/{ => location}/SelectLocationScreenTest.kt (50%) create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayListItemPreviewData.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsUiStatePreviewParameterProvider.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt delete mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/LocationBottomSheet.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListContent.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationList.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/FilterChip.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListItem.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListType.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SearchLocationUiState.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationListUiState.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCase.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCase.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/Daita.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModel.kt delete mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/CustomListEdit.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/Expand.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/RelayItemListCreator.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModel.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModel.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModel.kt create mode 100644 android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectRelay.kt create mode 100644 android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCaseTest.kt create mode 100644 android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCaseTest.kt create mode 100644 android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModelTest.kt create mode 100644 android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModelTest.kt create mode 100644 android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModelTest.kt rename android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/{ => location}/SelectLocationViewModelTest.kt (52%) create mode 100644 android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItemSelection.kt create mode 100644 android/lib/resource/src/main/res/drawable-hdpi/multihop_illustration.png create mode 100644 android/lib/resource/src/main/res/drawable-mdpi/multihop_illustration.png create mode 100644 android/lib/resource/src/main/res/drawable-xhdpi/multihop_illustration.png create mode 100644 android/lib/resource/src/main/res/drawable-xxhdpi/multihop_illustration.png create mode 100644 android/lib/resource/src/main/res/drawable-xxxhdpi/multihop_illustration.png diff --git a/android/CHANGELOG.md b/android/CHANGELOG.md index ba6f2e925520..008df4241fbf 100644 --- a/android/CHANGELOG.md +++ b/android/CHANGELOG.md @@ -25,6 +25,8 @@ Line wrap the file at 100 chars. Th ### Added - Add a new access method: Encrypted DNS Proxy. Encrypted DNS proxy is a way to reach the API via proxies. The access method is enabled by default. +- Add multihop which allows the routing of traffic through an entry and exit server, making it + harder to trace. ### Changed - Animation has been changed to look better with predictive back. diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt index 1c3342086354..487e73902532 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt @@ -474,6 +474,7 @@ class ConnectScreenTest { val inPort = 99 val inProtocol = TransportProtocol.Udp every { mockLocation.hostname } returns mockHostName + every { mockLocation.entryHostname } returns null // In every { mockTunnelEndpoint.obfuscation } returns null diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreenTest.kt index 444bbd2c5b07..484bb132d68f 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/CustomListLocationsScreenTest.kt @@ -163,9 +163,7 @@ class CustomListLocationsScreenTest { } // Assert - onNodeWithText(EMPTY_SEARCH_FIRST_ROW.format(mockSearchString), substring = true) - .assertExists() - onNodeWithText(EMPTY_SEARCH_SECOND_ROW, substring = true).assertExists() + onNodeWithText(EMPTY_SEARCH.format(mockSearchString)).assertExists() } @Test @@ -239,8 +237,7 @@ class CustomListLocationsScreenTest { const val ADD_LOCATIONS_TEXT = "Add locations" const val EDIT_LOCATIONS_TEXT = "Edit locations" const val SEARCH_PLACEHOLDER = "Search for..." - const val EMPTY_SEARCH_FIRST_ROW = "No result for %s." - const val EMPTY_SEARCH_SECOND_ROW = "Try a different search" + const val EMPTY_SEARCH = "No result for \"%s\", please try a different search" const val NO_LOCATIONS_FOUND_TEXT = "No locations found" } } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt index 2509c7be8d50..e691909a40a0 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreenTest.kt @@ -33,6 +33,7 @@ class SettingsScreenTest { isLoggedIn = true, isSupportedVersion = true, isPlayBuild = false, + multihopEnabled = false, ) ) } @@ -56,6 +57,7 @@ class SettingsScreenTest { isLoggedIn = false, isSupportedVersion = true, isPlayBuild = false, + multihopEnabled = false, ) ) } diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreenTest.kt new file mode 100644 index 000000000000..5901599df9c4 --- /dev/null +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreenTest.kt @@ -0,0 +1,105 @@ +package net.mullvad.mullvadvpn.compose.screen.location + +import androidx.compose.ui.test.ExperimentalTestApi +import androidx.compose.ui.test.onNodeWithTag +import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performTextInput +import io.mockk.MockKAnnotations +import io.mockk.mockk +import io.mockk.unmockkAll +import io.mockk.verify +import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension +import net.mullvad.mullvadvpn.compose.data.DUMMY_RELAY_ITEM_CUSTOM_LISTS +import net.mullvad.mullvadvpn.compose.setContentWithTheme +import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState +import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.RegisterExtension + +@OptIn(ExperimentalTestApi::class) +class SearchLocationScreenTest { + @JvmField @RegisterExtension val composeExtension = createEdgeToEdgeComposeExtension() + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + } + + @AfterEach + fun teardown() { + unmockkAll() + } + + @Test + fun testSearchInput() = + composeExtension.use { + // Arrange + val mockedSearchTermInput: (String) -> Unit = mockk(relaxed = true) + setContentWithTheme { + SearchLocationScreen( + state = + SearchLocationUiState.NoQuery(searchTerm = "", filterChips = emptyList()), + onSearchInputChanged = mockedSearchTermInput, + ) + } + val mockSearchString = "SEARCH" + + // Act + onNodeWithText("Search for...").performTextInput(mockSearchString) + + // Assert + verify { mockedSearchTermInput.invoke(mockSearchString) } + } + + @Test + fun testSearchTermNotFound() = + composeExtension.use { + // Arrange + val mockSearchString = "SEARCH" + setContentWithTheme { + SearchLocationScreen( + state = + SearchLocationUiState.Content( + searchTerm = mockSearchString, + filterChips = emptyList(), + relayListItems = + listOf(RelayListItem.LocationsEmptyText(mockSearchString)), + customLists = emptyList(), + ) + ) + } + + // Assert + onNodeWithText("No result for \"$mockSearchString\", please try a different search") + .assertExists() + } + + @Test + fun givenNoCustomListsAndSearchIsActiveShouldNotShowCustomListHeader() = + composeExtension.use { + // Arrange + val mockSearchString = "SEARCH" + setContentWithTheme { + SearchLocationScreen( + state = + SearchLocationUiState.Content( + searchTerm = mockSearchString, + filterChips = emptyList(), + relayListItems = emptyList(), + customLists = DUMMY_RELAY_ITEM_CUSTOM_LISTS, + ) + ) + } + + // Assert + onNodeWithText(CUSTOM_LISTS_EMPTY_TEXT).assertDoesNotExist() + onNodeWithTag(SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG).assertDoesNotExist() + } + + companion object { + private const val CUSTOM_LISTS_EMPTY_TEXT = "To create a custom list press the \"︙\"" + } +} diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreenTest.kt similarity index 50% rename from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt rename to android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreenTest.kt index 31097725db1c..a154344f2673 100644 --- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreenTest.kt +++ b/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreenTest.kt @@ -1,63 +1,74 @@ -package net.mullvad.mullvadvpn.compose.screen +package net.mullvad.mullvadvpn.compose.screen.location import androidx.compose.ui.test.ExperimentalTestApi import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick -import androidx.compose.ui.test.performTextInput import io.mockk.MockKAnnotations +import io.mockk.every import io.mockk.mockk +import io.mockk.unmockkAll import io.mockk.verify +import kotlinx.coroutines.flow.MutableStateFlow import net.mullvad.mullvadvpn.compose.createEdgeToEdgeComposeExtension import net.mullvad.mullvadvpn.compose.data.DUMMY_RELAY_COUNTRIES import net.mullvad.mullvadvpn.compose.data.DUMMY_RELAY_ITEM_CUSTOM_LISTS import net.mullvad.mullvadvpn.compose.setContentWithTheme import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState -import net.mullvad.mullvadvpn.compose.test.CIRCULAR_PROGRESS_INDICATOR import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_CUSTOM_LIST_BOTTOM_SHEET_TEST_TAG -import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_LOCATION_BOTTOM_SHEET_TEST_TAG import net.mullvad.mullvadvpn.lib.model.RelayItem import net.mullvad.mullvadvpn.performLongClick +import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationListViewModel +import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.RegisterExtension +import org.koin.core.context.loadKoinModules +import org.koin.core.module.dsl.viewModel +import org.koin.dsl.module @OptIn(ExperimentalTestApi::class) class SelectLocationScreenTest { @JvmField @RegisterExtension val composeExtension = createEdgeToEdgeComposeExtension() + private val listViewModel: SelectLocationListViewModel = mockk(relaxed = true) + @BeforeEach fun setup() { MockKAnnotations.init(this) + loadKoinModules(module { viewModel { listViewModel } }) + every { listViewModel.uiState } returns MutableStateFlow(SelectLocationListUiState.Loading) } - @Test - fun testDefaultState() = - composeExtension.use { - // Arrange - setContentWithTheme { SelectLocationScreen(state = SelectLocationUiState.Loading) } - - // Assert - onNodeWithTag(CIRCULAR_PROGRESS_INDICATOR).assertExists() - } + @AfterEach + fun teardown() { + unmockkAll() + } @Test fun testShowRelayListState() = composeExtension.use { // Arrange + every { listViewModel.uiState } returns + MutableStateFlow( + SelectLocationListUiState.Content( + relayListItems = + DUMMY_RELAY_COUNTRIES.map { RelayListItem.GeoLocationItem(item = it) }, + customLists = emptyList(), + ) + ) setContentWithTheme { SelectLocationScreen( state = - SelectLocationUiState.Content( - searchTerm = "", + SelectLocationUiState( + // searchTerm = "", filterChips = emptyList(), - relayListItems = - DUMMY_RELAY_COUNTRIES.map { - RelayListItem.GeoLocationItem(item = it) - }, - customLists = emptyList(), + multihopEnabled = false, + relayListType = RelayListType.EXIT, ) ) } @@ -71,98 +82,30 @@ class SelectLocationScreenTest { onNodeWithText("Relay host 2").assertDoesNotExist() } - @Test - fun testSearchInput() = - composeExtension.use { - // Arrange - val mockedSearchTermInput: (String) -> Unit = mockk(relaxed = true) - setContentWithTheme { - SelectLocationScreen( - state = - SelectLocationUiState.Content( - searchTerm = "", - filterChips = emptyList(), - relayListItems = emptyList(), - customLists = emptyList(), - ), - onSearchTermInput = mockedSearchTermInput, - ) - } - val mockSearchString = "SEARCH" - - // Act - onNodeWithText("Search for...").performTextInput(mockSearchString) - - // Assert - verify { mockedSearchTermInput.invoke(mockSearchString) } - } - - @Test - fun testSearchTermNotFound() = - composeExtension.use { - // Arrange - val mockedSearchTermInput: (String) -> Unit = mockk(relaxed = true) - val mockSearchString = "SEARCH" - setContentWithTheme { - SelectLocationScreen( - state = - SelectLocationUiState.Content( - searchTerm = mockSearchString, - filterChips = emptyList(), - relayListItems = - listOf(RelayListItem.LocationsEmptyText(mockSearchString)), - customLists = emptyList(), - ), - onSearchTermInput = mockedSearchTermInput, - ) - } - - // Assert - onNodeWithText("No result for $mockSearchString.", substring = true).assertExists() - onNodeWithText("Try a different search", substring = true).assertExists() - } - @Test fun customListFooterShouldShowEmptyTextWhenNoCustomList() = composeExtension.use { // Arrange - val mockSearchString = "" - setContentWithTheme { - SelectLocationScreen( - state = - SelectLocationUiState.Content( - searchTerm = mockSearchString, - filterChips = emptyList(), - relayListItems = listOf(RelayListItem.CustomListFooter(false)), - customLists = emptyList(), - ) + every { listViewModel.uiState } returns + MutableStateFlow( + SelectLocationListUiState.Content( + relayListItems = listOf(RelayListItem.CustomListFooter(false)), + customLists = emptyList(), + ) ) - } - - // Assert - onNodeWithText(CUSTOM_LISTS_EMPTY_TEXT).assertExists() - } - - @Test - fun givenNoCustomListsAndSearchIsActiveShouldNotShowCustomListHeader() = - composeExtension.use { - // Arrange - val mockSearchString = "SEARCH" setContentWithTheme { SelectLocationScreen( state = - SelectLocationUiState.Content( - searchTerm = mockSearchString, + SelectLocationUiState( filterChips = emptyList(), - relayListItems = emptyList(), - customLists = DUMMY_RELAY_ITEM_CUSTOM_LISTS, + multihopEnabled = false, + relayListType = RelayListType.EXIT, ) ) } // Assert - onNodeWithText(CUSTOM_LISTS_EMPTY_TEXT).assertDoesNotExist() - onNodeWithTag(SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG).assertDoesNotExist() + onNodeWithText(CUSTOM_LISTS_EMPTY_TEXT).assertExists() } @Test @@ -170,15 +113,21 @@ class SelectLocationScreenTest { composeExtension.use { // Arrange val customList = DUMMY_RELAY_ITEM_CUSTOM_LISTS[0] + every { listViewModel.uiState } returns + MutableStateFlow( + SelectLocationListUiState.Content( + relayListItems = listOf(RelayListItem.CustomListItem(customList)), + customLists = DUMMY_RELAY_ITEM_CUSTOM_LISTS, + ) + ) val mockedOnSelectRelay: (RelayItem) -> Unit = mockk(relaxed = true) setContentWithTheme { SelectLocationScreen( state = - SelectLocationUiState.Content( - searchTerm = "", + SelectLocationUiState( filterChips = emptyList(), - relayListItems = listOf(RelayListItem.CustomListItem(customList)), - customLists = DUMMY_RELAY_ITEM_CUSTOM_LISTS, + multihopEnabled = false, + relayListType = RelayListType.EXIT, ), onSelectRelay = mockedOnSelectRelay, ) @@ -196,16 +145,22 @@ class SelectLocationScreenTest { composeExtension.use { // Arrange val customList = DUMMY_RELAY_ITEM_CUSTOM_LISTS[0] + every { listViewModel.uiState } returns + MutableStateFlow( + SelectLocationListUiState.Content( + relayListItems = listOf(RelayListItem.CustomListItem(item = customList)), + customLists = DUMMY_RELAY_ITEM_CUSTOM_LISTS, + ) + ) val mockedOnSelectRelay: (RelayItem) -> Unit = mockk(relaxed = true) setContentWithTheme { SelectLocationScreen( state = - SelectLocationUiState.Content( - searchTerm = "", + SelectLocationUiState( + // searchTerm = "", filterChips = emptyList(), - relayListItems = - listOf(RelayListItem.CustomListItem(item = customList)), - customLists = DUMMY_RELAY_ITEM_CUSTOM_LISTS, + multihopEnabled = false, + relayListType = RelayListType.EXIT, ), onSelectRelay = mockedOnSelectRelay, ) @@ -223,15 +178,21 @@ class SelectLocationScreenTest { composeExtension.use { // Arrange val relayItem = DUMMY_RELAY_COUNTRIES[0] + every { listViewModel.uiState } returns + MutableStateFlow( + SelectLocationListUiState.Content( + relayListItems = listOf(RelayListItem.GeoLocationItem(relayItem)), + customLists = emptyList(), + ) + ) val mockedOnSelectRelay: (RelayItem) -> Unit = mockk(relaxed = true) setContentWithTheme { SelectLocationScreen( state = - SelectLocationUiState.Content( - searchTerm = "", + SelectLocationUiState( filterChips = emptyList(), - relayListItems = listOf(RelayListItem.GeoLocationItem(relayItem)), - customLists = emptyList(), + multihopEnabled = false, + relayListType = RelayListType.EXIT, ), onSelectRelay = mockedOnSelectRelay, ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt new file mode 100644 index 000000000000..f67e7228af43 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt @@ -0,0 +1,107 @@ +package net.mullvad.mullvadvpn.compose.button + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.material3.SingleChoiceSegmentedButtonRowScope +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import net.mullvad.mullvadvpn.lib.theme.AppTheme +import net.mullvad.mullvadvpn.lib.theme.color.onSelected +import net.mullvad.mullvadvpn.lib.theme.color.selected + +@Preview +@Composable +private fun PreviewMullvadSegmentedButton() { + AppTheme { + SingleChoiceSegmentedButtonRow { + MullvadSegmentedStartButton(selected = true, text = "Start", onClick = {}) + MullvadSegmentedMiddleButton(selected = false, text = "Middle", onClick = {}) + MullvadSegmentedEndButton(selected = false, text = "End", onClick = {}) + } + } +} + +@Composable +private fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedButton( + selected: Boolean, + text: String, + onClick: () -> Unit, + shape: Shape, +) { + SegmentedButton( + onClick = onClick, + selected = selected, + colors = + SegmentedButtonDefaults.colors() + .copy( + activeContainerColor = MaterialTheme.colorScheme.selected, + activeContentColor = MaterialTheme.colorScheme.onSelected, + inactiveContainerColor = MaterialTheme.colorScheme.primary, + inactiveContentColor = MaterialTheme.colorScheme.onPrimary, + ), + border = BorderStroke(0.dp, Color.Unspecified), + label = { + Text( + text = text, + textAlign = TextAlign.Center, + style = MaterialTheme.typography.bodyMedium, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + }, + icon = {}, + shape = shape, + ) +} + +@Composable +fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedStartButton( + selected: Boolean, + text: String, + onClick: () -> Unit, +) { + MullvadSegmentedButton( + selected = selected, + text = text, + onClick = onClick, + shape = RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp), + ) +} + +@Composable +fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedMiddleButton( + selected: Boolean, + text: String, + onClick: () -> Unit, +) { + MullvadSegmentedButton( + selected = selected, + text = text, + onClick = onClick, + shape = RoundedCornerShape(0.dp), // Square + ) +} + +@Composable +fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedEndButton( + selected: Boolean, + text: String, + onClick: () -> Unit, +) { + MullvadSegmentedButton( + selected = selected, + text = text, + onClick = onClick, + shape = RoundedCornerShape(topEnd = 8.dp, bottomEnd = 8.dp), + ) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt index d3e233c67b75..ab708e77d19f 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt @@ -15,19 +15,19 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.compose.component.MullvadFilterChip -import net.mullvad.mullvadvpn.compose.state.FilterChip import net.mullvad.mullvadvpn.lib.model.Ownership import net.mullvad.mullvadvpn.lib.theme.AppTheme import net.mullvad.mullvadvpn.lib.theme.Dimens +import net.mullvad.mullvadvpn.usecase.FilterChip @Preview @Composable private fun PreviewFilterCell() { AppTheme { FilterRow( - listOf(FilterChip.Ownership(Ownership.MullvadOwned), FilterChip.Provider(2)), - {}, - {}, + filters = listOf(FilterChip.Ownership(Ownership.MullvadOwned), FilterChip.Provider(2)), + onRemoveOwnershipFilter = {}, + onRemoveProviderFilter = {}, ) } } @@ -35,6 +35,7 @@ private fun PreviewFilterCell() { @Composable fun FilterRow( filters: List, + showTitle: Boolean = true, onRemoveOwnershipFilter: () -> Unit, onRemoveProviderFilter: () -> Unit, ) { @@ -42,22 +43,26 @@ fun FilterRow( Row( verticalAlignment = Alignment.CenterVertically, modifier = - Modifier.horizontalScroll(scrollState) - .padding(horizontal = Dimens.searchFieldHorizontalPadding) - .fillMaxWidth(), + Modifier.padding(horizontal = Dimens.searchFieldHorizontalPadding) + .fillMaxWidth() + .horizontalScroll(scrollState), horizontalArrangement = Arrangement.spacedBy(Dimens.chipSpace), ) { - Text( - text = stringResource(id = R.string.filtered), - color = MaterialTheme.colorScheme.onPrimary, - style = MaterialTheme.typography.labelMedium, - ) + if (showTitle) { + Text( + text = stringResource(id = R.string.filters), + color = MaterialTheme.colorScheme.onPrimary, + style = MaterialTheme.typography.labelMedium, + ) + } filters.forEach { when (it) { is FilterChip.Ownership -> OwnershipFilterChip(it.ownership, onRemoveOwnershipFilter) is FilterChip.Provider -> ProviderFilterChip(it.count, onRemoveProviderFilter) is FilterChip.Daita -> DaitaFilterChip() + is FilterChip.Entry -> EntryFilterChip() + is FilterChip.Exit -> ExitFilterChip() } } } @@ -90,6 +95,24 @@ fun DaitaFilterChip() { ) } +@Composable +fun EntryFilterChip() { + MullvadFilterChip( + text = stringResource(id = R.string.entry), + onRemoveClick = {}, + enabled = false, + ) +} + +@Composable +fun ExitFilterChip() { + MullvadFilterChip( + text = stringResource(id = R.string.exit), + onRemoveClick = {}, + enabled = false, + ) +} + private fun Ownership.stringResources(): Int = when (this) { Ownership.MullvadOwned -> R.string.owned diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt index e1157eb3bcd0..eb729701bc9d 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/RelayLocationCell.kt @@ -27,13 +27,16 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp +import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.compose.component.ExpandChevron import net.mullvad.mullvadvpn.compose.component.MullvadCheckbox import net.mullvad.mullvadvpn.compose.preview.RelayItemCheckableCellPreviewParameterProvider +import net.mullvad.mullvadvpn.compose.state.RelayListItemState import net.mullvad.mullvadvpn.compose.test.EXPAND_BUTTON_TEST_TAG import net.mullvad.mullvadvpn.compose.test.LOCATION_CELL_TEST_TAG import net.mullvad.mullvadvpn.lib.model.RelayItem @@ -70,6 +73,7 @@ private fun PreviewCheckableRelayLocationCell( fun StatusRelayItemCell( item: RelayItem, isSelected: Boolean, + state: RelayListItemState?, modifier: Modifier = Modifier, onClick: () -> Unit = {}, onLongClick: (() -> Unit)? = null, @@ -80,11 +84,11 @@ fun StatusRelayItemCell( inactiveColor: Color = MaterialTheme.colorScheme.error, disabledColor: Color = MaterialTheme.colorScheme.onSurfaceVariant, ) { - RelayItemCell( modifier = modifier, - item, - isSelected, + item = item, + isSelected = isSelected, + state = state, leadingContent = { if (isSelected) { Icon(imageVector = Icons.Default.Check, contentDescription = null) @@ -98,6 +102,7 @@ fun StatusRelayItemCell( when { item is RelayItem.CustomList && item.locations.isEmpty() -> disabledColor + state != null -> disabledColor item.active -> activeColor else -> inactiveColor }, @@ -120,6 +125,7 @@ fun RelayItemCell( modifier: Modifier = Modifier, item: RelayItem, isSelected: Boolean, + state: RelayListItemState?, leadingContent: (@Composable RowScope.() -> Unit)? = null, onClick: () -> Unit, onLongClick: (() -> Unit)? = null, @@ -148,7 +154,7 @@ fun RelayItemCell( Row( modifier = Modifier.combinedClickable( - enabled = item.active, + enabled = state == null && item.active, onClick = onClick, onLongClick = onLongClick, ) @@ -159,7 +165,7 @@ fun RelayItemCell( if (leadingContent != null) { leadingContent() } - Name(relay = item) + Name(name = item.name, state = state) } if (item.hasChildren) { @@ -187,6 +193,7 @@ fun CheckableRelayLocationCell( modifier = modifier, item = item, isSelected = false, + state = null, leadingContent = { MullvadCheckbox( checked = checked, @@ -201,14 +208,14 @@ fun CheckableRelayLocationCell( } @Composable -private fun Name(modifier: Modifier = Modifier, relay: RelayItem) { +private fun Name(modifier: Modifier = Modifier, name: String, state: RelayListItemState?) { Text( - text = relay.name, + text = state?.let { name.withSuffix(state) } ?: name, color = MaterialTheme.colorScheme.onSurface, modifier = modifier .alpha( - if (relay.active) { + if (state == null) { AlphaVisible } else { AlphaInactive @@ -252,3 +259,10 @@ private fun Int.toBackgroundColor(): Color = 2 -> MaterialTheme.colorScheme.surfaceContainerLow else -> MaterialTheme.colorScheme.surfaceContainerLowest } + +@Composable +private fun String.withSuffix(state: RelayListItemState) = + when (state) { + RelayListItemState.USED_AS_EXIT -> stringResource(R.string.x_exit, this) + RelayListItemState.USED_AS_ENTRY -> stringResource(R.string.x_entry, this) + } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationsEmptyText.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationsEmptyText.kt index 347de1654edb..579be88bb646 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationsEmptyText.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/LocationsEmptyText.kt @@ -1,51 +1,29 @@ package net.mullvad.mullvadvpn.compose.component -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding 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.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow -import androidx.core.text.HtmlCompat import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.extensions.toAnnotatedString import net.mullvad.mullvadvpn.lib.theme.Dimens import net.mullvad.mullvadvpn.relaylist.MIN_SEARCH_LENGTH @Composable fun LocationsEmptyText(searchTerm: String) { if (searchTerm.length >= MIN_SEARCH_LENGTH) { - val firstRow = - HtmlCompat.fromHtml( - textResource(id = R.string.select_location_empty_text_first_row, searchTerm), - HtmlCompat.FROM_HTML_MODE_COMPACT, - ) - .toAnnotatedString(boldFontWeight = FontWeight.ExtraBold) - val secondRow = textResource(id = R.string.select_location_empty_text_second_row) - Column( - modifier = Modifier.padding(horizontal = Dimens.selectLocationTitlePadding), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - text = firstRow, - style = MaterialTheme.typography.labelMedium, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurfaceVariant, - maxLines = 2, - overflow = TextOverflow.Ellipsis, - ) - Text( - text = secondRow, - style = MaterialTheme.typography.labelMedium, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } + Text( + text = textResource(R.string.search_location_empty_text, searchTerm), + style = MaterialTheme.typography.labelMedium, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(Dimens.screenVerticalMargin), + ) } else { Text( text = stringResource(R.string.no_locations_found), diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt index 8b04017f0a67..c31608949d81 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt @@ -92,6 +92,7 @@ private fun FeatureIndicator.text(): String { FeatureIndicator.SERVER_IP_OVERRIDE -> R.string.feature_server_ip_override FeatureIndicator.CUSTOM_MTU -> R.string.feature_custom_mtu FeatureIndicator.DAITA -> R.string.feature_daita + FeatureIndicator.MULTIHOP -> R.string.feature_multihop } return textResource(resource) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayListItemPreviewData.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayListItemPreviewData.kt new file mode 100644 index 000000000000..2c695764d731 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/RelayListItemPreviewData.kt @@ -0,0 +1,113 @@ +package net.mullvad.mullvadvpn.compose.preview + +import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListItemState +import net.mullvad.mullvadvpn.lib.model.CustomList +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.CustomListName +import net.mullvad.mullvadvpn.lib.model.RelayItem + +object RelayListItemPreviewData { + @Suppress("LongMethod") + fun generateRelayListItems( + includeCustomLists: Boolean, + isSearching: Boolean, + ): List = buildList { + if (!isSearching || includeCustomLists) { + add(RelayListItem.CustomListHeader) + // Add custom list items + if (includeCustomLists) { + RelayListItem.CustomListItem( + item = + RelayItem.CustomList( + customList = + CustomList( + id = CustomListId("custom_list_id"), + name = CustomListName.fromString("Custom List"), + locations = emptyList(), + ), + locations = + listOf( + RelayItemPreviewData.generateRelayItemCountry( + name = "Country", + cityNames = listOf("City"), + relaysPerCity = 2, + active = true, + ) + ), + ), + isSelected = false, + state = null, + expanded = false, + ) + } + if (!isSearching) { + add(RelayListItem.CustomListFooter(hasCustomList = includeCustomLists)) + } + } + add(RelayListItem.LocationHeader) + val locations = + listOf( + RelayItemPreviewData.generateRelayItemCountry( + name = "A relay", + cityNames = listOf("City 1", "City 2"), + relaysPerCity = 2, + active = true, + ), + RelayItemPreviewData.generateRelayItemCountry( + name = "Another relay", + cityNames = listOf("City X", "City Y", "City Z"), + relaysPerCity = 1, + active = false, + ), + ) + addAll( + listOf( + RelayListItem.GeoLocationItem( + item = locations[0], + isSelected = false, + depth = 0, + expanded = true, + state = null, + ), + RelayListItem.GeoLocationItem( + item = locations[0].cities[0], + isSelected = true, + depth = 1, + expanded = false, + state = null, + ), + RelayListItem.GeoLocationItem( + item = locations[0].cities[1], + isSelected = false, + depth = 1, + expanded = true, + state = null, + ), + RelayListItem.GeoLocationItem( + item = locations[0].cities[1].relays[0], + isSelected = false, + depth = 2, + expanded = false, + state = RelayListItemState.USED_AS_EXIT, + ), + RelayListItem.GeoLocationItem( + item = locations[0].cities[1].relays[0], + isSelected = false, + depth = 2, + expanded = false, + state = null, + ), + RelayListItem.GeoLocationItem( + item = locations[1], + isSelected = false, + depth = 0, + expanded = false, + state = null, + ), + ) + ) + } + + fun generateEmptyList(searchTerm: String) = listOf(RelayListItem.LocationsEmptyText(searchTerm)) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsUiStatePreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsUiStatePreviewParameterProvider.kt new file mode 100644 index 000000000000..ebed8d229f8c --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsUiStatePreviewParameterProvider.kt @@ -0,0 +1,29 @@ +package net.mullvad.mullvadvpn.compose.preview + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState +import net.mullvad.mullvadvpn.usecase.FilterChip + +class SearchLocationsUiStatePreviewParameterProvider : + PreviewParameterProvider { + override val values = + sequenceOf( + SearchLocationUiState.NoQuery(searchTerm = "", filterChips = listOf(FilterChip.Entry)), + SearchLocationUiState.Content( + searchTerm = "Mullvad", + filterChips = listOf(FilterChip.Entry), + relayListItems = RelayListItemPreviewData.generateEmptyList("Mullvad"), + customLists = emptyList(), + ), + SearchLocationUiState.Content( + searchTerm = "Germany", + filterChips = listOf(FilterChip.Entry), + relayListItems = + RelayListItemPreviewData.generateRelayListItems( + includeCustomLists = true, + isSearching = true, + ), + customLists = emptyList(), + ), + ) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectLocationsUiStatePreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectLocationsUiStatePreviewParameterProvider.kt index a3b4e1bcdc57..b0415b1c7e5f 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectLocationsUiStatePreviewParameterProvider.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectLocationsUiStatePreviewParameterProvider.kt @@ -1,66 +1,46 @@ package net.mullvad.mullvadvpn.compose.preview import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import net.mullvad.mullvadvpn.compose.state.FilterChip -import net.mullvad.mullvadvpn.compose.state.ModelOwnership -import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListType import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState -import net.mullvad.mullvadvpn.lib.model.CustomListId -import net.mullvad.mullvadvpn.lib.model.CustomListName -import net.mullvad.mullvadvpn.lib.model.DomainCustomList -import net.mullvad.mullvadvpn.lib.model.GeoLocationId import net.mullvad.mullvadvpn.lib.model.Ownership import net.mullvad.mullvadvpn.lib.model.Provider -import net.mullvad.mullvadvpn.lib.model.ProviderId -import net.mullvad.mullvadvpn.lib.model.RelayItem - -private val RELAY = - RelayItem.Location.Relay( - id = - GeoLocationId.Hostname( - city = GeoLocationId.City(country = GeoLocationId.Country("se"), code = "code"), - code = "code", - ), - provider = Provider(providerId = ProviderId("providerId"), ownership = Ownership.Rented), - active = true, - daita = true, - ) +import net.mullvad.mullvadvpn.usecase.FilterChip +import net.mullvad.mullvadvpn.usecase.ModelOwnership class SelectLocationsUiStatePreviewParameterProvider : PreviewParameterProvider { override val values = sequenceOf( - SelectLocationUiState.Content( - searchTerm = "search term", - listOf(FilterChip.Ownership(ownership = ModelOwnership.MullvadOwned)), - relayListItems = + SelectLocationUiState( + filterChips = emptyList(), + multihopEnabled = false, + relayListType = RelayListType.EXIT, + ), + SelectLocationUiState( + filterChips = listOf( - RelayListItem.GeoLocationItem( - item = RELAY, - isSelected = true, - depth = 1, - expanded = true, - ) + FilterChip.Ownership(ownership = ModelOwnership.Rented), + FilterChip.Provider(PROVIDER_COUNT), ), - customLists = + multihopEnabled = false, + relayListType = RelayListType.EXIT, + ), + SelectLocationUiState( + filterChips = emptyList(), + multihopEnabled = true, + relayListType = RelayListType.ENTRY, + ), + SelectLocationUiState( + filterChips = listOf( - RelayItem.CustomList( - customList = - DomainCustomList( - id = CustomListId("custom_list_id"), - locations = - listOf( - GeoLocationId.City( - country = GeoLocationId.Country("dk"), - code = "code2", - ) - ), - name = CustomListName.fromString("Custom List"), - ), - locations = listOf(RELAY), - ) + FilterChip.Ownership(ownership = ModelOwnership.MullvadOwned), + FilterChip.Provider(PROVIDER_COUNT), ), + multihopEnabled = true, + relayListType = RelayListType.ENTRY, ), - SelectLocationUiState.Loading, ) } + +private const val PROVIDER_COUNT = 3 diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SettingsUiStatePreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SettingsUiStatePreviewParameterProvider.kt index 623091176623..18f422a988af 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SettingsUiStatePreviewParameterProvider.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SettingsUiStatePreviewParameterProvider.kt @@ -11,12 +11,14 @@ class SettingsUiStatePreviewParameterProvider : PreviewParameterProvider + stringResource(R.string.x_via_x, location.hostname!!, location.entryHostname!!) + else -> location?.hostname + } AnimatedContent(hostname, label = "hostname") { if (it != null) { Text( diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt new file mode 100644 index 000000000000..5491fc624c06 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MultihopScreen.kt @@ -0,0 +1,89 @@ +package net.mullvad.mullvadvpn.compose.screen + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.widthIn +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.compose.dropUnlessResumed +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.cell.HeaderSwitchComposeCell +import net.mullvad.mullvadvpn.compose.cell.SwitchComposeSubtitleCell +import net.mullvad.mullvadvpn.compose.component.NavigateBackIconButton +import net.mullvad.mullvadvpn.compose.component.ScaffoldWithMediumTopBar +import net.mullvad.mullvadvpn.compose.transitions.SlideInFromRightTransition +import net.mullvad.mullvadvpn.lib.theme.AppTheme +import net.mullvad.mullvadvpn.lib.theme.Dimens +import net.mullvad.mullvadvpn.viewmodel.MultihopUiState +import net.mullvad.mullvadvpn.viewmodel.MultihopViewModel +import org.koin.androidx.compose.koinViewModel + +@Preview +@Composable +private fun PreviewMultihopScreen() { + AppTheme { MultihopScreen(state = MultihopUiState(false)) } +} + +@Destination(style = SlideInFromRightTransition::class) +@Composable +fun Multihop(navigator: DestinationsNavigator) { + val viewModel = koinViewModel() + val state by viewModel.uiState.collectAsStateWithLifecycle() + MultihopScreen( + state = state, + onMultihopClick = viewModel::setMultihop, + onBackClick = dropUnlessResumed { navigator.navigateUp() }, + ) +} + +@Composable +fun MultihopScreen( + state: MultihopUiState, + onMultihopClick: (enable: Boolean) -> Unit = {}, + onBackClick: () -> Unit = {}, +) { + ScaffoldWithMediumTopBar( + appBarTitle = stringResource(id = R.string.multihop), + navigationIcon = { NavigateBackIconButton { onBackClick() } }, + ) { modifier -> + Column(modifier = modifier) { + // Scale image to fit width up to certain width + Image( + contentScale = ContentScale.FillWidth, + modifier = + Modifier.widthIn(max = Dimens.settingsDetailsImageMaxWidth) + .fillMaxWidth() + .padding(horizontal = Dimens.mediumPadding) + .align(Alignment.CenterHorizontally), + painter = painterResource(id = R.drawable.multihop_illustration), + contentDescription = stringResource(R.string.multihop), + ) + Description() + HeaderSwitchComposeCell( + title = stringResource(R.string.enable), + isToggled = state.enable, + onCellClicked = onMultihopClick, + ) + } + } +} + +@Composable +private fun Description() { + SwitchComposeSubtitleCell( + modifier = Modifier.padding(vertical = Dimens.mediumPadding), + text = stringResource(R.string.multihop_description), + ) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt deleted file mode 100644 index c36f10212e34..000000000000 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SelectLocationScreen.kt +++ /dev/null @@ -1,938 +0,0 @@ -package net.mullvad.mullvadvpn.compose.screen - -import android.content.Context -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.background -import androidx.compose.foundation.gestures.animateScrollBy -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyItemScope -import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Add -import androidx.compose.material.icons.filled.Close -import androidx.compose.material.icons.filled.Delete -import androidx.compose.material.icons.filled.Edit -import androidx.compose.material.icons.filled.FilterList -import androidx.compose.material.icons.filled.Remove -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SheetState -import androidx.compose.material3.SnackbarDuration -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Text -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -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.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.testTag -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.compose.dropUnlessResumed -import com.ramcosta.composedestinations.annotation.Destination -import com.ramcosta.composedestinations.annotation.RootGraph -import com.ramcosta.composedestinations.generated.destinations.CreateCustomListDestination -import com.ramcosta.composedestinations.generated.destinations.CustomListLocationsDestination -import com.ramcosta.composedestinations.generated.destinations.CustomListsDestination -import com.ramcosta.composedestinations.generated.destinations.DeleteCustomListDestination -import com.ramcosta.composedestinations.generated.destinations.EditCustomListNameDestination -import com.ramcosta.composedestinations.generated.destinations.FilterDestination -import com.ramcosta.composedestinations.navigation.DestinationsNavigator -import com.ramcosta.composedestinations.result.NavResult -import com.ramcosta.composedestinations.result.ResultBackNavigator -import com.ramcosta.composedestinations.result.ResultRecipient -import com.ramcosta.composedestinations.spec.DestinationSpec -import kotlinx.coroutines.launch -import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.compose.cell.FilterRow -import net.mullvad.mullvadvpn.compose.cell.HeaderCell -import net.mullvad.mullvadvpn.compose.cell.IconCell -import net.mullvad.mullvadvpn.compose.cell.StatusRelayItemCell -import net.mullvad.mullvadvpn.compose.cell.SwitchComposeSubtitleCell -import net.mullvad.mullvadvpn.compose.cell.ThreeDotCell -import net.mullvad.mullvadvpn.compose.communication.CustomListAction -import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData -import net.mullvad.mullvadvpn.compose.component.LocationsEmptyText -import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorLarge -import net.mullvad.mullvadvpn.compose.component.MullvadModalBottomSheet -import net.mullvad.mullvadvpn.compose.component.MullvadSnackbar -import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar -import net.mullvad.mullvadvpn.compose.constant.ContentType -import net.mullvad.mullvadvpn.compose.extensions.dropUnlessResumed -import net.mullvad.mullvadvpn.compose.preview.SelectLocationsUiStatePreviewParameterProvider -import net.mullvad.mullvadvpn.compose.screen.BottomSheetState.ShowCustomListsBottomSheet -import net.mullvad.mullvadvpn.compose.screen.BottomSheetState.ShowCustomListsEntryBottomSheet -import net.mullvad.mullvadvpn.compose.screen.BottomSheetState.ShowEditCustomListBottomSheet -import net.mullvad.mullvadvpn.compose.screen.BottomSheetState.ShowLocationBottomSheet -import net.mullvad.mullvadvpn.compose.state.RelayListItem -import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState -import net.mullvad.mullvadvpn.compose.test.CIRCULAR_PROGRESS_INDICATOR -import net.mullvad.mullvadvpn.compose.test.LOCATION_CELL_TEST_TAG -import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_CUSTOM_LIST_BOTTOM_SHEET_TEST_TAG -import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG -import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_LOCATION_BOTTOM_SHEET_TEST_TAG -import net.mullvad.mullvadvpn.compose.textfield.SearchTextField -import net.mullvad.mullvadvpn.compose.transitions.TopLevelTransition -import net.mullvad.mullvadvpn.compose.util.CollectSideEffectWithLifecycle -import net.mullvad.mullvadvpn.compose.util.RunOnKeyChange -import net.mullvad.mullvadvpn.compose.util.showSnackbarImmediately -import net.mullvad.mullvadvpn.lib.model.CustomListId -import net.mullvad.mullvadvpn.lib.model.CustomListName -import net.mullvad.mullvadvpn.lib.model.RelayItem -import net.mullvad.mullvadvpn.lib.model.RelayItemId -import net.mullvad.mullvadvpn.lib.theme.AppTheme -import net.mullvad.mullvadvpn.lib.theme.Dimens -import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive -import net.mullvad.mullvadvpn.lib.theme.color.AlphaScrollbar -import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible -import net.mullvad.mullvadvpn.relaylist.canAddLocation -import net.mullvad.mullvadvpn.viewmodel.SelectLocationSideEffect -import net.mullvad.mullvadvpn.viewmodel.SelectLocationViewModel -import org.koin.androidx.compose.koinViewModel - -@Preview("Content|Loading") -@Composable -private fun PreviewSelectLocationScreen( - @PreviewParameter(SelectLocationsUiStatePreviewParameterProvider::class) - state: SelectLocationUiState -) { - AppTheme { SelectLocationScreen(state = state) } -} - -@Destination(style = TopLevelTransition::class) -@Suppress("LongMethod") -@Composable -fun SelectLocation( - navigator: DestinationsNavigator, - backNavigator: ResultBackNavigator, - createCustomListDialogResultRecipient: - ResultRecipient< - CreateCustomListDestination, - CustomListActionResultData.Success.CreatedWithLocations, - >, - editCustomListNameDialogResultRecipient: - ResultRecipient, - deleteCustomListDialogResultRecipient: - ResultRecipient, - updateCustomListResultRecipient: - ResultRecipient, -) { - val vm = koinViewModel() - val state = vm.uiState.collectAsStateWithLifecycle() - - val snackbarHostState = remember { SnackbarHostState() } - val context = LocalContext.current - val lazyListState = rememberLazyListState() - CollectSideEffectWithLifecycle(vm.uiSideEffect) { - when (it) { - SelectLocationSideEffect.CloseScreen -> backNavigator.navigateBack(result = true) - is SelectLocationSideEffect.CustomListActionToast -> - launch { - snackbarHostState.showResultSnackbar( - context = context, - result = it.resultData, - onUndo = vm::performAction, - ) - } - SelectLocationSideEffect.GenericError -> - launch { - snackbarHostState.showSnackbarImmediately( - message = context.getString(R.string.error_occurred), - duration = SnackbarDuration.Short, - ) - } - } - } - - val stateActual = state.value - RunOnKeyChange(stateActual is SelectLocationUiState.Content) { - val index = stateActual.indexOfSelectedRelayItem() - if (index != -1) { - lazyListState.scrollToItem(index) - lazyListState.animateScrollAndCentralizeItem(index) - } - } - - createCustomListDialogResultRecipient.OnCustomListNavResult( - snackbarHostState, - vm::performAction, - ) - - editCustomListNameDialogResultRecipient.OnCustomListNavResult( - snackbarHostState, - vm::performAction, - ) - - deleteCustomListDialogResultRecipient.OnCustomListNavResult( - snackbarHostState, - vm::performAction, - ) - - updateCustomListResultRecipient.OnCustomListNavResult(snackbarHostState, vm::performAction) - - SelectLocationScreen( - state = state.value, - lazyListState = lazyListState, - snackbarHostState = snackbarHostState, - onSelectRelay = vm::selectRelay, - onSearchTermInput = vm::onSearchTermInput, - onBackClick = dropUnlessResumed { backNavigator.navigateBack() }, - onFilterClick = dropUnlessResumed { navigator.navigate(FilterDestination) }, - onCreateCustomList = - dropUnlessResumed { relayItem -> - navigator.navigate(CreateCustomListDestination(locationCode = relayItem?.id)) - }, - onToggleExpand = vm::onToggleExpand, - onEditCustomLists = dropUnlessResumed { navigator.navigate(CustomListsDestination()) }, - removeOwnershipFilter = vm::removeOwnerFilter, - removeProviderFilter = vm::removeProviderFilter, - onAddLocationToList = vm::addLocationToList, - onRemoveLocationFromList = vm::removeLocationFromList, - onEditCustomListName = - dropUnlessResumed { customList: RelayItem.CustomList -> - navigator.navigate( - EditCustomListNameDestination( - customListId = customList.id, - initialName = customList.customList.name, - ) - ) - }, - onEditLocationsCustomList = - dropUnlessResumed { customList: RelayItem.CustomList -> - navigator.navigate( - CustomListLocationsDestination(customListId = customList.id, newList = false) - ) - }, - onDeleteCustomList = - dropUnlessResumed { customList: RelayItem.CustomList -> - navigator.navigate( - DeleteCustomListDestination( - customListId = customList.id, - name = customList.customList.name, - ) - ) - }, - ) -} - -@OptIn(ExperimentalFoundationApi::class) -@Suppress("LongMethod") -@Composable -fun SelectLocationScreen( - state: SelectLocationUiState, - lazyListState: LazyListState = rememberLazyListState(), - snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }, - onSelectRelay: (item: RelayItem) -> Unit = {}, - onSearchTermInput: (searchTerm: String) -> Unit = {}, - onBackClick: () -> Unit = {}, - onFilterClick: () -> Unit = {}, - onCreateCustomList: (location: RelayItem.Location?) -> Unit = {}, - onEditCustomLists: () -> Unit = {}, - removeOwnershipFilter: () -> Unit = {}, - removeProviderFilter: () -> Unit = {}, - onAddLocationToList: (location: RelayItem.Location, customList: RelayItem.CustomList) -> Unit = - { _, _ -> - }, - onRemoveLocationFromList: (location: RelayItem.Location, customListId: CustomListId) -> Unit = - { _, _ -> - }, - onEditCustomListName: (RelayItem.CustomList) -> Unit = {}, - onEditLocationsCustomList: (RelayItem.CustomList) -> Unit = {}, - onDeleteCustomList: (RelayItem.CustomList) -> Unit = {}, - onToggleExpand: (RelayItemId, CustomListId?, Boolean) -> Unit = { _, _, _ -> }, -) { - val backgroundColor = MaterialTheme.colorScheme.surface - - Scaffold( - snackbarHost = { - SnackbarHost( - snackbarHostState, - snackbar = { snackbarData -> MullvadSnackbar(snackbarData = snackbarData) }, - ) - } - ) { - var bottomSheetState by remember { mutableStateOf(null) } - BottomSheets( - bottomSheetState = bottomSheetState, - onCreateCustomList = onCreateCustomList, - onEditCustomLists = onEditCustomLists, - onAddLocationToList = onAddLocationToList, - onRemoveLocationFromList = onRemoveLocationFromList, - onEditCustomListName = onEditCustomListName, - onEditLocationsCustomList = onEditLocationsCustomList, - onDeleteCustomList = onDeleteCustomList, - onHideBottomSheet = { bottomSheetState = null }, - ) - - Column(modifier = Modifier.padding(it).background(backgroundColor).fillMaxSize()) { - SelectLocationTopBar(onBackClick = onBackClick, onFilterClick = onFilterClick) - - if (state is SelectLocationUiState.Content && state.filterChips.isNotEmpty()) { - FilterRow(filters = state.filterChips, removeOwnershipFilter, removeProviderFilter) - } - - SearchTextField( - modifier = - Modifier.fillMaxWidth() - .height(Dimens.searchFieldHeight) - .padding(horizontal = Dimens.searchFieldHorizontalPadding), - textColor = MaterialTheme.colorScheme.onTertiaryContainer, - backgroundColor = MaterialTheme.colorScheme.tertiaryContainer, - ) { searchString -> - onSearchTermInput.invoke(searchString) - } - Spacer(modifier = Modifier.height(height = Dimens.verticalSpace)) - - LazyColumn( - modifier = - Modifier.fillMaxSize() - .drawVerticalScrollbar( - lazyListState, - MaterialTheme.colorScheme.onSurface.copy(alpha = AlphaScrollbar), - ), - state = lazyListState, - horizontalAlignment = Alignment.CenterHorizontally, - ) { - when (state) { - SelectLocationUiState.Loading -> { - loading() - } - is SelectLocationUiState.Content -> { - - itemsIndexed( - items = state.relayListItems, - key = { _: Int, item: RelayListItem -> item.key }, - contentType = { _, item -> item.contentType }, - itemContent = { index: Int, listItem: RelayListItem -> - Column(modifier = Modifier.animateItem()) { - if (index != 0) { - HorizontalDivider(color = backgroundColor) - } - when (listItem) { - RelayListItem.CustomListHeader -> - CustomListHeader( - onShowCustomListBottomSheet = { - bottomSheetState = - ShowCustomListsBottomSheet( - editListEnabled = - state.customLists.isNotEmpty() - ) - } - ) - is RelayListItem.CustomListItem -> - CustomListItem( - listItem, - onSelectRelay, - { - bottomSheetState = - ShowEditCustomListBottomSheet(it) - }, - { customListId, expand -> - onToggleExpand(customListId, null, expand) - }, - ) - is RelayListItem.CustomListEntryItem -> - CustomListEntryItem( - listItem, - { onSelectRelay(listItem.item) }, - if (listItem.depth == 1) { - { - bottomSheetState = - ShowCustomListsEntryBottomSheet( - listItem.parentId, - listItem.parentName, - listItem.item, - ) - } - } else { - null - }, - { expand: Boolean -> - onToggleExpand( - listItem.item.id, - listItem.parentId, - expand, - ) - }, - ) - is RelayListItem.CustomListFooter -> - CustomListFooter(listItem) - RelayListItem.LocationHeader -> RelayLocationHeader() - is RelayListItem.GeoLocationItem -> - RelayLocationItem( - listItem, - { onSelectRelay(listItem.item) }, - { - // Only direct children can be removed - bottomSheetState = - ShowLocationBottomSheet( - state.customLists, - listItem.item, - ) - }, - { expand -> - onToggleExpand(listItem.item.id, null, expand) - }, - ) - is RelayListItem.LocationsEmptyText -> - LocationsEmptyText(listItem.searchTerm) - } - } - }, - ) - } - } - } - } - } -} - -@Composable -fun LazyItemScope.RelayLocationHeader() { - HeaderCell(text = stringResource(R.string.all_locations)) -} - -@Composable -fun LazyItemScope.RelayLocationItem( - relayItem: RelayListItem.GeoLocationItem, - onSelectRelay: () -> Unit, - onLongClick: () -> Unit, - onExpand: (Boolean) -> Unit, -) { - val location = relayItem.item - StatusRelayItemCell( - location, - relayItem.isSelected, - onClick = { onSelectRelay() }, - onLongClick = { onLongClick() }, - onToggleExpand = { onExpand(it) }, - isExpanded = relayItem.expanded, - depth = relayItem.depth, - modifier = Modifier.testTag(LOCATION_CELL_TEST_TAG), - ) -} - -@Composable -fun LazyItemScope.CustomListItem( - itemState: RelayListItem.CustomListItem, - onSelectRelay: (item: RelayItem) -> Unit, - onShowEditBottomSheet: (RelayItem.CustomList) -> Unit, - onExpand: ((CustomListId, Boolean) -> Unit), -) { - val customListItem = itemState.item - StatusRelayItemCell( - customListItem, - itemState.isSelected, - onClick = { onSelectRelay(customListItem) }, - onLongClick = { onShowEditBottomSheet(customListItem) }, - onToggleExpand = { onExpand(customListItem.id, it) }, - isExpanded = itemState.expanded, - ) -} - -@Composable -fun LazyItemScope.CustomListEntryItem( - itemState: RelayListItem.CustomListEntryItem, - onSelectRelay: () -> Unit, - onShowEditCustomListEntryBottomSheet: (() -> Unit)?, - onToggleExpand: (Boolean) -> Unit, -) { - val customListEntryItem = itemState.item - StatusRelayItemCell( - customListEntryItem, - false, - onClick = onSelectRelay, - onLongClick = onShowEditCustomListEntryBottomSheet, - onToggleExpand = onToggleExpand, - isExpanded = itemState.expanded, - depth = itemState.depth, - ) -} - -@Composable -fun LazyItemScope.CustomListFooter(item: RelayListItem.CustomListFooter) { - SwitchComposeSubtitleCell( - text = - if (item.hasCustomList) { - stringResource(R.string.to_add_locations_to_a_list) - } else { - stringResource(R.string.to_create_a_custom_list) - }, - modifier = Modifier.background(MaterialTheme.colorScheme.surface), - ) -} - -@Composable -private fun SelectLocationTopBar(onBackClick: () -> Unit, onFilterClick: () -> Unit) { - Row(modifier = Modifier.fillMaxWidth()) { - IconButton(onClick = onBackClick) { - Icon( - imageVector = Icons.Default.Close, - tint = MaterialTheme.colorScheme.onSurface, - contentDescription = stringResource(id = R.string.back), - ) - } - Text( - text = stringResource(id = R.string.select_location), - modifier = Modifier.align(Alignment.CenterVertically).weight(weight = 1f), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.onSurface, - ) - IconButton(onClick = onFilterClick) { - Icon( - imageVector = Icons.Default.FilterList, - contentDescription = stringResource(id = R.string.filter), - tint = MaterialTheme.colorScheme.onSurface, - ) - } - } -} - -private fun LazyListScope.loading() { - item(contentType = ContentType.PROGRESS) { - MullvadCircularProgressIndicatorLarge(Modifier.testTag(CIRCULAR_PROGRESS_INDICATOR)) - } -} - -@Composable -private fun LazyItemScope.CustomListHeader(onShowCustomListBottomSheet: () -> Unit) { - ThreeDotCell( - text = stringResource(R.string.custom_lists), - onClickDots = onShowCustomListBottomSheet, - modifier = Modifier.testTag(SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG), - ) -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun BottomSheets( - bottomSheetState: BottomSheetState?, - onCreateCustomList: (RelayItem.Location?) -> Unit, - onEditCustomLists: () -> Unit, - onAddLocationToList: (RelayItem.Location, RelayItem.CustomList) -> Unit, - onRemoveLocationFromList: (location: RelayItem.Location, parent: CustomListId) -> Unit, - onEditCustomListName: (RelayItem.CustomList) -> Unit, - onEditLocationsCustomList: (RelayItem.CustomList) -> Unit, - onDeleteCustomList: (RelayItem.CustomList) -> Unit, - onHideBottomSheet: () -> Unit, -) { - val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - val scope = rememberCoroutineScope() - val onCloseBottomSheet: (animate: Boolean) -> Unit = { animate -> - if (animate) { - scope.launch { sheetState.hide() }.invokeOnCompletion { onHideBottomSheet() } - } else { - onHideBottomSheet() - } - } - val backgroundColor: Color = MaterialTheme.colorScheme.surfaceContainer - val onBackgroundColor: Color = MaterialTheme.colorScheme.onSurface - - when (bottomSheetState) { - is ShowCustomListsBottomSheet -> { - CustomListsBottomSheet( - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - sheetState = sheetState, - bottomSheetState = bottomSheetState, - onCreateCustomList = { onCreateCustomList(null) }, - onEditCustomLists = onEditCustomLists, - closeBottomSheet = onCloseBottomSheet, - ) - } - is ShowLocationBottomSheet -> { - LocationBottomSheet( - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - sheetState = sheetState, - customLists = bottomSheetState.customLists, - item = bottomSheetState.item, - onCreateCustomList = onCreateCustomList, - onAddLocationToList = onAddLocationToList, - closeBottomSheet = onCloseBottomSheet, - ) - } - is ShowEditCustomListBottomSheet -> { - EditCustomListBottomSheet( - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - sheetState = sheetState, - customList = bottomSheetState.customList, - onEditName = onEditCustomListName, - onEditLocations = onEditLocationsCustomList, - onDeleteCustomList = onDeleteCustomList, - closeBottomSheet = onCloseBottomSheet, - ) - } - is ShowCustomListsEntryBottomSheet -> { - CustomListEntryBottomSheet( - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - sheetState = sheetState, - customListId = bottomSheetState.customListId, - customListName = bottomSheetState.customListName, - item = bottomSheetState.item, - onRemoveLocationFromList = onRemoveLocationFromList, - closeBottomSheet = onCloseBottomSheet, - ) - } - null -> { - /* Do nothing */ - } - } -} - -private fun SelectLocationUiState.indexOfSelectedRelayItem(): Int = - if (this is SelectLocationUiState.Content) { - relayListItems.indexOfFirst { - when (it) { - is RelayListItem.CustomListItem -> it.isSelected - is RelayListItem.GeoLocationItem -> it.isSelected - is RelayListItem.CustomListEntryItem -> false - is RelayListItem.CustomListFooter -> false - RelayListItem.CustomListHeader -> false - RelayListItem.LocationHeader -> false - is RelayListItem.LocationsEmptyText -> false - } - } - } else { - -1 - } - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun CustomListsBottomSheet( - backgroundColor: Color, - onBackgroundColor: Color, - sheetState: SheetState, - bottomSheetState: ShowCustomListsBottomSheet, - onCreateCustomList: () -> Unit, - onEditCustomLists: () -> Unit, - closeBottomSheet: (animate: Boolean) -> Unit, -) { - - MullvadModalBottomSheet( - sheetState = sheetState, - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - onDismissRequest = { closeBottomSheet(false) }, - modifier = Modifier.testTag(SELECT_LOCATION_CUSTOM_LIST_BOTTOM_SHEET_TEST_TAG), - ) { - HeaderCell( - text = stringResource(id = R.string.edit_custom_lists), - background = backgroundColor, - ) - HorizontalDivider(color = onBackgroundColor) - IconCell( - imageVector = Icons.Default.Add, - title = stringResource(id = R.string.new_list), - titleColor = onBackgroundColor, - onClick = { - onCreateCustomList() - closeBottomSheet(true) - }, - background = backgroundColor, - ) - IconCell( - imageVector = Icons.Default.Edit, - title = stringResource(id = R.string.edit_lists), - titleColor = - onBackgroundColor.copy( - alpha = - if (bottomSheetState.editListEnabled) { - AlphaVisible - } else { - AlphaInactive - } - ), - onClick = { - onEditCustomLists() - closeBottomSheet(true) - }, - background = backgroundColor, - enabled = bottomSheetState.editListEnabled, - ) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun LocationBottomSheet( - backgroundColor: Color, - onBackgroundColor: Color, - sheetState: SheetState, - customLists: List, - item: RelayItem.Location, - onCreateCustomList: (relayItem: RelayItem.Location) -> Unit, - onAddLocationToList: (location: RelayItem.Location, customList: RelayItem.CustomList) -> Unit, - closeBottomSheet: (animate: Boolean) -> Unit, -) { - MullvadModalBottomSheet( - sheetState = sheetState, - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - onDismissRequest = { closeBottomSheet(false) }, - modifier = Modifier.testTag(SELECT_LOCATION_LOCATION_BOTTOM_SHEET_TEST_TAG), - ) { -> - HeaderCell( - text = stringResource(id = R.string.add_location_to_list, item.name), - background = backgroundColor, - ) - HorizontalDivider(color = onBackgroundColor) - customLists.forEach { - val enabled = it.canAddLocation(item) - IconCell( - imageVector = null, - title = - if (enabled) { - it.name - } else { - stringResource(id = R.string.location_added, it.name) - }, - titleColor = - if (enabled) { - onBackgroundColor - } else { - MaterialTheme.colorScheme.onSurfaceVariant - }, - onClick = { - onAddLocationToList(item, it) - closeBottomSheet(true) - }, - background = backgroundColor, - enabled = enabled, - ) - } - IconCell( - imageVector = Icons.Default.Add, - title = stringResource(id = R.string.new_list), - titleColor = onBackgroundColor, - onClick = { - onCreateCustomList(item) - closeBottomSheet(true) - }, - background = backgroundColor, - ) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun EditCustomListBottomSheet( - backgroundColor: Color, - onBackgroundColor: Color, - sheetState: SheetState, - customList: RelayItem.CustomList, - onEditName: (item: RelayItem.CustomList) -> Unit, - onEditLocations: (item: RelayItem.CustomList) -> Unit, - onDeleteCustomList: (item: RelayItem.CustomList) -> Unit, - closeBottomSheet: (animate: Boolean) -> Unit, -) { - MullvadModalBottomSheet( - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - sheetState = sheetState, - onDismissRequest = { closeBottomSheet(false) }, - ) { - HeaderCell(text = customList.name, background = backgroundColor) - HorizontalDivider(color = onBackgroundColor) - IconCell( - imageVector = Icons.Default.Edit, - title = stringResource(id = R.string.edit_name), - titleColor = onBackgroundColor, - onClick = { - onEditName(customList) - closeBottomSheet(true) - }, - background = backgroundColor, - ) - IconCell( - imageVector = Icons.Default.Add, - title = stringResource(id = R.string.edit_locations), - titleColor = onBackgroundColor, - onClick = { - onEditLocations(customList) - closeBottomSheet(true) - }, - background = backgroundColor, - ) - IconCell( - imageVector = Icons.Default.Delete, - title = stringResource(id = R.string.delete), - titleColor = onBackgroundColor, - onClick = { - onDeleteCustomList(customList) - closeBottomSheet(true) - }, - background = backgroundColor, - ) - } -} - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun CustomListEntryBottomSheet( - backgroundColor: Color, - onBackgroundColor: Color, - sheetState: SheetState, - customListId: CustomListId, - customListName: CustomListName, - item: RelayItem.Location, - onRemoveLocationFromList: (location: RelayItem.Location, customListId: CustomListId) -> Unit, - closeBottomSheet: (animate: Boolean) -> Unit, -) { - MullvadModalBottomSheet( - sheetState = sheetState, - backgroundColor = backgroundColor, - onBackgroundColor = onBackgroundColor, - onDismissRequest = { closeBottomSheet(false) }, - modifier = Modifier.testTag(SELECT_LOCATION_LOCATION_BOTTOM_SHEET_TEST_TAG), - ) { - HeaderCell( - text = - stringResource(id = R.string.remove_location_from_list, item.name, customListName), - background = backgroundColor, - ) - HorizontalDivider(color = onBackgroundColor) - - IconCell( - imageVector = Icons.Default.Remove, - title = stringResource(id = R.string.remove_button), - titleColor = onBackgroundColor, - onClick = { - onRemoveLocationFromList(item, customListId) - closeBottomSheet(true) - }, - background = backgroundColor, - ) - } -} - -private suspend fun LazyListState.animateScrollAndCentralizeItem(index: Int) { - val itemInfo = this.layoutInfo.visibleItemsInfo.firstOrNull { it.index == index } - if (itemInfo != null) { - val center = layoutInfo.viewportEndOffset / 2 - val childCenter = itemInfo.offset + itemInfo.size / 2 - animateScrollBy((childCenter - center).toFloat()) - } else { - animateScrollToItem(index) - } -} - -private suspend fun SnackbarHostState.showResultSnackbar( - context: Context, - result: CustomListActionResultData, - onUndo: (CustomListAction) -> Unit, -) { - - showSnackbarImmediately( - message = result.message(context), - actionLabel = - if (result is CustomListActionResultData.Success) context.getString(R.string.undo) - else { - null - }, - duration = SnackbarDuration.Long, - onAction = { - if (result is CustomListActionResultData.Success) { - onUndo(result.undo) - } - }, - ) -} - -private fun CustomListActionResultData.message(context: Context): String = - when (this) { - is CustomListActionResultData.Success.CreatedWithLocations -> - if (locationNames.size == 1) { - context.getString( - R.string.location_was_added_to_list, - locationNames.first(), - customListName, - ) - } else { - context.getString(R.string.create_custom_list_message, customListName) - } - is CustomListActionResultData.Success.Deleted -> - context.getString(R.string.delete_custom_list_message, customListName) - is CustomListActionResultData.Success.LocationAdded -> - context.getString(R.string.location_was_added_to_list, locationName, customListName) - is CustomListActionResultData.Success.LocationRemoved -> - context.getString(R.string.location_was_removed_from_list, locationName, customListName) - is CustomListActionResultData.Success.LocationChanged -> - context.getString(R.string.locations_were_changed_for, customListName) - is CustomListActionResultData.Success.Renamed -> - context.getString(R.string.name_was_changed_to, newName) - CustomListActionResultData.GenericError -> context.getString(R.string.error_occurred) - } - -@Composable -private fun ResultRecipient - .OnCustomListNavResult( - snackbarHostState: SnackbarHostState, - performAction: (action: CustomListAction) -> Unit, -) { - val scope = rememberCoroutineScope() - val context = LocalContext.current - this.onNavResult { result -> - when (result) { - NavResult.Canceled -> { - /* Do nothing */ - } - is NavResult.Value -> { - // Handle result - scope.launch { - snackbarHostState.showResultSnackbar( - context = context, - result = result.value, - onUndo = performAction, - ) - } - } - } - } -} - -sealed interface BottomSheetState { - - data class ShowCustomListsBottomSheet(val editListEnabled: Boolean) : BottomSheetState - - data class ShowCustomListsEntryBottomSheet( - val customListId: CustomListId, - val customListName: CustomListName, - val item: RelayItem.Location, - ) : BottomSheetState - - data class ShowLocationBottomSheet( - val customLists: List, - val item: RelayItem.Location, - ) : BottomSheetState - - data class ShowEditCustomListBottomSheet(val customList: RelayItem.CustomList) : - BottomSheetState -} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt index 27beeeca4eff..b8c418cd0681 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SettingsScreen.kt @@ -26,6 +26,7 @@ import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootGraph import com.ramcosta.composedestinations.generated.destinations.ApiAccessListDestination import com.ramcosta.composedestinations.generated.destinations.AppInfoDestination +import com.ramcosta.composedestinations.generated.destinations.MultihopDestination import com.ramcosta.composedestinations.generated.destinations.ReportProblemDestination import com.ramcosta.composedestinations.generated.destinations.SplitTunnelingDestination import com.ramcosta.composedestinations.generated.destinations.VpnSettingsDestination @@ -49,7 +50,7 @@ import net.mullvad.mullvadvpn.viewmodel.SettingsViewModel import org.koin.androidx.compose.koinViewModel @OptIn(ExperimentalMaterial3Api::class) -@Preview("Supported|Unsupported") +@Preview("Supported|+") @Composable private fun PreviewSettingsScreen( @PreviewParameter(SettingsUiStatePreviewParameterProvider::class) state: SettingsUiState @@ -72,6 +73,7 @@ fun Settings(navigator: DestinationsNavigator) { onApiAccessClick = dropUnlessResumed { navigator.navigate(ApiAccessListDestination) }, onReportProblemCellClick = dropUnlessResumed { navigator.navigate(ReportProblemDestination) }, + onMultihopClick = dropUnlessResumed { navigator.navigate(MultihopDestination) }, onBackClick = dropUnlessResumed { navigator.navigateUp() }, ) } @@ -85,6 +87,7 @@ fun SettingsScreen( onAppInfoClick: () -> Unit = {}, onReportProblemCellClick: () -> Unit = {}, onApiAccessClick: () -> Unit = {}, + onMultihopClick: () -> Unit = {}, onBackClick: () -> Unit = {}, ) { ScaffoldWithMediumTopBar( @@ -96,8 +99,13 @@ fun SettingsScreen( state = lazyListState, ) { if (state.isLoggedIn) { - item { Spacer(modifier = Modifier.height(Dimens.cellLabelVerticalPadding)) } - item { + itemWithDivider { + MultihopCell( + isMultihopEnabled = state.multihopEnabled, + onMultihopClick = onMultihopClick, + ) + } + itemWithDivider { NavigationComposeCell( title = stringResource(id = R.string.settings_vpn), onClick = onVpnSettingCellClick, @@ -181,13 +189,12 @@ private fun FaqAndGuides() { NavigationComposeCell( title = faqGuideLabel, - bodyView = - @Composable { - DefaultExternalLinkView( - chevronContentDescription = faqGuideLabel, - tint = MaterialTheme.colorScheme.onPrimary, - ) - }, + bodyView = { + DefaultExternalLinkView( + chevronContentDescription = faqGuideLabel, + tint = MaterialTheme.colorScheme.onPrimary, + ) + }, onClick = openFaqAndGuides, ) } @@ -203,13 +210,29 @@ private fun PrivacyPolicy(state: SettingsUiState) { NavigationComposeCell( title = privacyPolicyLabel, - bodyView = - @Composable { - DefaultExternalLinkView( - chevronContentDescription = privacyPolicyLabel, - tint = MaterialTheme.colorScheme.onPrimary, - ) - }, + bodyView = { + DefaultExternalLinkView( + chevronContentDescription = privacyPolicyLabel, + tint = MaterialTheme.colorScheme.onPrimary, + ) + }, onClick = openPrivacyPolicy, ) } + +@Composable +private fun MultihopCell(isMultihopEnabled: Boolean, onMultihopClick: () -> Unit) { + val title = stringResource(id = R.string.multihop) + TwoRowCell( + titleText = title, + subtitleText = + stringResource( + if (isMultihopEnabled) { + R.string.on + } else { + R.string.off + } + ), + onCellClicked = onMultihopClick, + ) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/LocationBottomSheet.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/LocationBottomSheet.kt new file mode 100644 index 000000000000..7df4987d03f1 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/LocationBottomSheet.kt @@ -0,0 +1,426 @@ +package net.mullvad.mullvadvpn.compose.screen.location + +import android.content.Context +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add +import androidx.compose.material.icons.filled.Delete +import androidx.compose.material.icons.filled.Edit +import androidx.compose.material.icons.filled.Remove +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SheetState +import androidx.compose.material3.SnackbarDuration +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource +import com.ramcosta.composedestinations.result.NavResult +import com.ramcosta.composedestinations.result.ResultRecipient +import com.ramcosta.composedestinations.spec.DestinationSpec +import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.cell.HeaderCell +import net.mullvad.mullvadvpn.compose.cell.IconCell +import net.mullvad.mullvadvpn.compose.communication.CustomListAction +import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData +import net.mullvad.mullvadvpn.compose.component.MullvadModalBottomSheet +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowCustomListsBottomSheet +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowCustomListsEntryBottomSheet +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowEditCustomListBottomSheet +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowLocationBottomSheet +import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_CUSTOM_LIST_BOTTOM_SHEET_TEST_TAG +import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_LOCATION_BOTTOM_SHEET_TEST_TAG +import net.mullvad.mullvadvpn.compose.util.showSnackbarImmediately +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.CustomListName +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.theme.color.AlphaInactive +import net.mullvad.mullvadvpn.lib.theme.color.AlphaVisible +import net.mullvad.mullvadvpn.relaylist.canAddLocation + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +internal fun LocationBottomSheets( + locationBottomSheetState: LocationBottomSheetState?, + onCreateCustomList: (RelayItem.Location?) -> Unit, + onEditCustomLists: () -> Unit, + onAddLocationToList: (RelayItem.Location, RelayItem.CustomList) -> Unit, + onRemoveLocationFromList: (location: RelayItem.Location, parent: CustomListId) -> Unit, + onEditCustomListName: (RelayItem.CustomList) -> Unit, + onEditLocationsCustomList: (RelayItem.CustomList) -> Unit, + onDeleteCustomList: (RelayItem.CustomList) -> Unit, + onHideBottomSheet: () -> Unit, +) { + val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) + val scope = rememberCoroutineScope() + val onCloseBottomSheet: (animate: Boolean) -> Unit = { animate -> + if (animate) { + scope.launch { sheetState.hide() }.invokeOnCompletion { onHideBottomSheet() } + } else { + onHideBottomSheet() + } + } + val backgroundColor: Color = MaterialTheme.colorScheme.surfaceContainer + val onBackgroundColor: Color = MaterialTheme.colorScheme.onSurface + + when (locationBottomSheetState) { + is ShowCustomListsBottomSheet -> { + CustomListsBottomSheet( + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + sheetState = sheetState, + bottomSheetState = locationBottomSheetState, + onCreateCustomList = { onCreateCustomList(null) }, + onEditCustomLists = onEditCustomLists, + closeBottomSheet = onCloseBottomSheet, + ) + } + is ShowLocationBottomSheet -> { + LocationBottomSheet( + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + sheetState = sheetState, + customLists = locationBottomSheetState.customLists, + item = locationBottomSheetState.item, + onCreateCustomList = onCreateCustomList, + onAddLocationToList = onAddLocationToList, + closeBottomSheet = onCloseBottomSheet, + ) + } + is ShowEditCustomListBottomSheet -> { + EditCustomListBottomSheet( + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + sheetState = sheetState, + customList = locationBottomSheetState.customList, + onEditName = onEditCustomListName, + onEditLocations = onEditLocationsCustomList, + onDeleteCustomList = onDeleteCustomList, + closeBottomSheet = onCloseBottomSheet, + ) + } + is ShowCustomListsEntryBottomSheet -> { + CustomListEntryBottomSheet( + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + sheetState = sheetState, + customListId = locationBottomSheetState.customListId, + customListName = locationBottomSheetState.customListName, + item = locationBottomSheetState.item, + onRemoveLocationFromList = onRemoveLocationFromList, + closeBottomSheet = onCloseBottomSheet, + ) + } + null -> { + /* Do nothing */ + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun CustomListsBottomSheet( + backgroundColor: Color, + onBackgroundColor: Color, + sheetState: SheetState, + bottomSheetState: ShowCustomListsBottomSheet, + onCreateCustomList: () -> Unit, + onEditCustomLists: () -> Unit, + closeBottomSheet: (animate: Boolean) -> Unit, +) { + + MullvadModalBottomSheet( + sheetState = sheetState, + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + onDismissRequest = { closeBottomSheet(false) }, + modifier = Modifier.testTag(SELECT_LOCATION_CUSTOM_LIST_BOTTOM_SHEET_TEST_TAG), + ) { + HeaderCell( + text = stringResource(id = R.string.edit_custom_lists), + background = backgroundColor, + ) + HorizontalDivider(color = onBackgroundColor) + IconCell( + imageVector = Icons.Default.Add, + title = stringResource(id = R.string.new_list), + titleColor = onBackgroundColor, + onClick = { + onCreateCustomList() + closeBottomSheet(true) + }, + background = backgroundColor, + ) + IconCell( + imageVector = Icons.Default.Edit, + title = stringResource(id = R.string.edit_lists), + titleColor = + onBackgroundColor.copy( + alpha = + if (bottomSheetState.editListEnabled) { + AlphaVisible + } else { + AlphaInactive + } + ), + onClick = { + onEditCustomLists() + closeBottomSheet(true) + }, + background = backgroundColor, + enabled = bottomSheetState.editListEnabled, + ) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun LocationBottomSheet( + backgroundColor: Color, + onBackgroundColor: Color, + sheetState: SheetState, + customLists: List, + item: RelayItem.Location, + onCreateCustomList: (relayItem: RelayItem.Location) -> Unit, + onAddLocationToList: (location: RelayItem.Location, customList: RelayItem.CustomList) -> Unit, + closeBottomSheet: (animate: Boolean) -> Unit, +) { + MullvadModalBottomSheet( + sheetState = sheetState, + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + onDismissRequest = { closeBottomSheet(false) }, + modifier = Modifier.testTag(SELECT_LOCATION_LOCATION_BOTTOM_SHEET_TEST_TAG), + ) { -> + HeaderCell( + text = stringResource(id = R.string.add_location_to_list, item.name), + background = backgroundColor, + ) + HorizontalDivider(color = onBackgroundColor) + customLists.forEach { + val enabled = it.canAddLocation(item) + IconCell( + imageVector = null, + title = + if (enabled) { + it.name + } else { + stringResource(id = R.string.location_added, it.name) + }, + titleColor = + if (enabled) { + onBackgroundColor + } else { + MaterialTheme.colorScheme.onSurfaceVariant + }, + onClick = { + onAddLocationToList(item, it) + closeBottomSheet(true) + }, + background = backgroundColor, + enabled = enabled, + ) + } + IconCell( + imageVector = Icons.Default.Add, + title = stringResource(id = R.string.new_list), + titleColor = onBackgroundColor, + onClick = { + onCreateCustomList(item) + closeBottomSheet(true) + }, + background = backgroundColor, + ) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun EditCustomListBottomSheet( + backgroundColor: Color, + onBackgroundColor: Color, + sheetState: SheetState, + customList: RelayItem.CustomList, + onEditName: (item: RelayItem.CustomList) -> Unit, + onEditLocations: (item: RelayItem.CustomList) -> Unit, + onDeleteCustomList: (item: RelayItem.CustomList) -> Unit, + closeBottomSheet: (animate: Boolean) -> Unit, +) { + MullvadModalBottomSheet( + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + sheetState = sheetState, + onDismissRequest = { closeBottomSheet(false) }, + ) { + HeaderCell(text = customList.name, background = backgroundColor) + HorizontalDivider(color = onBackgroundColor) + IconCell( + imageVector = Icons.Default.Edit, + title = stringResource(id = R.string.edit_name), + titleColor = onBackgroundColor, + onClick = { + onEditName(customList) + closeBottomSheet(true) + }, + background = backgroundColor, + ) + IconCell( + imageVector = Icons.Default.Add, + title = stringResource(id = R.string.edit_locations), + titleColor = onBackgroundColor, + onClick = { + onEditLocations(customList) + closeBottomSheet(true) + }, + background = backgroundColor, + ) + IconCell( + imageVector = Icons.Default.Delete, + title = stringResource(id = R.string.delete), + titleColor = onBackgroundColor, + onClick = { + onDeleteCustomList(customList) + closeBottomSheet(true) + }, + background = backgroundColor, + ) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun CustomListEntryBottomSheet( + backgroundColor: Color, + onBackgroundColor: Color, + sheetState: SheetState, + customListId: CustomListId, + customListName: CustomListName, + item: RelayItem.Location, + onRemoveLocationFromList: (location: RelayItem.Location, customListId: CustomListId) -> Unit, + closeBottomSheet: (animate: Boolean) -> Unit, +) { + MullvadModalBottomSheet( + sheetState = sheetState, + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + onDismissRequest = { closeBottomSheet(false) }, + modifier = Modifier.testTag(SELECT_LOCATION_LOCATION_BOTTOM_SHEET_TEST_TAG), + ) { + HeaderCell( + text = + stringResource(id = R.string.remove_location_from_list, item.name, customListName), + background = backgroundColor, + ) + HorizontalDivider(color = onBackgroundColor) + + IconCell( + imageVector = Icons.Default.Remove, + title = stringResource(id = R.string.remove_button), + titleColor = onBackgroundColor, + onClick = { + onRemoveLocationFromList(item, customListId) + closeBottomSheet(true) + }, + background = backgroundColor, + ) + } +} + +internal suspend fun SnackbarHostState.showResultSnackbar( + context: Context, + result: CustomListActionResultData, + onUndo: (CustomListAction) -> Unit, +) { + + showSnackbarImmediately( + message = result.message(context), + actionLabel = + if (result is CustomListActionResultData.Success) context.getString(R.string.undo) + else { + null + }, + duration = SnackbarDuration.Long, + onAction = { + if (result is CustomListActionResultData.Success) { + onUndo(result.undo) + } + }, + ) +} + +private fun CustomListActionResultData.message(context: Context): String = + when (this) { + is CustomListActionResultData.Success.CreatedWithLocations -> + if (locationNames.size == 1) { + context.getString( + R.string.location_was_added_to_list, + locationNames.first(), + customListName, + ) + } else { + context.getString(R.string.create_custom_list_message, customListName) + } + is CustomListActionResultData.Success.Deleted -> + context.getString(R.string.delete_custom_list_message, customListName) + is CustomListActionResultData.Success.LocationAdded -> + context.getString(R.string.location_was_added_to_list, locationName, customListName) + is CustomListActionResultData.Success.LocationRemoved -> + context.getString(R.string.location_was_removed_from_list, locationName, customListName) + is CustomListActionResultData.Success.LocationChanged -> + context.getString(R.string.locations_were_changed_for, customListName) + is CustomListActionResultData.Success.Renamed -> + context.getString(R.string.name_was_changed_to, newName) + CustomListActionResultData.GenericError -> context.getString(R.string.error_occurred) + } + +@Composable +internal fun ResultRecipient + .OnCustomListNavResult( + snackbarHostState: SnackbarHostState, + performAction: (action: CustomListAction) -> Unit, +) { + val scope = rememberCoroutineScope() + val context = LocalContext.current + this.onNavResult { result -> + when (result) { + NavResult.Canceled -> { + /* Do nothing */ + } + is NavResult.Value -> { + // Handle result + scope.launch { + snackbarHostState.showResultSnackbar( + context = context, + result = result.value, + onUndo = performAction, + ) + } + } + } + } +} + +sealed interface LocationBottomSheetState { + + data class ShowCustomListsBottomSheet(val editListEnabled: Boolean) : LocationBottomSheetState + + data class ShowCustomListsEntryBottomSheet( + val customListId: CustomListId, + val customListName: CustomListName, + val item: RelayItem.Location, + ) : LocationBottomSheetState + + data class ShowLocationBottomSheet( + val customLists: List, + val item: RelayItem.Location, + ) : LocationBottomSheetState + + data class ShowEditCustomListBottomSheet(val customList: RelayItem.CustomList) : + LocationBottomSheetState +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListContent.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListContent.kt new file mode 100644 index 000000000000..62eeb38892a1 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListContent.kt @@ -0,0 +1,196 @@ +package net.mullvad.mullvadvpn.compose.screen.location + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.lazy.LazyItemScope +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.cell.HeaderCell +import net.mullvad.mullvadvpn.compose.cell.StatusRelayItemCell +import net.mullvad.mullvadvpn.compose.cell.SwitchComposeSubtitleCell +import net.mullvad.mullvadvpn.compose.cell.ThreeDotCell +import net.mullvad.mullvadvpn.compose.component.LocationsEmptyText +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowCustomListsBottomSheet +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowCustomListsEntryBottomSheet +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowEditCustomListBottomSheet +import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowLocationBottomSheet +import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.test.LOCATION_CELL_TEST_TAG +import net.mullvad.mullvadvpn.compose.test.SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.model.RelayItemId + +/** Used by both the select location screen and search select location screen */ +fun LazyListScope.relayListContent( + backgroundColor: Color, + relayListItems: List, + customLists: List, + onSelectRelay: (RelayItem) -> Unit, + onToggleExpand: (RelayItemId, CustomListId?, Boolean) -> Unit, + onUpdateBottomSheetState: (LocationBottomSheetState) -> Unit, + customListHeader: @Composable LazyItemScope.() -> Unit = { + CustomListHeader( + onShowCustomListBottomSheet = { + onUpdateBottomSheetState( + ShowCustomListsBottomSheet(editListEnabled = customLists.isNotEmpty()) + ) + } + ) + }, + locationHeader: @Composable LazyItemScope.() -> Unit = { RelayLocationHeader() }, +) { + itemsIndexed( + items = relayListItems, + key = { _: Int, item: RelayListItem -> item.key }, + contentType = { _, item -> item.contentType }, + itemContent = { index: Int, listItem: RelayListItem -> + Column(modifier = Modifier.animateItem()) { + if (index != 0) { + HorizontalDivider(color = backgroundColor) + } + when (listItem) { + RelayListItem.CustomListHeader -> customListHeader() + is RelayListItem.CustomListItem -> + CustomListItem( + listItem, + onSelectRelay, + { onUpdateBottomSheetState(ShowEditCustomListBottomSheet(it)) }, + { customListId, expand -> onToggleExpand(customListId, null, expand) }, + ) + is RelayListItem.CustomListEntryItem -> + CustomListEntryItem( + listItem, + { onSelectRelay(listItem.item) }, + // Only direct children can be removed + if (listItem.depth == 1) { + { + onUpdateBottomSheetState( + ShowCustomListsEntryBottomSheet( + listItem.parentId, + listItem.parentName, + listItem.item, + ) + ) + } + } else { + null + }, + { expand: Boolean -> + onToggleExpand(listItem.item.id, listItem.parentId, expand) + }, + ) + is RelayListItem.CustomListFooter -> CustomListFooter(listItem) + RelayListItem.LocationHeader -> locationHeader() + is RelayListItem.GeoLocationItem -> + RelayLocationItem( + listItem, + { onSelectRelay(listItem.item) }, + { + onUpdateBottomSheetState( + ShowLocationBottomSheet(customLists, listItem.item) + ) + }, + { expand -> onToggleExpand(listItem.item.id, null, expand) }, + ) + is RelayListItem.LocationsEmptyText -> LocationsEmptyText(listItem.searchTerm) + } + } + }, + ) +} + +@Composable +private fun LazyItemScope.RelayLocationItem( + relayItem: RelayListItem.GeoLocationItem, + onSelectRelay: () -> Unit, + onLongClick: () -> Unit, + onExpand: (Boolean) -> Unit, +) { + val location = relayItem.item + StatusRelayItemCell( + item = location, + state = relayItem.state, + isSelected = relayItem.isSelected, + onClick = { onSelectRelay() }, + onLongClick = { onLongClick() }, + onToggleExpand = { onExpand(it) }, + isExpanded = relayItem.expanded, + depth = relayItem.depth, + modifier = Modifier.testTag(LOCATION_CELL_TEST_TAG), + ) +} + +@Composable +private fun LazyItemScope.CustomListEntryItem( + itemState: RelayListItem.CustomListEntryItem, + onSelectRelay: () -> Unit, + onShowEditCustomListEntryBottomSheet: (() -> Unit)?, + onToggleExpand: (Boolean) -> Unit, +) { + val customListEntryItem = itemState.item + StatusRelayItemCell( + item = customListEntryItem, + state = itemState.state, + isSelected = false, + onClick = onSelectRelay, + onLongClick = onShowEditCustomListEntryBottomSheet, + onToggleExpand = onToggleExpand, + isExpanded = itemState.expanded, + depth = itemState.depth, + ) +} + +@Composable +private fun LazyItemScope.CustomListItem( + itemState: RelayListItem.CustomListItem, + onSelectRelay: (item: RelayItem) -> Unit, + onShowEditBottomSheet: (RelayItem.CustomList) -> Unit, + onExpand: ((CustomListId, Boolean) -> Unit), +) { + val customListItem = itemState.item + StatusRelayItemCell( + item = customListItem, + state = itemState.state, + isSelected = itemState.isSelected, + onClick = { onSelectRelay(customListItem) }, + onLongClick = { onShowEditBottomSheet(customListItem) }, + onToggleExpand = { onExpand(customListItem.id, it) }, + isExpanded = itemState.expanded, + ) +} + +@Composable +private fun LazyItemScope.CustomListHeader(onShowCustomListBottomSheet: () -> Unit) { + ThreeDotCell( + text = stringResource(R.string.custom_lists), + onClickDots = onShowCustomListBottomSheet, + modifier = Modifier.testTag(SELECT_LOCATION_CUSTOM_LIST_HEADER_TEST_TAG), + ) +} + +@Composable +private fun LazyItemScope.CustomListFooter(item: RelayListItem.CustomListFooter) { + SwitchComposeSubtitleCell( + text = + if (item.hasCustomList) { + stringResource(R.string.to_add_locations_to_a_list) + } else { + stringResource(R.string.to_create_a_custom_list) + }, + modifier = Modifier.background(MaterialTheme.colorScheme.surface), + ) +} + +@Composable +private fun LazyItemScope.RelayLocationHeader() { + HeaderCell(text = stringResource(R.string.all_locations)) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt new file mode 100644 index 000000000000..fc810e68827b --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt @@ -0,0 +1,401 @@ +package net.mullvad.mullvadvpn.compose.screen.location + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.filled.Close +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.SearchBarDefaults +import androidx.compose.material3.SnackbarHost +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.material3.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +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.LocalSoftwareKeyboardController +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.compose.dropUnlessResumed +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.CreateCustomListDestination +import com.ramcosta.composedestinations.generated.destinations.CustomListLocationsDestination +import com.ramcosta.composedestinations.generated.destinations.CustomListsDestination +import com.ramcosta.composedestinations.generated.destinations.DeleteCustomListDestination +import com.ramcosta.composedestinations.generated.destinations.EditCustomListNameDestination +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import com.ramcosta.composedestinations.result.ResultBackNavigator +import com.ramcosta.composedestinations.result.ResultRecipient +import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.cell.FilterRow +import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData +import net.mullvad.mullvadvpn.compose.component.MullvadSnackbar +import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar +import net.mullvad.mullvadvpn.compose.constant.ContentType +import net.mullvad.mullvadvpn.compose.extensions.dropUnlessResumed +import net.mullvad.mullvadvpn.compose.preview.SearchLocationsUiStatePreviewParameterProvider +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState +import net.mullvad.mullvadvpn.compose.transitions.TopLevelTransition +import net.mullvad.mullvadvpn.compose.util.CollectSideEffectWithLifecycle +import net.mullvad.mullvadvpn.compose.util.showSnackbarImmediately +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.model.RelayItemId +import net.mullvad.mullvadvpn.lib.theme.AppTheme +import net.mullvad.mullvadvpn.lib.theme.Dimens +import net.mullvad.mullvadvpn.lib.theme.color.AlphaScrollbar +import net.mullvad.mullvadvpn.usecase.FilterChip +import net.mullvad.mullvadvpn.viewmodel.location.SearchLocationSideEffect +import net.mullvad.mullvadvpn.viewmodel.location.SearchLocationViewModel +import org.koin.androidx.compose.koinViewModel + +@Preview("Default|Not found|Results") +@Composable +private fun PreviewSearchLocationScreen( + @PreviewParameter(SearchLocationsUiStatePreviewParameterProvider::class) + state: SearchLocationUiState +) { + AppTheme { SearchLocationScreen(state = state) } +} + +data class SearchLocationNavArgs(val relayListType: RelayListType) + +@Suppress("LongMethod") +@Composable +@Destination(style = TopLevelTransition::class, navArgs = SearchLocationNavArgs::class) +fun SearchLocation( + navigator: DestinationsNavigator, + backNavigator: ResultBackNavigator, + createCustomListDialogResultRecipient: + ResultRecipient< + CreateCustomListDestination, + CustomListActionResultData.Success.CreatedWithLocations, + >, + editCustomListNameDialogResultRecipient: + ResultRecipient, + deleteCustomListDialogResultRecipient: + ResultRecipient, + updateCustomListResultRecipient: + ResultRecipient, +) { + val viewModel = koinViewModel() + val state by viewModel.uiState.collectAsStateWithLifecycle() + + val snackbarHostState = remember { SnackbarHostState() } + val context = LocalContext.current + + CollectSideEffectWithLifecycle(viewModel.uiSideEffect) { + when (it) { + is SearchLocationSideEffect.LocationSelected -> + backNavigator.navigateBack(result = it.relayListType) + is SearchLocationSideEffect.CustomListActionToast -> + launch { + snackbarHostState.showResultSnackbar( + context = context, + result = it.resultData, + onUndo = viewModel::performAction, + ) + } + SearchLocationSideEffect.GenericError -> + launch { + snackbarHostState.showSnackbarImmediately( + message = context.getString(R.string.error_occurred) + ) + } + } + } + + createCustomListDialogResultRecipient.OnCustomListNavResult( + snackbarHostState, + viewModel::performAction, + ) + + editCustomListNameDialogResultRecipient.OnCustomListNavResult( + snackbarHostState, + viewModel::performAction, + ) + + deleteCustomListDialogResultRecipient.OnCustomListNavResult( + snackbarHostState, + viewModel::performAction, + ) + + updateCustomListResultRecipient.OnCustomListNavResult( + snackbarHostState, + viewModel::performAction, + ) + + SearchLocationScreen( + state = state, + snackbarHostState = snackbarHostState, + onSelectRelay = viewModel::selectRelay, + onToggleExpand = viewModel::onToggleExpand, + onSearchInputChanged = viewModel::onSearchInputUpdated, + onCreateCustomList = + dropUnlessResumed { relayItem -> + navigator.navigate(CreateCustomListDestination(locationCode = relayItem?.id)) + }, + onEditCustomLists = dropUnlessResumed { navigator.navigate(CustomListsDestination()) }, + onAddLocationToList = viewModel::addLocationToList, + onRemoveLocationFromList = viewModel::removeLocationFromList, + onEditCustomListName = + dropUnlessResumed { customList: RelayItem.CustomList -> + navigator.navigate( + EditCustomListNameDestination( + customListId = customList.id, + initialName = customList.customList.name, + ) + ) + }, + onEditLocationsCustomList = + dropUnlessResumed { customList: RelayItem.CustomList -> + navigator.navigate( + CustomListLocationsDestination(customListId = customList.id, newList = false) + ) + }, + onDeleteCustomList = + dropUnlessResumed { customList: RelayItem.CustomList -> + navigator.navigate( + DeleteCustomListDestination( + customListId = customList.id, + name = customList.customList.name, + ) + ) + }, + onRemoveOwnershipFilter = viewModel::removeOwnerFilter, + onRemoveProviderFilter = viewModel::removeProviderFilter, + onGoBack = dropUnlessResumed { navigator.navigateUp() }, + ) +} + +@Suppress("LongMethod") +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SearchLocationScreen( + state: SearchLocationUiState, + snackbarHostState: SnackbarHostState = SnackbarHostState(), + onSelectRelay: (RelayItem) -> Unit = {}, + onToggleExpand: (RelayItemId, CustomListId?, Boolean) -> Unit = { _, _, _ -> }, + onSearchInputChanged: (String) -> Unit = {}, + onCreateCustomList: (location: RelayItem.Location?) -> Unit = {}, + onEditCustomLists: () -> Unit = {}, + onAddLocationToList: (location: RelayItem.Location, customList: RelayItem.CustomList) -> Unit = + { _, _ -> + }, + onRemoveLocationFromList: (location: RelayItem.Location, customListId: CustomListId) -> Unit = + { _, _ -> + }, + onEditCustomListName: (RelayItem.CustomList) -> Unit = {}, + onEditLocationsCustomList: (RelayItem.CustomList) -> Unit = {}, + onDeleteCustomList: (RelayItem.CustomList) -> Unit = {}, + onRemoveOwnershipFilter: () -> Unit = {}, + onRemoveProviderFilter: () -> Unit = {}, + onGoBack: () -> Unit = {}, +) { + val backgroundColor = MaterialTheme.colorScheme.surface + val onBackgroundColor = MaterialTheme.colorScheme.onSurface + val keyboardController = LocalSoftwareKeyboardController.current + Scaffold( + snackbarHost = { + SnackbarHost( + snackbarHostState, + snackbar = { snackbarData -> MullvadSnackbar(snackbarData = snackbarData) }, + ) + } + ) { + var locationBottomSheetState by remember { mutableStateOf(null) } + LocationBottomSheets( + locationBottomSheetState = locationBottomSheetState, + onCreateCustomList = onCreateCustomList, + onEditCustomLists = onEditCustomLists, + onAddLocationToList = onAddLocationToList, + onRemoveLocationFromList = onRemoveLocationFromList, + onEditCustomListName = onEditCustomListName, + onEditLocationsCustomList = onEditLocationsCustomList, + onDeleteCustomList = onDeleteCustomList, + onHideBottomSheet = { locationBottomSheetState = null }, + ) + Column(modifier = Modifier.padding(it)) { + SearchBar( + searchTerm = state.searchTerm, + backgroundColor = backgroundColor, + onBackgroundColor = onBackgroundColor, + onSearchInputChanged = onSearchInputChanged, + hideKeyboard = { keyboardController?.hide() }, + onGoBack = onGoBack, + ) + HorizontalDivider(color = onBackgroundColor) + val lazyListState = rememberLazyListState() + LazyColumn( + modifier = + Modifier.fillMaxSize() + .background(color = backgroundColor) + .drawVerticalScrollbar( + lazyListState, + MaterialTheme.colorScheme.onSurface.copy(alpha = AlphaScrollbar), + ), + state = lazyListState, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + filterRow( + filters = state.filterChips, + onBackgroundColor = onBackgroundColor, + onRemoveOwnershipFilter = onRemoveOwnershipFilter, + onRemoveProviderFilter = onRemoveProviderFilter, + ) + when (state) { + is SearchLocationUiState.NoQuery -> { + noQuery() + } + is SearchLocationUiState.Content -> { + relayListContent( + backgroundColor = backgroundColor, + customLists = state.customLists, + relayListItems = state.relayListItems, + onSelectRelay = onSelectRelay, + onToggleExpand = onToggleExpand, + onUpdateBottomSheetState = { newSheetState -> + locationBottomSheetState = newSheetState + }, + customListHeader = { + Title( + text = stringResource(R.string.custom_lists), + onBackgroundColor = onBackgroundColor, + ) + }, + locationHeader = { + Title( + text = stringResource(R.string.locations), + onBackgroundColor = onBackgroundColor, + ) + }, + ) + } + } + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun SearchBar( + searchTerm: String, + backgroundColor: Color, + onBackgroundColor: Color, + onSearchInputChanged: (String) -> Unit, + hideKeyboard: () -> Unit, + onGoBack: () -> Unit, +) { + SearchBarDefaults.InputField( + modifier = Modifier.height(Dimens.searchFieldHeightExpanded).fillMaxWidth(), + query = searchTerm, + onQueryChange = onSearchInputChanged, + onSearch = { hideKeyboard() }, + expanded = true, + onExpandedChange = {}, + leadingIcon = { + IconButton(onClick = onGoBack) { + Icon( + imageVector = Icons.AutoMirrored.Default.ArrowBack, + contentDescription = stringResource(R.string.back), + ) + } + }, + trailingIcon = { + if (searchTerm.isNotEmpty()) { + IconButton(onClick = { onSearchInputChanged("") }) { + Icon( + imageVector = Icons.Default.Close, + contentDescription = stringResource(R.string.clear_input), + ) + } + } + }, + placeholder = { Text(text = stringResource(id = R.string.search_placeholder)) }, + colors = + TextFieldDefaults.colors( + focusedContainerColor = backgroundColor, + unfocusedContainerColor = backgroundColor, + focusedPlaceholderColor = onBackgroundColor, + unfocusedPlaceholderColor = onBackgroundColor, + focusedTextColor = onBackgroundColor, + unfocusedTextColor = onBackgroundColor, + cursorColor = onBackgroundColor, + focusedLeadingIconColor = onBackgroundColor, + unfocusedLeadingIconColor = onBackgroundColor, + focusedTrailingIconColor = onBackgroundColor, + unfocusedTrailingIconColor = onBackgroundColor, + ), + ) +} + +private fun LazyListScope.noQuery() { + item(contentType = ContentType.DESCRIPTION) { + Text( + text = stringResource(R.string.search_query_empty), + style = MaterialTheme.typography.labelMedium, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(Dimens.mediumPadding), + ) + } +} + +private fun LazyListScope.filterRow( + filters: List, + onBackgroundColor: Color, + onRemoveOwnershipFilter: () -> Unit, + onRemoveProviderFilter: () -> Unit, +) { + if (filters.isNotEmpty()) { + item { + Title(text = stringResource(R.string.filters), onBackgroundColor = onBackgroundColor) + } + item { + FilterRow( + filters = filters, + showTitle = false, + onRemoveOwnershipFilter = onRemoveOwnershipFilter, + onRemoveProviderFilter = onRemoveProviderFilter, + ) + } + } +} + +@Composable +private fun Title(text: String, onBackgroundColor: Color) { + Text( + text = text, + color = onBackgroundColor, + modifier = + Modifier.fillMaxWidth() + .padding(horizontal = Dimens.sideMargin, vertical = Dimens.smallPadding), + style = MaterialTheme.typography.labelMedium, + ) +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationList.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationList.kt new file mode 100644 index 000000000000..8f07ab180e7b --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationList.kt @@ -0,0 +1,114 @@ +package net.mullvad.mullvadvpn.compose.screen.location + +import androidx.compose.foundation.gestures.animateScrollBy +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.testTag +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import net.mullvad.mullvadvpn.compose.component.MullvadCircularProgressIndicatorLarge +import net.mullvad.mullvadvpn.compose.component.drawVerticalScrollbar +import net.mullvad.mullvadvpn.compose.constant.ContentType +import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState +import net.mullvad.mullvadvpn.compose.test.CIRCULAR_PROGRESS_INDICATOR +import net.mullvad.mullvadvpn.compose.util.RunOnKeyChange +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.theme.color.AlphaScrollbar +import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationListViewModel +import org.koin.androidx.compose.koinViewModel +import org.koin.core.parameter.parametersOf + +@Composable +fun SelectLocationList( + backgroundColor: Color, + relayListType: RelayListType, + onSelectRelay: (RelayItem) -> Unit, + onUpdateBottomSheetState: (LocationBottomSheetState) -> Unit, +) { + val viewModel = + koinViewModel( + key = relayListType.name, + parameters = { parametersOf(relayListType) }, + ) + val state by viewModel.uiState.collectAsStateWithLifecycle() + val lazyListState = rememberLazyListState() + val stateActual = state + RunOnKeyChange(stateActual is SelectLocationListUiState.Content) { + stateActual.indexOfSelectedRelayItem()?.let { index -> + lazyListState.scrollToItem(index) + lazyListState.animateScrollAndCentralizeItem(index) + } + } + LazyColumn( + modifier = + Modifier.fillMaxSize() + .drawVerticalScrollbar( + lazyListState, + MaterialTheme.colorScheme.onSurface.copy(alpha = AlphaScrollbar), + ), + state = lazyListState, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + when (stateActual) { + SelectLocationListUiState.Loading -> { + loading() + } + is SelectLocationListUiState.Content -> { + relayListContent( + backgroundColor = backgroundColor, + relayListItems = stateActual.relayListItems, + customLists = stateActual.customLists, + onSelectRelay = onSelectRelay, + onToggleExpand = viewModel::onToggleExpand, + onUpdateBottomSheetState = onUpdateBottomSheetState, + ) + } + } + } +} + +private fun LazyListScope.loading() { + item(contentType = ContentType.PROGRESS) { + MullvadCircularProgressIndicatorLarge(Modifier.testTag(CIRCULAR_PROGRESS_INDICATOR)) + } +} + +private fun SelectLocationListUiState.indexOfSelectedRelayItem(): Int? = + if (this is SelectLocationListUiState.Content) { + val index = + relayListItems.indexOfFirst { + when (it) { + is RelayListItem.CustomListItem -> it.isSelected + is RelayListItem.GeoLocationItem -> it.isSelected + is RelayListItem.CustomListEntryItem, + is RelayListItem.CustomListFooter, + RelayListItem.CustomListHeader, + RelayListItem.LocationHeader, + is RelayListItem.LocationsEmptyText -> false + } + } + if (index >= 0) index else null + } else { + null + } + +private suspend fun LazyListState.animateScrollAndCentralizeItem(index: Int) { + val itemInfo = this.layoutInfo.visibleItemsInfo.firstOrNull { it.index == index } + if (itemInfo != null) { + val center = layoutInfo.viewportEndOffset / 2 + val childCenter = itemInfo.offset + itemInfo.size / 2 + animateScrollBy((childCenter - center).toFloat()) + } else { + animateScrollToItem(index) + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt new file mode 100644 index 000000000000..5ad5eb1507b2 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt @@ -0,0 +1,352 @@ +package net.mullvad.mullvadvpn.compose.screen.location + +import android.annotation.SuppressLint +import androidx.compose.animation.AnimatedContent +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.pager.HorizontalPager +import androidx.compose.foundation.pager.rememberPagerState +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close +import androidx.compose.material.icons.filled.FilterList +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.material3.SnackbarHostState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +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.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.lifecycle.compose.dropUnlessResumed +import com.ramcosta.composedestinations.annotation.Destination +import com.ramcosta.composedestinations.annotation.RootGraph +import com.ramcosta.composedestinations.generated.destinations.CreateCustomListDestination +import com.ramcosta.composedestinations.generated.destinations.CustomListLocationsDestination +import com.ramcosta.composedestinations.generated.destinations.CustomListsDestination +import com.ramcosta.composedestinations.generated.destinations.DeleteCustomListDestination +import com.ramcosta.composedestinations.generated.destinations.EditCustomListNameDestination +import com.ramcosta.composedestinations.generated.destinations.FilterDestination +import com.ramcosta.composedestinations.generated.destinations.SearchLocationDestination +import com.ramcosta.composedestinations.navigation.DestinationsNavigator +import com.ramcosta.composedestinations.result.ResultBackNavigator +import com.ramcosta.composedestinations.result.ResultRecipient +import com.ramcosta.composedestinations.result.onResult +import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.R +import net.mullvad.mullvadvpn.compose.button.MullvadSegmentedEndButton +import net.mullvad.mullvadvpn.compose.button.MullvadSegmentedStartButton +import net.mullvad.mullvadvpn.compose.cell.FilterRow +import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData +import net.mullvad.mullvadvpn.compose.component.ScaffoldWithSmallTopBar +import net.mullvad.mullvadvpn.compose.extensions.dropUnlessResumed +import net.mullvad.mullvadvpn.compose.preview.SelectLocationsUiStatePreviewParameterProvider +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState +import net.mullvad.mullvadvpn.compose.transitions.TopLevelTransition +import net.mullvad.mullvadvpn.compose.util.CollectSideEffectWithLifecycle +import net.mullvad.mullvadvpn.compose.util.showSnackbarImmediately +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.theme.AppTheme +import net.mullvad.mullvadvpn.lib.theme.Dimens +import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationSideEffect +import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationViewModel +import org.koin.androidx.compose.koinViewModel + +@Preview("Default|Filters|Multihop|Multihop and Filters") +@Composable +private fun PreviewSelectLocationScreen( + @PreviewParameter(SelectLocationsUiStatePreviewParameterProvider::class) + state: SelectLocationUiState +) { + AppTheme { SelectLocationScreen(state = state) } +} + +@SuppressLint("CheckResult") +@Destination(style = TopLevelTransition::class) +@Suppress("LongMethod") +@Composable +fun SelectLocation( + navigator: DestinationsNavigator, + backNavigator: ResultBackNavigator, + createCustomListDialogResultRecipient: + ResultRecipient< + CreateCustomListDestination, + CustomListActionResultData.Success.CreatedWithLocations, + >, + editCustomListNameDialogResultRecipient: + ResultRecipient, + deleteCustomListDialogResultRecipient: + ResultRecipient, + updateCustomListResultRecipient: + ResultRecipient, + searchSelectedLocationResultRecipient: ResultRecipient, +) { + val vm = koinViewModel() + val state = vm.uiState.collectAsStateWithLifecycle() + + val snackbarHostState = remember { SnackbarHostState() } + val context = LocalContext.current + CollectSideEffectWithLifecycle(vm.uiSideEffect) { + when (it) { + SelectLocationSideEffect.CloseScreen -> backNavigator.navigateBack(result = true) + is SelectLocationSideEffect.CustomListActionToast -> + launch { + snackbarHostState.showResultSnackbar( + context = context, + result = it.resultData, + onUndo = vm::performAction, + ) + } + SelectLocationSideEffect.GenericError -> + launch { + snackbarHostState.showSnackbarImmediately( + message = context.getString(R.string.error_occurred) + ) + } + } + } + + createCustomListDialogResultRecipient.OnCustomListNavResult( + snackbarHostState, + vm::performAction, + ) + + editCustomListNameDialogResultRecipient.OnCustomListNavResult( + snackbarHostState, + vm::performAction, + ) + + deleteCustomListDialogResultRecipient.OnCustomListNavResult( + snackbarHostState, + vm::performAction, + ) + + updateCustomListResultRecipient.OnCustomListNavResult(snackbarHostState, vm::performAction) + + searchSelectedLocationResultRecipient.onResult { result -> + when (result) { + RelayListType.ENTRY -> { + vm.selectRelayList(RelayListType.EXIT) + } + RelayListType.EXIT -> backNavigator.navigateBack(result = true) + } + } + + SelectLocationScreen( + state = state.value, + snackbarHostState = snackbarHostState, + onSelectRelay = vm::selectRelay, + onSearchClick = { navigator.navigate(SearchLocationDestination(it)) }, + onBackClick = dropUnlessResumed { backNavigator.navigateBack() }, + onFilterClick = dropUnlessResumed { navigator.navigate(FilterDestination) }, + onCreateCustomList = + dropUnlessResumed { relayItem -> + navigator.navigate(CreateCustomListDestination(locationCode = relayItem?.id)) + }, + onEditCustomLists = dropUnlessResumed { navigator.navigate(CustomListsDestination()) }, + removeOwnershipFilter = vm::removeOwnerFilter, + removeProviderFilter = vm::removeProviderFilter, + onAddLocationToList = vm::addLocationToList, + onRemoveLocationFromList = vm::removeLocationFromList, + onEditCustomListName = + dropUnlessResumed { customList: RelayItem.CustomList -> + navigator.navigate( + EditCustomListNameDestination( + customListId = customList.id, + initialName = customList.customList.name, + ) + ) + }, + onEditLocationsCustomList = + dropUnlessResumed { customList: RelayItem.CustomList -> + navigator.navigate( + CustomListLocationsDestination(customListId = customList.id, newList = false) + ) + }, + onDeleteCustomList = + dropUnlessResumed { customList: RelayItem.CustomList -> + navigator.navigate( + DeleteCustomListDestination( + customListId = customList.id, + name = customList.customList.name, + ) + ) + }, + onSelectRelayList = vm::selectRelayList, + ) +} + +@Suppress("LongMethod") +@Composable +fun SelectLocationScreen( + state: SelectLocationUiState, + snackbarHostState: SnackbarHostState = remember { SnackbarHostState() }, + onSelectRelay: (item: RelayItem) -> Unit = {}, + onSearchClick: (RelayListType) -> Unit = {}, + onBackClick: () -> Unit = {}, + onFilterClick: () -> Unit = {}, + onCreateCustomList: (location: RelayItem.Location?) -> Unit = {}, + onEditCustomLists: () -> Unit = {}, + removeOwnershipFilter: () -> Unit = {}, + removeProviderFilter: () -> Unit = {}, + onAddLocationToList: (location: RelayItem.Location, customList: RelayItem.CustomList) -> Unit = + { _, _ -> + }, + onRemoveLocationFromList: (location: RelayItem.Location, customListId: CustomListId) -> Unit = + { _, _ -> + }, + onEditCustomListName: (RelayItem.CustomList) -> Unit = {}, + onEditLocationsCustomList: (RelayItem.CustomList) -> Unit = {}, + onDeleteCustomList: (RelayItem.CustomList) -> Unit = {}, + onSelectRelayList: (RelayListType) -> Unit = {}, +) { + val backgroundColor = MaterialTheme.colorScheme.surface + + ScaffoldWithSmallTopBar( + appBarTitle = stringResource(id = R.string.select_location), + navigationIcon = { + IconButton(onClick = onBackClick) { + Icon( + imageVector = Icons.Default.Close, + tint = MaterialTheme.colorScheme.onSurface, + contentDescription = stringResource(id = R.string.back), + ) + } + }, + snackbarHostState = snackbarHostState, + actions = { + IconButton(onClick = { onSearchClick(state.relayListType) }) { + Icon( + imageVector = Icons.Default.Search, + contentDescription = stringResource(id = R.string.filter), + tint = MaterialTheme.colorScheme.onSurface, + ) + } + IconButton(onClick = onFilterClick) { + Icon( + imageVector = Icons.Default.FilterList, + contentDescription = stringResource(id = R.string.filter), + tint = MaterialTheme.colorScheme.onSurface, + ) + } + }, + ) { modifier -> + var locationBottomSheetState by remember { mutableStateOf(null) } + LocationBottomSheets( + locationBottomSheetState = locationBottomSheetState, + onCreateCustomList = onCreateCustomList, + onEditCustomLists = onEditCustomLists, + onAddLocationToList = onAddLocationToList, + onRemoveLocationFromList = onRemoveLocationFromList, + onEditCustomListName = onEditCustomListName, + onEditLocationsCustomList = onEditLocationsCustomList, + onDeleteCustomList = onDeleteCustomList, + onHideBottomSheet = { locationBottomSheetState = null }, + ) + + Column(modifier = modifier.background(backgroundColor).fillMaxSize()) { + AnimatedContent(targetState = state.filterChips, label = "Select location top bar") { + filterChips -> + if (filterChips.isNotEmpty()) { + FilterRow( + filters = filterChips, + onRemoveOwnershipFilter = removeOwnershipFilter, + onRemoveProviderFilter = removeProviderFilter, + ) + } + } + + if (state.multihopEnabled) { + MultihopBar(state.relayListType, onSelectRelayList) + } + + Spacer(modifier = Modifier.height(height = Dimens.verticalSpace)) + RelayLists( + state = state, + backgroundColor = backgroundColor, + onSelectRelay = onSelectRelay, + onUpdateBottomSheetState = { newState -> locationBottomSheetState = newState }, + ) + } + } +} + +@Composable +private fun MultihopBar(relayListType: RelayListType, onSelectRelayList: (RelayListType) -> Unit) { + SingleChoiceSegmentedButtonRow( + modifier = + Modifier.fillMaxWidth().padding(start = Dimens.sideMargin, end = Dimens.sideMargin) + ) { + MullvadSegmentedStartButton( + selected = relayListType == RelayListType.ENTRY, + onClick = { onSelectRelayList(RelayListType.ENTRY) }, + text = stringResource(id = R.string.entry), + ) + MullvadSegmentedEndButton( + selected = relayListType == RelayListType.EXIT, + onClick = { onSelectRelayList(RelayListType.EXIT) }, + text = stringResource(id = R.string.exit), + ) + } +} + +@Composable +private fun RelayLists( + state: SelectLocationUiState, + backgroundColor: Color, + onSelectRelay: (RelayItem) -> Unit, + onUpdateBottomSheetState: (LocationBottomSheetState) -> Unit, +) { + // For multihop we want to start on the entry list. + // If multihop is not enabled we want to start on the exit list. + // The exit endpoint is what is selected when multihop is disabled. + val pagerState = + rememberPagerState( + initialPage = + if (state.multihopEnabled) { + RelayListType.ENTRY.ordinal + } else { + RelayListType.EXIT.ordinal + }, + pageCount = { RelayListType.entries.size }, + ) + LaunchedEffect(state.relayListType) { + val index = state.relayListType.ordinal + pagerState.animateScrollToPage(index) + } + + HorizontalPager( + state = pagerState, + userScrollEnabled = false, + beyondViewportPageCount = + if (state.multihopEnabled) { + 1 + } else { + 0 + }, + ) { pageIndex -> + SelectLocationList( + backgroundColor = backgroundColor, + relayListType = RelayListType.entries[pageIndex], + onSelectRelay = onSelectRelay, + onUpdateBottomSheetState = onUpdateBottomSheetState, + ) + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/FilterChip.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/FilterChip.kt new file mode 100644 index 000000000000..84396805004c --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/FilterChip.kt @@ -0,0 +1 @@ +package net.mullvad.mullvadvpn.compose.state diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListItem.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListItem.kt new file mode 100644 index 000000000000..34fd369526d8 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListItem.kt @@ -0,0 +1,89 @@ +package net.mullvad.mullvadvpn.compose.state + +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.CustomListName +import net.mullvad.mullvadvpn.lib.model.RelayItem + +enum class RelayListItemContentType { + CUSTOM_LIST_HEADER, + CUSTOM_LIST_ITEM, + CUSTOM_LIST_ENTRY_ITEM, + CUSTOM_LIST_FOOTER, + LOCATION_HEADER, + LOCATION_ITEM, + LOCATIONS_EMPTY_TEXT, +} + +enum class RelayListItemState { + USED_AS_ENTRY, + USED_AS_EXIT, +} + +sealed interface RelayListItem { + val key: Any + val contentType: RelayListItemContentType + + data object CustomListHeader : RelayListItem { + override val key = "custom_list_header" + override val contentType = RelayListItemContentType.CUSTOM_LIST_HEADER + } + + sealed interface SelectableItem : RelayListItem { + val depth: Int + val isSelected: Boolean + val expanded: Boolean + val state: RelayListItemState? + } + + data class CustomListItem( + val item: RelayItem.CustomList, + override val isSelected: Boolean = false, + override val expanded: Boolean = false, + override val state: RelayListItemState? = null, + ) : SelectableItem { + override val key = item.id + override val depth: Int = 0 + override val contentType = RelayListItemContentType.CUSTOM_LIST_ITEM + } + + data class CustomListEntryItem( + val parentId: CustomListId, + val parentName: CustomListName, + val item: RelayItem.Location, + override val expanded: Boolean, + override val depth: Int = 0, + override val state: RelayListItemState? = null, + ) : SelectableItem { + override val key = parentId to item.id + + // Can't be displayed as selected + override val isSelected: Boolean = false + override val contentType = RelayListItemContentType.CUSTOM_LIST_ENTRY_ITEM + } + + data class CustomListFooter(val hasCustomList: Boolean) : RelayListItem { + override val key = "custom_list_footer" + override val contentType = RelayListItemContentType.CUSTOM_LIST_FOOTER + } + + data object LocationHeader : RelayListItem { + override val key = "location_header" + override val contentType = RelayListItemContentType.LOCATION_HEADER + } + + data class GeoLocationItem( + val item: RelayItem.Location, + override val isSelected: Boolean = false, + override val depth: Int = 0, + override val expanded: Boolean = false, + override val state: RelayListItemState? = null, + ) : SelectableItem { + override val key = item.id + override val contentType = RelayListItemContentType.LOCATION_ITEM + } + + data class LocationsEmptyText(val searchTerm: String) : RelayListItem { + override val key = "locations_empty_text" + override val contentType = RelayListItemContentType.LOCATIONS_EMPTY_TEXT + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListType.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListType.kt new file mode 100644 index 000000000000..6640ceea4a43 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/RelayListType.kt @@ -0,0 +1,6 @@ +package net.mullvad.mullvadvpn.compose.state + +enum class RelayListType { + ENTRY, + EXIT, +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SearchLocationUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SearchLocationUiState.kt new file mode 100644 index 000000000000..fd35213daca4 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SearchLocationUiState.kt @@ -0,0 +1,21 @@ +package net.mullvad.mullvadvpn.compose.state + +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.usecase.FilterChip + +sealed interface SearchLocationUiState { + val searchTerm: String + val filterChips: List + + data class NoQuery( + override val searchTerm: String, + override val filterChips: List, + ) : SearchLocationUiState + + data class Content( + override val searchTerm: String, + override val filterChips: List, + val relayListItems: List, + val customLists: List, + ) : SearchLocationUiState +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationListUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationListUiState.kt new file mode 100644 index 000000000000..bb320de81d3f --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationListUiState.kt @@ -0,0 +1,13 @@ +package net.mullvad.mullvadvpn.compose.state + +import net.mullvad.mullvadvpn.lib.model.RelayItem + +sealed interface SelectLocationListUiState { + + data object Loading : SelectLocationListUiState + + data class Content( + val relayListItems: List, + val customLists: List, + ) : SelectLocationListUiState +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt index d8245792a330..bb61bd4e7d5d 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt @@ -1,102 +1,9 @@ package net.mullvad.mullvadvpn.compose.state -import net.mullvad.mullvadvpn.lib.model.CustomListId -import net.mullvad.mullvadvpn.lib.model.CustomListName -import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.usecase.FilterChip -typealias ModelOwnership = net.mullvad.mullvadvpn.lib.model.Ownership - -sealed interface SelectLocationUiState { - - data object Loading : SelectLocationUiState - - data class Content( - val searchTerm: String, - val filterChips: List, - val relayListItems: List, - val customLists: List, - ) : SelectLocationUiState -} - -sealed interface FilterChip { - data class Ownership(val ownership: ModelOwnership) : FilterChip - - data class Provider(val count: Int) : FilterChip - - data object Daita : FilterChip -} - -enum class RelayListItemContentType { - CUSTOM_LIST_HEADER, - CUSTOM_LIST_ITEM, - CUSTOM_LIST_ENTRY_ITEM, - CUSTOM_LIST_FOOTER, - LOCATION_HEADER, - LOCATION_ITEM, - LOCATIONS_EMPTY_TEXT, -} - -sealed interface RelayListItem { - val key: Any - val contentType: RelayListItemContentType - - data object CustomListHeader : RelayListItem { - override val key = "custom_list_header" - override val contentType = RelayListItemContentType.CUSTOM_LIST_HEADER - } - - sealed interface SelectableItem : RelayListItem { - val depth: Int - val isSelected: Boolean - val expanded: Boolean - } - - data class CustomListItem( - val item: RelayItem.CustomList, - override val isSelected: Boolean = false, - override val expanded: Boolean = false, - ) : SelectableItem { - override val key = item.id - override val depth: Int = 0 - override val contentType = RelayListItemContentType.CUSTOM_LIST_ITEM - } - - data class CustomListEntryItem( - val parentId: CustomListId, - val parentName: CustomListName, - val item: RelayItem.Location, - override val expanded: Boolean, - override val depth: Int = 0, - ) : SelectableItem { - override val key = parentId to item.id - - // Can't be displayed as selected - override val isSelected: Boolean = false - override val contentType = RelayListItemContentType.CUSTOM_LIST_ENTRY_ITEM - } - - data class CustomListFooter(val hasCustomList: Boolean) : RelayListItem { - override val key = "custom_list_footer" - override val contentType = RelayListItemContentType.CUSTOM_LIST_FOOTER - } - - data object LocationHeader : RelayListItem { - override val key: Any = "location_header" - override val contentType = RelayListItemContentType.LOCATION_HEADER - } - - data class GeoLocationItem( - val item: RelayItem.Location, - override val isSelected: Boolean = false, - override val depth: Int = 0, - override val expanded: Boolean = false, - ) : SelectableItem { - override val key = item.id - override val contentType = RelayListItemContentType.LOCATION_ITEM - } - - data class LocationsEmptyText(val searchTerm: String) : RelayListItem { - override val key: Any = "locations_empty_text" - override val contentType = RelayListItemContentType.LOCATIONS_EMPTY_TEXT - } -} +data class SelectLocationUiState( + val filterChips: List, + val multihopEnabled: Boolean, + val relayListType: RelayListType, +) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SettingsUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SettingsUiState.kt index d804dd6678e1..4ebbf9ad23fe 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SettingsUiState.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SettingsUiState.kt @@ -5,4 +5,5 @@ data class SettingsUiState( val isLoggedIn: Boolean, val isSupportedVersion: Boolean, val isPlayBuild: Boolean, + val multihopEnabled: Boolean, ) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt index 2605075ef8d3..1d62de5bb25b 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt @@ -8,6 +8,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.MainScope import net.mullvad.mullvadvpn.BuildConfig import net.mullvad.mullvadvpn.applist.ApplicationsProvider +import net.mullvad.mullvadvpn.compose.state.RelayListType import net.mullvad.mullvadvpn.constant.IS_PLAY_BUILD import net.mullvad.mullvadvpn.dataproxy.MullvadProblemReport import net.mullvad.mullvadvpn.lib.payment.PaymentProvider @@ -34,6 +35,7 @@ import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager import net.mullvad.mullvadvpn.usecase.AccountExpiryInAppNotificationUseCase import net.mullvad.mullvadvpn.usecase.AvailableProvidersUseCase import net.mullvad.mullvadvpn.usecase.EmptyPaymentUseCase +import net.mullvad.mullvadvpn.usecase.FilterChipUseCase import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase import net.mullvad.mullvadvpn.usecase.InternetAvailableUseCase import net.mullvad.mullvadvpn.usecase.LastKnownLocationUseCase @@ -42,6 +44,7 @@ import net.mullvad.mullvadvpn.usecase.OutOfTimeUseCase import net.mullvad.mullvadvpn.usecase.PaymentUseCase import net.mullvad.mullvadvpn.usecase.PlayPaymentUseCase import net.mullvad.mullvadvpn.usecase.SelectedLocationTitleUseCase +import net.mullvad.mullvadvpn.usecase.SelectedLocationUseCase import net.mullvad.mullvadvpn.usecase.SystemVpnSettingsAvailableUseCase import net.mullvad.mullvadvpn.usecase.TunnelStateNotificationUseCase import net.mullvad.mullvadvpn.usecase.VersionNotificationUseCase @@ -71,6 +74,7 @@ import net.mullvad.mullvadvpn.viewmodel.EditCustomListViewModel import net.mullvad.mullvadvpn.viewmodel.FilterViewModel import net.mullvad.mullvadvpn.viewmodel.LoginViewModel import net.mullvad.mullvadvpn.viewmodel.MtuDialogViewModel +import net.mullvad.mullvadvpn.viewmodel.MultihopViewModel import net.mullvad.mullvadvpn.viewmodel.NoDaemonViewModel import net.mullvad.mullvadvpn.viewmodel.OutOfTimeViewModel import net.mullvad.mullvadvpn.viewmodel.PaymentViewModel @@ -78,7 +82,6 @@ import net.mullvad.mullvadvpn.viewmodel.PrivacyDisclaimerViewModel import net.mullvad.mullvadvpn.viewmodel.ReportProblemViewModel import net.mullvad.mullvadvpn.viewmodel.ResetServerIpOverridesConfirmationViewModel import net.mullvad.mullvadvpn.viewmodel.SaveApiAccessMethodViewModel -import net.mullvad.mullvadvpn.viewmodel.SelectLocationViewModel import net.mullvad.mullvadvpn.viewmodel.ServerIpOverridesViewModel import net.mullvad.mullvadvpn.viewmodel.SettingsViewModel import net.mullvad.mullvadvpn.viewmodel.ShadowsocksCustomPortDialogViewModel @@ -92,6 +95,9 @@ import net.mullvad.mullvadvpn.viewmodel.VpnPermissionViewModel import net.mullvad.mullvadvpn.viewmodel.VpnSettingsViewModel import net.mullvad.mullvadvpn.viewmodel.WelcomeViewModel import net.mullvad.mullvadvpn.viewmodel.WireguardCustomPortDialogViewModel +import net.mullvad.mullvadvpn.viewmodel.location.SearchLocationViewModel +import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationListViewModel +import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationViewModel import org.apache.commons.validator.routines.InetAddressValidator import org.koin.android.ext.koin.androidApplication import org.koin.android.ext.koin.androidContext @@ -154,11 +160,13 @@ val uiModule = module { single { CustomListActionUseCase(get(), get()) } single { SelectedLocationTitleUseCase(get(), get()) } single { AvailableProvidersUseCase(get()) } - single { FilterCustomListsRelayItemUseCase(get(), get(), get()) } + single { FilterCustomListsRelayItemUseCase(get(), get(), get(), get()) } single { CustomListsRelayItemUseCase(get(), get()) } single { CustomListRelayItemsUseCase(get(), get()) } - single { FilteredRelayListUseCase(get(), get(), get()) } + single { FilteredRelayListUseCase(get(), get(), get(), get()) } single { LastKnownLocationUseCase(get()) } + single { SelectedLocationUseCase(get(), get()) } + single { FilterChipUseCase(get(), get(), get(), get()) } single { InAppNotificationController(get(), get(), get(), get(), MainScope()) } @@ -210,10 +218,8 @@ val uiModule = module { viewModel { WireguardCustomPortDialogViewModel(get()) } viewModel { LoginViewModel(get(), get(), get()) } viewModel { PrivacyDisclaimerViewModel(get(), IS_PLAY_BUILD) } - viewModel { - SelectLocationViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get()) - } - viewModel { SettingsViewModel(get(), get(), IS_PLAY_BUILD) } + viewModel { SelectLocationViewModel(get(), get(), get(), get(), get(), get()) } + viewModel { SettingsViewModel(get(), get(), get(), IS_PLAY_BUILD) } viewModel { SplashViewModel(get(), get(), get(), get()) } viewModel { VoucherDialogViewModel(get()) } viewModel { VpnSettingsViewModel(get(), get(), get(), get(), get()) } @@ -240,6 +246,25 @@ val uiModule = module { viewModel { Udp2TcpSettingsViewModel(get()) } viewModel { ShadowsocksSettingsViewModel(get(), get()) } viewModel { ShadowsocksCustomPortDialogViewModel(get()) } + viewModel { MultihopViewModel(get()) } + viewModel { + SearchLocationViewModel( + get(), + get(), + get(), + get(), + get(), + get(), + get(), + get(), + get(), + get(), + get(), + ) + } + viewModel { (relayListType: RelayListType) -> + SelectLocationListViewModel(relayListType, get(), get(), get(), get(), get(), get()) + } // This view model must be single so we correctly attach lifecycle and share it with activity single { NoDaemonViewModel(get()) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt index 5d6e48a3f71b..0aeef5e219a1 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayItemExtensions.kt @@ -56,14 +56,15 @@ private fun RelayItem.Location.hasProvider(providersConstraint: Constraint, providers: Constraint, - isDaitaEnabled: Boolean, + shouldFilterByDaita: Boolean, ): RelayItem.CustomList { val newLocations = locations.mapNotNull { when (it) { - is RelayItem.Location.Country -> it.filter(ownership, providers, isDaitaEnabled) - is RelayItem.Location.City -> it.filter(ownership, providers, isDaitaEnabled) - is RelayItem.Location.Relay -> it.filter(ownership, providers, isDaitaEnabled) + is RelayItem.Location.Country -> + it.filter(ownership, providers, shouldFilterByDaita) + is RelayItem.Location.City -> it.filter(ownership, providers, shouldFilterByDaita) + is RelayItem.Location.Relay -> it.filter(ownership, providers, shouldFilterByDaita) } } return copy(locations = newLocations) @@ -72,9 +73,9 @@ fun RelayItem.CustomList.filter( fun RelayItem.Location.Country.filter( ownership: Constraint, providers: Constraint, - isDaitaEnabled: Boolean, + shouldFilterByDaita: Boolean, ): RelayItem.Location.Country? { - val cities = cities.mapNotNull { it.filter(ownership, providers, isDaitaEnabled) } + val cities = cities.mapNotNull { it.filter(ownership, providers, shouldFilterByDaita) } return if (cities.isNotEmpty()) { this.copy(cities = cities) } else { @@ -85,9 +86,9 @@ fun RelayItem.Location.Country.filter( private fun RelayItem.Location.City.filter( ownership: Constraint, providers: Constraint, - isDaitaEnabled: Boolean, + shouldFilterByDaita: Boolean, ): RelayItem.Location.City? { - val relays = relays.mapNotNull { it.filter(ownership, providers, isDaitaEnabled) } + val relays = relays.mapNotNull { it.filter(ownership, providers, shouldFilterByDaita) } return if (relays.isNotEmpty()) { this.copy(relays = relays) } else { @@ -102,10 +103,12 @@ private fun RelayItem.Location.Relay.hasMatchingDaitaSetting(isDaitaEnabled: Boo private fun RelayItem.Location.Relay.filter( ownership: Constraint, providers: Constraint, - isDaitaEnabled: Boolean, + shouldFilterByDaita: Boolean, ): RelayItem.Location.Relay? { return if ( - hasMatchingDaitaSetting(isDaitaEnabled) && hasOwnership(ownership) && hasProvider(providers) + hasMatchingDaitaSetting(shouldFilterByDaita) && + hasOwnership(ownership) && + hasProvider(providers) ) { this } else { diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/WireguardConstraintsRepository.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/WireguardConstraintsRepository.kt index 816b172ea5ff..093b87cafcbc 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/WireguardConstraintsRepository.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/WireguardConstraintsRepository.kt @@ -1,11 +1,29 @@ package net.mullvad.mullvadvpn.repository +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.stateIn import net.mullvad.mullvadvpn.lib.daemon.grpc.ManagementService import net.mullvad.mullvadvpn.lib.model.Constraint import net.mullvad.mullvadvpn.lib.model.Port +import net.mullvad.mullvadvpn.lib.model.RelayItemId + +class WireguardConstraintsRepository( + private val managementService: ManagementService, + dispatcher: CoroutineDispatcher = Dispatchers.IO, +) { + val wireguardConstraints = + managementService.settings + .mapNotNull { it.relaySettings.relayConstraints.wireguardConstraints } + .stateIn(CoroutineScope(dispatcher), SharingStarted.Eagerly, null) -class WireguardConstraintsRepository(private val managementService: ManagementService) { suspend fun setWireguardPort(port: Constraint) = managementService.setWireguardPort(port) suspend fun setMultihop(enabled: Boolean) = managementService.setMultihop(enabled) + + suspend fun setEntryLocation(relayItemId: RelayItemId) = + managementService.setEntryLocation(relayItemId) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCase.kt new file mode 100644 index 000000000000..3874785920dc --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCase.kt @@ -0,0 +1,103 @@ +package net.mullvad.mullvadvpn.usecase + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.toSelectedProviders +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.Ownership +import net.mullvad.mullvadvpn.lib.model.Provider +import net.mullvad.mullvadvpn.lib.model.Providers +import net.mullvad.mullvadvpn.repository.RelayListFilterRepository +import net.mullvad.mullvadvpn.repository.SettingsRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.util.showOnlyRelaysWithDaita + +typealias ModelOwnership = Ownership + +class FilterChipUseCase( + private val relayListFilterRepository: RelayListFilterRepository, + private val availableProvidersUseCase: AvailableProvidersUseCase, + private val settingsRepository: SettingsRepository, + private val wireguardConstraintsRepository: WireguardConstraintsRepository, +) { + operator fun invoke(relayListType: RelayListType): Flow> = + combine( + relayListFilterRepository.selectedOwnership, + relayListFilterRepository.selectedProviders, + availableProvidersUseCase(), + settingsRepository.settingsUpdates, + wireguardConstraintsRepository.wireguardConstraints, + ) { + selectedOwnership, + selectedConstraintProviders, + allProviders, + settings, + wireguardConstraints -> + filterChips( + selectedOwnership = selectedOwnership, + selectedConstraintProviders = selectedConstraintProviders, + allProviders = allProviders, + isDaitaEnabled = settings?.isDaitaEnabled() == true, + isMultihopEnabled = wireguardConstraints?.isMultihopEnabled == true, + relayListType = relayListType, + ) + } + + private fun filterChips( + selectedOwnership: Constraint, + selectedConstraintProviders: Constraint, + allProviders: List, + isDaitaEnabled: Boolean, + isMultihopEnabled: Boolean, + relayListType: RelayListType, + ): List { + val ownershipFilter = selectedOwnership.getOrNull() + val providerCountFilter = + when (selectedConstraintProviders) { + is Constraint.Any -> null + is Constraint.Only -> + filterSelectedProvidersByOwnership( + selectedConstraintProviders.toSelectedProviders(allProviders), + ownershipFilter, + ) + .size + } + return buildList { + if (ownershipFilter != null) { + add(FilterChip.Ownership(ownershipFilter)) + } + if (providerCountFilter != null) { + add(FilterChip.Provider(providerCountFilter)) + } + if ( + showOnlyRelaysWithDaita( + isDaitaEnabled = isDaitaEnabled, + relayListType = relayListType, + isMultihopEnabled = isMultihopEnabled, + ) + ) { + add(FilterChip.Daita) + } + } + } + + private fun filterSelectedProvidersByOwnership( + selectedProviders: List, + selectedOwnership: Ownership?, + ): List = + if (selectedOwnership == null) selectedProviders + else selectedProviders.filter { it.ownership == selectedOwnership } +} + +sealed interface FilterChip { + data class Ownership(val ownership: ModelOwnership) : FilterChip + + data class Provider(val count: Int) : FilterChip + + data object Daita : FilterChip + + data object Entry : FilterChip + + data object Exit : FilterChip +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt index 60de94946f6f..5a83e483d5ee 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/FilteredRelayListUseCase.kt @@ -1,6 +1,7 @@ package net.mullvad.mullvadvpn.usecase import kotlinx.coroutines.flow.combine +import net.mullvad.mullvadvpn.compose.state.RelayListType import net.mullvad.mullvadvpn.lib.model.Constraint import net.mullvad.mullvadvpn.lib.model.Ownership import net.mullvad.mullvadvpn.lib.model.Providers @@ -9,29 +10,38 @@ import net.mullvad.mullvadvpn.relaylist.filter import net.mullvad.mullvadvpn.repository.RelayListFilterRepository import net.mullvad.mullvadvpn.repository.RelayListRepository import net.mullvad.mullvadvpn.repository.SettingsRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.util.showOnlyRelaysWithDaita class FilteredRelayListUseCase( private val relayListRepository: RelayListRepository, private val relayListFilterRepository: RelayListFilterRepository, private val settingsRepository: SettingsRepository, + private val wireguardConstraintsRepository: WireguardConstraintsRepository, ) { - operator fun invoke() = + operator fun invoke(relayListType: RelayListType) = combine( relayListRepository.relayList, relayListFilterRepository.selectedOwnership, relayListFilterRepository.selectedProviders, settingsRepository.settingsUpdates, - ) { relayList, selectedOwnership, selectedProviders, settings -> + wireguardConstraintsRepository.wireguardConstraints, + ) { relayList, selectedOwnership, selectedProviders, settings, wireguardConstraints -> relayList.filter( - selectedOwnership, - selectedProviders, - isDaitaEnabled = settings?.isDaitaEnabled() ?: false, + ownership = selectedOwnership, + providers = selectedProviders, + shouldFilterByDaita = + showOnlyRelaysWithDaita( + isDaitaEnabled = settings?.isDaitaEnabled() == true, + isMultihopEnabled = wireguardConstraints?.isMultihopEnabled == true, + relayListType = relayListType, + ), ) } private fun List.filter( ownership: Constraint, providers: Constraint, - isDaitaEnabled: Boolean, - ) = mapNotNull { it.filter(ownership, providers, isDaitaEnabled) } + shouldFilterByDaita: Boolean, + ) = mapNotNull { it.filter(ownership, providers, shouldFilterByDaita) } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCase.kt new file mode 100644 index 000000000000..b103e45c6307 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCase.kt @@ -0,0 +1,27 @@ +package net.mullvad.mullvadvpn.usecase + +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.filterNotNull +import net.mullvad.mullvadvpn.lib.model.RelayItemSelection +import net.mullvad.mullvadvpn.repository.RelayListRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository + +class SelectedLocationUseCase( + private val relayListRepository: RelayListRepository, + private val wireguardConstraintsRepository: WireguardConstraintsRepository, +) { + operator fun invoke() = + combine( + relayListRepository.selectedLocation.filterNotNull(), + wireguardConstraintsRepository.wireguardConstraints.filterNotNull(), + ) { selectedLocation, wireguardConstraints -> + if (wireguardConstraints.isMultihopEnabled) { + RelayItemSelection.Multiple( + entryLocation = wireguardConstraints.entryLocation, + exitLocation = selectedLocation, + ) + } else { + RelayItemSelection.Single(selectedLocation) + } + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt index 17ead75d2ac9..af519841a249 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/customlists/FilterCustomListsRelayItemUseCase.kt @@ -2,6 +2,7 @@ package net.mullvad.mullvadvpn.usecase.customlists import kotlin.collections.mapNotNull import kotlinx.coroutines.flow.combine +import net.mullvad.mullvadvpn.compose.state.RelayListType import net.mullvad.mullvadvpn.lib.model.Constraint import net.mullvad.mullvadvpn.lib.model.Ownership import net.mullvad.mullvadvpn.lib.model.Providers @@ -9,30 +10,39 @@ import net.mullvad.mullvadvpn.lib.model.RelayItem import net.mullvad.mullvadvpn.relaylist.filter import net.mullvad.mullvadvpn.repository.RelayListFilterRepository import net.mullvad.mullvadvpn.repository.SettingsRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.util.showOnlyRelaysWithDaita class FilterCustomListsRelayItemUseCase( private val customListsRelayItemUseCase: CustomListsRelayItemUseCase, private val relayListFilterRepository: RelayListFilterRepository, private val settingsRepository: SettingsRepository, + private val wireguardConstraintsRepository: WireguardConstraintsRepository, ) { - operator fun invoke() = + operator fun invoke(relayListType: RelayListType) = combine( customListsRelayItemUseCase(), relayListFilterRepository.selectedOwnership, relayListFilterRepository.selectedProviders, settingsRepository.settingsUpdates, - ) { customLists, selectedOwnership, selectedProviders, settings -> + wireguardConstraintsRepository.wireguardConstraints, + ) { customLists, selectedOwnership, selectedProviders, settings, wireguardConstraints -> customLists.filterOnOwnershipAndProvider( - selectedOwnership, - selectedProviders, - isDaitaEnabled = settings?.isDaitaEnabled() ?: false, + ownership = selectedOwnership, + providers = selectedProviders, + shouldFilterByDaita = + showOnlyRelaysWithDaita( + isDaitaEnabled = settings?.isDaitaEnabled() == true, + isMultihopEnabled = wireguardConstraints?.isMultihopEnabled == true, + relayListType = relayListType, + ), ) } private fun List.filterOnOwnershipAndProvider( ownership: Constraint, providers: Constraint, - isDaitaEnabled: Boolean, - ) = mapNotNull { it.filter(ownership, providers, isDaitaEnabled = isDaitaEnabled) } + shouldFilterByDaita: Boolean, + ) = mapNotNull { it.filter(ownership, providers, shouldFilterByDaita = shouldFilterByDaita) } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/Daita.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/Daita.kt new file mode 100644 index 000000000000..0126e9e7f540 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/Daita.kt @@ -0,0 +1,12 @@ +package net.mullvad.mullvadvpn.util + +import net.mullvad.mullvadvpn.compose.state.RelayListType + +fun showOnlyRelaysWithDaita( + isDaitaEnabled: Boolean, + isMultihopEnabled: Boolean, + relayListType: RelayListType, +) = + isDaitaEnabled && + (relayListType == RelayListType.ENTRY || + !isMultihopEnabled && relayListType == RelayListType.EXIT) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/FlowUtils.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/FlowUtils.kt index 200502dee4ff..0c885989233e 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/FlowUtils.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/util/FlowUtils.kt @@ -29,6 +29,31 @@ inline fun combine( } } +inline fun combine( + flow: Flow, + flow2: Flow, + flow3: Flow, + flow4: Flow, + flow5: Flow, + flow6: Flow, + flow7: Flow, + crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7) -> R, +): Flow { + return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6, flow7) { + args: Array<*> -> + @Suppress("UNCHECKED_CAST") + transform( + args[0] as T1, + args[1] as T2, + args[2] as T3, + args[3] as T4, + args[4] as T5, + args[5] as T6, + args[6] as T7, + ) + } +} + @OptIn(ExperimentalCoroutinesApi::class) fun Deferred.getOrDefault(default: T) = try { diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModel.kt new file mode 100644 index 000000000000..4ff63b8fe747 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModel.kt @@ -0,0 +1,26 @@ +package net.mullvad.mullvadvpn.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository + +class MultihopViewModel( + private val wireguardConstraintsRepository: WireguardConstraintsRepository +) : ViewModel() { + + val uiState: StateFlow = + wireguardConstraintsRepository.wireguardConstraints + .map { MultihopUiState(it?.isMultihopEnabled ?: false) } + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), MultihopUiState(false)) + + fun setMultihop(enable: Boolean) { + viewModelScope.launch { wireguardConstraintsRepository.setMultihop(enable) } + } +} + +data class MultihopUiState(val enable: Boolean) diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt deleted file mode 100644 index 4ddad8477bae..000000000000 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt +++ /dev/null @@ -1,436 +0,0 @@ -package net.mullvad.mullvadvpn.viewmodel - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import arrow.core.getOrElse -import arrow.core.raise.either -import kotlinx.coroutines.channels.Channel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.receiveAsFlow -import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import net.mullvad.mullvadvpn.compose.communication.CustomListAction -import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData -import net.mullvad.mullvadvpn.compose.state.FilterChip -import net.mullvad.mullvadvpn.compose.state.RelayListItem -import net.mullvad.mullvadvpn.compose.state.RelayListItem.CustomListHeader -import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState -import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState.Content -import net.mullvad.mullvadvpn.compose.state.toSelectedProviders -import net.mullvad.mullvadvpn.lib.model.Constraint -import net.mullvad.mullvadvpn.lib.model.CustomListId -import net.mullvad.mullvadvpn.lib.model.GeoLocationId -import net.mullvad.mullvadvpn.lib.model.Ownership -import net.mullvad.mullvadvpn.lib.model.Provider -import net.mullvad.mullvadvpn.lib.model.RelayItem -import net.mullvad.mullvadvpn.lib.model.RelayItemId -import net.mullvad.mullvadvpn.relaylist.MIN_SEARCH_LENGTH -import net.mullvad.mullvadvpn.relaylist.descendants -import net.mullvad.mullvadvpn.relaylist.filterOnSearchTerm -import net.mullvad.mullvadvpn.relaylist.newFilterOnSearch -import net.mullvad.mullvadvpn.repository.CustomListsRepository -import net.mullvad.mullvadvpn.repository.RelayListFilterRepository -import net.mullvad.mullvadvpn.repository.RelayListRepository -import net.mullvad.mullvadvpn.repository.SettingsRepository -import net.mullvad.mullvadvpn.usecase.AvailableProvidersUseCase -import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase -import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase -import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase -import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase - -@Suppress("TooManyFunctions") -class SelectLocationViewModel( - private val relayListFilterRepository: RelayListFilterRepository, - private val availableProvidersUseCase: AvailableProvidersUseCase, - customListsRelayItemUseCase: CustomListsRelayItemUseCase, - private val filteredCustomListRelayItemsUseCase: FilterCustomListsRelayItemUseCase, - private val customListsRepository: CustomListsRepository, - private val customListActionUseCase: CustomListActionUseCase, - private val filteredRelayListUseCase: FilteredRelayListUseCase, - private val relayListRepository: RelayListRepository, - private val settingsRepository: SettingsRepository, -) : ViewModel() { - private val _searchTerm = MutableStateFlow(EMPTY_SEARCH_TERM) - - private val _expandedItems = MutableStateFlow(initialExpand()) - - @Suppress("DestructuringDeclarationWithTooManyEntries") - val uiState = - combine(_searchTerm, relayListItems(), filterChips(), customListsRelayItemUseCase()) { - searchTerm, - relayListItems, - filterChips, - customLists -> - Content( - searchTerm = searchTerm, - filterChips = filterChips, - relayListItems = relayListItems, - customLists = customLists, - ) - } - .stateIn(viewModelScope, SharingStarted.Lazily, SelectLocationUiState.Loading) - - private val _uiSideEffect = Channel() - val uiSideEffect = _uiSideEffect.receiveAsFlow() - - private fun initialExpand(): Set = buildSet { - when (val item = relayListRepository.selectedLocation.value.getOrNull()) { - is GeoLocationId.City -> { - add(item.country.code) - } - is GeoLocationId.Hostname -> { - add(item.country.code) - add(item.city.code) - } - is CustomListId, - is GeoLocationId.Country, - null -> { - /* No expands */ - } - } - } - - private fun searchRelayListLocations() = - combine(_searchTerm, filteredRelayListUseCase()) { searchTerm, relayCountries -> - val isSearching = searchTerm.length >= MIN_SEARCH_LENGTH - if (isSearching) { - val (exp, filteredRelayCountries) = relayCountries.newFilterOnSearch(searchTerm) - exp.map { it.expandKey() }.toSet() to filteredRelayCountries - } else { - initialExpand() to relayCountries - } - } - .onEach { _expandedItems.value = it.first } - .map { it.second } - - private fun filterChips() = - combine( - relayListFilterRepository.selectedOwnership, - relayListFilterRepository.selectedProviders, - availableProvidersUseCase(), - settingsRepository.settingsUpdates, - ) { selectedOwnership, selectedConstraintProviders, allProviders, settings -> - val ownershipFilter = selectedOwnership.getOrNull() - val providerCountFilter = - when (selectedConstraintProviders) { - is Constraint.Any -> null - is Constraint.Only -> - filterSelectedProvidersByOwnership( - selectedConstraintProviders.toSelectedProviders(allProviders), - ownershipFilter, - ) - .size - } - buildList { - if (ownershipFilter != null) { - add(FilterChip.Ownership(ownershipFilter)) - } - if (providerCountFilter != null) { - add(FilterChip.Provider(providerCountFilter)) - } - if (settings?.isDaitaEnabled() == true) { - add(FilterChip.Daita) - } - } - } - - private fun relayListItems() = - combine( - _searchTerm, - searchRelayListLocations(), - filteredCustomListRelayItemsUseCase(), - relayListRepository.selectedLocation, - _expandedItems, - ) { searchTerm, relayCountries, customLists, selectedItem, expandedItems -> - val filteredCustomLists = customLists.filterOnSearchTerm(searchTerm) - - buildList { - val relayItems = - createRelayListItems( - searchTerm.length >= MIN_SEARCH_LENGTH, - selectedItem.getOrNull(), - filteredCustomLists, - relayCountries, - ) { - it in expandedItems - } - if (relayItems.isEmpty()) { - add(RelayListItem.LocationsEmptyText(searchTerm)) - } else { - addAll(relayItems) - } - } - } - - private fun createRelayListItems( - isSearching: Boolean, - selectedItem: RelayItemId?, - customLists: List, - countries: List, - isExpanded: (String) -> Boolean, - ): List = - createCustomListSection(isSearching, selectedItem, customLists, isExpanded) + - createLocationSection(isSearching, selectedItem, countries, isExpanded) - - private fun createCustomListSection( - isSearching: Boolean, - selectedItem: RelayItemId?, - customLists: List, - isExpanded: (String) -> Boolean, - ): List = buildList { - if (isSearching && customLists.isEmpty()) { - // If we are searching and no results are found don't show header or footer - } else { - add(CustomListHeader) - val customListItems = createCustomListRelayItems(customLists, selectedItem, isExpanded) - addAll(customListItems) - add(RelayListItem.CustomListFooter(customListItems.isNotEmpty())) - } - } - - private fun createCustomListRelayItems( - customLists: List, - selectedItem: RelayItemId?, - isExpanded: (String) -> Boolean, - ): List = - customLists.flatMap { customList -> - val expanded = isExpanded(customList.id.expandKey()) - buildList { - add( - RelayListItem.CustomListItem( - customList, - isSelected = selectedItem == customList.id, - expanded, - ) - ) - - if (expanded) { - addAll( - customList.locations.flatMap { - createCustomListEntry(parent = customList, item = it, 1, isExpanded) - } - ) - } - } - } - - private fun createLocationSection( - isSearching: Boolean, - selectedItem: RelayItemId?, - countries: List, - isExpanded: (String) -> Boolean, - ): List = buildList { - if (isSearching && countries.isEmpty()) { - // If we are searching and no results are found don't show header or footer - } else { - add(RelayListItem.LocationHeader) - addAll( - countries.flatMap { country -> - createGeoLocationEntry(country, selectedItem, isExpanded = isExpanded) - } - ) - } - } - - private fun createCustomListEntry( - parent: RelayItem.CustomList, - item: RelayItem.Location, - depth: Int = 1, - isExpanded: (String) -> Boolean, - ): List = buildList { - val expanded = isExpanded(item.id.expandKey(parent.id)) - add( - RelayListItem.CustomListEntryItem( - parentId = parent.id, - parentName = parent.customList.name, - item = item, - expanded = expanded, - depth, - ) - ) - - if (expanded) { - when (item) { - is RelayItem.Location.City -> - addAll( - item.relays.flatMap { - createCustomListEntry(parent, it, depth + 1, isExpanded) - } - ) - is RelayItem.Location.Country -> - addAll( - item.cities.flatMap { - createCustomListEntry(parent, it, depth + 1, isExpanded) - } - ) - is RelayItem.Location.Relay -> {} // No children to add - } - } - } - - private fun createGeoLocationEntry( - item: RelayItem.Location, - selectedItem: RelayItemId?, - depth: Int = 0, - isExpanded: (String) -> Boolean, - ): List = buildList { - val expanded = isExpanded(item.id.expandKey()) - - add( - RelayListItem.GeoLocationItem( - item = item, - isSelected = selectedItem == item.id, - depth = depth, - expanded = expanded, - ) - ) - - if (expanded) { - when (item) { - is RelayItem.Location.City -> - addAll( - item.relays.flatMap { - createGeoLocationEntry(it, selectedItem, depth + 1, isExpanded) - } - ) - is RelayItem.Location.Country -> - addAll( - item.cities.flatMap { - createGeoLocationEntry(it, selectedItem, depth + 1, isExpanded) - } - ) - is RelayItem.Location.Relay -> {} // Do nothing - } - } - } - - private fun RelayItemId.expandKey(parent: CustomListId? = null) = - (parent?.value ?: "") + - when (this) { - is CustomListId -> value - is GeoLocationId -> code - } - - fun selectRelay(relayItem: RelayItem) { - viewModelScope.launch { - val locationConstraint = relayItem.id - relayListRepository - .updateSelectedRelayLocation(locationConstraint) - .fold( - { _uiSideEffect.send(SelectLocationSideEffect.GenericError) }, - { _uiSideEffect.send(SelectLocationSideEffect.CloseScreen) }, - ) - } - } - - fun onToggleExpand(item: RelayItemId, parent: CustomListId? = null, expand: Boolean) { - _expandedItems.update { - val key = item.expandKey(parent) - if (expand) { - it + key - } else { - it - key - } - } - } - - fun onSearchTermInput(searchTerm: String) { - viewModelScope.launch { _searchTerm.emit(searchTerm) } - } - - private fun filterSelectedProvidersByOwnership( - selectedProviders: List, - selectedOwnership: Ownership?, - ): List = - if (selectedOwnership == null) selectedProviders - else selectedProviders.filter { it.ownership == selectedOwnership } - - fun removeOwnerFilter() { - viewModelScope.launch { relayListFilterRepository.updateSelectedOwnership(Constraint.Any) } - } - - fun removeProviderFilter() { - viewModelScope.launch { relayListFilterRepository.updateSelectedProviders(Constraint.Any) } - } - - fun addLocationToList(item: RelayItem.Location, customList: RelayItem.CustomList) { - viewModelScope.launch { - val newLocations = - (customList.locations + item).filter { it !in item.descendants() }.map { it.id } - val result = - customListActionUseCase( - CustomListAction.UpdateLocations(customList.id, newLocations) - ) - .fold( - { CustomListActionResultData.GenericError }, - { - if (it.removedLocations.isEmpty()) { - CustomListActionResultData.Success.LocationAdded( - customListName = it.name, - locationName = item.name, - undo = it.undo, - ) - } else { - CustomListActionResultData.Success.LocationChanged( - customListName = it.name, - undo = it.undo, - ) - } - }, - ) - _uiSideEffect.send(SelectLocationSideEffect.CustomListActionToast(result)) - } - } - - fun performAction(action: CustomListAction) { - viewModelScope.launch { customListActionUseCase(action) } - } - - fun removeLocationFromList(item: RelayItem.Location, customListId: CustomListId) { - viewModelScope.launch { - val result = - either { - val customList = - customListsRepository.getCustomListById(customListId).bind() - val newLocations = (customList.locations - item.id) - val success = - customListActionUseCase( - CustomListAction.UpdateLocations(customList.id, newLocations) - ) - .bind() - if (success.addedLocations.isEmpty()) { - CustomListActionResultData.Success.LocationRemoved( - customListName = success.name, - locationName = item.name, - undo = success.undo, - ) - } else { - CustomListActionResultData.Success.LocationChanged( - customListName = success.name, - undo = success.undo, - ) - } - } - .getOrElse { CustomListActionResultData.GenericError } - _uiSideEffect.send(SelectLocationSideEffect.CustomListActionToast(result)) - } - } - - companion object { - private const val EMPTY_SEARCH_TERM = "" - } -} - -sealed interface SelectLocationSideEffect { - data object CloseScreen : SelectLocationSideEffect - - data class CustomListActionToast(val resultData: CustomListActionResultData) : - SelectLocationSideEffect - - data object GenericError : SelectLocationSideEffect -} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModel.kt index fc6b4af3eeaf..22309fecfd6a 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModel.kt @@ -9,23 +9,28 @@ import kotlinx.coroutines.flow.stateIn import net.mullvad.mullvadvpn.compose.state.SettingsUiState import net.mullvad.mullvadvpn.lib.model.DeviceState import net.mullvad.mullvadvpn.lib.shared.DeviceRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository import net.mullvad.mullvadvpn.ui.serviceconnection.AppVersionInfoRepository class SettingsViewModel( deviceRepository: DeviceRepository, appVersionInfoRepository: AppVersionInfoRepository, + wireguardConstraintsRepository: WireguardConstraintsRepository, isPlayBuild: Boolean, ) : ViewModel() { val uiState: StateFlow = - combine(deviceRepository.deviceState, appVersionInfoRepository.versionInfo) { - deviceState, - versionInfo -> + combine( + deviceRepository.deviceState, + appVersionInfoRepository.versionInfo, + wireguardConstraintsRepository.wireguardConstraints, + ) { deviceState, versionInfo, wireguardConstraints -> SettingsUiState( isLoggedIn = deviceState is DeviceState.LoggedIn, appVersion = versionInfo.currentVersion, isSupportedVersion = versionInfo.isSupported, isPlayBuild = isPlayBuild, + multihopEnabled = wireguardConstraints?.isMultihopEnabled ?: false, ) } .stateIn( @@ -36,6 +41,7 @@ class SettingsViewModel( isLoggedIn = false, isSupportedVersion = true, isPlayBuild = isPlayBuild, + multihopEnabled = false, ), ) } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/CustomListEdit.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/CustomListEdit.kt new file mode 100644 index 000000000000..26454fc02843 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/CustomListEdit.kt @@ -0,0 +1,75 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import arrow.core.Either +import arrow.core.getOrElse +import arrow.core.raise.either +import net.mullvad.mullvadvpn.compose.communication.CustomListAction +import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData +import net.mullvad.mullvadvpn.compose.communication.LocationsChanged +import net.mullvad.mullvadvpn.lib.model.CustomList +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.GetCustomListError +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.relaylist.descendants +import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionError + +internal suspend fun addLocationToCustomList( + customList: RelayItem.CustomList, + item: RelayItem.Location, + update: + suspend (CustomListAction.UpdateLocations) -> Either< + CustomListActionError, + LocationsChanged, + >, +): CustomListActionResultData { + val newLocations = + (customList.locations + item).filter { it !in item.descendants() }.map { it.id } + return update(CustomListAction.UpdateLocations(customList.id, newLocations)) + .fold( + { CustomListActionResultData.GenericError }, + { + if (it.removedLocations.isEmpty()) { + CustomListActionResultData.Success.LocationAdded( + customListName = it.name, + locationName = item.name, + undo = it.undo, + ) + } else { + CustomListActionResultData.Success.LocationChanged( + customListName = it.name, + undo = it.undo, + ) + } + }, + ) +} + +internal suspend fun removeLocationFromCustomList( + item: RelayItem.Location, + customListId: CustomListId, + getCustomListById: suspend (CustomListId) -> Either, + update: + suspend (CustomListAction.UpdateLocations) -> Either< + CustomListActionError, + LocationsChanged, + >, +) = + either { + val customList = getCustomListById(customListId).bind() + val newLocations = (customList.locations - item.id) + val success = + update(CustomListAction.UpdateLocations(customList.id, newLocations)).bind() + if (success.addedLocations.isEmpty()) { + CustomListActionResultData.Success.LocationRemoved( + customListName = success.name, + locationName = item.name, + undo = success.undo, + ) + } else { + CustomListActionResultData.Success.LocationChanged( + customListName = success.name, + undo = success.undo, + ) + } + } + .getOrElse { CustomListActionResultData.GenericError } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/Expand.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/Expand.kt new file mode 100644 index 000000000000..b517619e6b9f --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/Expand.kt @@ -0,0 +1,21 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.update +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.RelayItemId + +internal fun MutableStateFlow>.onToggleExpand( + item: RelayItemId, + parent: CustomListId? = null, + expand: Boolean, +) { + update { + val key = item.expandKey(parent) + if (expand) { + it + key + } else { + it - key + } + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/RelayItemListCreator.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/RelayItemListCreator.kt new file mode 100644 index 000000000000..c4b9e44f4da4 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/RelayItemListCreator.kt @@ -0,0 +1,355 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListItemState +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.GeoLocationId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.model.RelayItemId +import net.mullvad.mullvadvpn.lib.model.RelayItemSelection +import net.mullvad.mullvadvpn.relaylist.MIN_SEARCH_LENGTH +import net.mullvad.mullvadvpn.relaylist.filterOnSearchTerm + +// Creates a relay list to be displayed by RelayListContent +internal fun relayListItems( + searchTerm: String = "", + relayListType: RelayListType, + relayCountries: List, + customLists: List, + selectedByThisEntryExitList: RelayItemId?, + selectedByOtherEntryExitList: RelayItemId?, + expandedItems: Set, +): List { + val filteredCustomLists = customLists.filterOnSearchTerm(searchTerm) + + return buildList { + val relayItems = + createRelayListItems( + isSearching = searchTerm.isSearching(), + relayListType = relayListType, + selectedByThisEntryExitList = selectedByThisEntryExitList, + selectedByOtherEntryExitList = selectedByOtherEntryExitList, + customLists = filteredCustomLists, + countries = relayCountries, + ) { + it in expandedItems + } + if (relayItems.isEmpty()) { + add(RelayListItem.LocationsEmptyText(searchTerm)) + } else { + addAll(relayItems) + } + } +} + +private fun createRelayListItems( + isSearching: Boolean, + relayListType: RelayListType, + selectedByThisEntryExitList: RelayItemId?, + selectedByOtherEntryExitList: RelayItemId?, + customLists: List, + countries: List, + isExpanded: (String) -> Boolean, +): List = + createCustomListSection( + isSearching, + relayListType, + selectedByThisEntryExitList, + selectedByOtherEntryExitList, + customLists, + isExpanded, + ) + + createLocationSection( + isSearching, + selectedByThisEntryExitList, + relayListType, + selectedByOtherEntryExitList, + countries, + isExpanded, + ) + +private fun createCustomListSection( + isSearching: Boolean, + relayListType: RelayListType, + selectedByThisEntryExitList: RelayItemId?, + selectedByOtherEntryExitList: RelayItemId?, + customLists: List, + isExpanded: (String) -> Boolean, +): List = buildList { + if (isSearching && customLists.isEmpty()) { + // If we are searching and no results are found don't show header or footer + } else { + add(RelayListItem.CustomListHeader) + val customListItems = + createCustomListRelayItems( + customLists, + relayListType, + selectedByThisEntryExitList, + selectedByOtherEntryExitList, + isExpanded, + ) + addAll(customListItems) + // Do not show the footer in the search view + if (!isSearching) { + add(RelayListItem.CustomListFooter(customListItems.isNotEmpty())) + } + } +} + +private fun createCustomListRelayItems( + customLists: List, + relayListType: RelayListType, + selectedByThisEntryExitList: RelayItemId?, + selectedByOtherEntryExitList: RelayItemId?, + isExpanded: (String) -> Boolean, +): List = + customLists.flatMap { customList -> + val expanded = isExpanded(customList.id.expandKey()) + buildList { + add( + RelayListItem.CustomListItem( + item = customList, + isSelected = selectedByThisEntryExitList == customList.id, + state = + customList.createState( + relayListType = relayListType, + selectedByOther = selectedByOtherEntryExitList, + ), + expanded = expanded, + ) + ) + + if (expanded) { + addAll( + customList.locations.flatMap { + createCustomListEntry( + parent = customList, + item = it, + relayListType = relayListType, + selectedByOtherEntryExitList = selectedByOtherEntryExitList, + depth = 1, + isExpanded = isExpanded, + ) + } + ) + } + } + } + +private fun createLocationSection( + isSearching: Boolean, + selectedByThisEntryExitList: RelayItemId?, + relayListType: RelayListType, + selectedByOtherEntryExitList: RelayItemId?, + countries: List, + isExpanded: (String) -> Boolean, +): List = buildList { + if (isSearching && countries.isEmpty()) { + // If we are searching and no results are found don't show header or footer + } else { + add(RelayListItem.LocationHeader) + addAll( + countries.flatMap { country -> + createGeoLocationEntry( + item = country, + selectedByThisEntryExitList = selectedByThisEntryExitList, + relayListType = relayListType, + selectedByOtherEntryExitList = selectedByOtherEntryExitList, + isExpanded = isExpanded, + ) + } + ) + } +} + +private fun createCustomListEntry( + parent: RelayItem.CustomList, + item: RelayItem.Location, + relayListType: RelayListType, + selectedByOtherEntryExitList: RelayItemId?, + depth: Int = 1, + isExpanded: (String) -> Boolean, +): List = buildList { + val expanded = isExpanded(item.id.expandKey(parent.id)) + add( + RelayListItem.CustomListEntryItem( + parentId = parent.id, + parentName = parent.customList.name, + item = item, + state = + item.createState( + relayListType = relayListType, + selectedByOther = selectedByOtherEntryExitList, + ), + expanded = expanded, + depth = depth, + ) + ) + + if (expanded) { + when (item) { + is RelayItem.Location.City -> + addAll( + item.relays.flatMap { + createCustomListEntry( + parent = parent, + item = it, + relayListType = relayListType, + selectedByOtherEntryExitList = selectedByOtherEntryExitList, + depth = depth + 1, + isExpanded = isExpanded, + ) + } + ) + is RelayItem.Location.Country -> + addAll( + item.cities.flatMap { + createCustomListEntry( + parent = parent, + item = it, + relayListType = relayListType, + selectedByOtherEntryExitList = selectedByOtherEntryExitList, + depth = depth + 1, + isExpanded = isExpanded, + ) + } + ) + is RelayItem.Location.Relay -> {} // No children to add + } + } +} + +private fun createGeoLocationEntry( + item: RelayItem.Location, + relayListType: RelayListType, + selectedByThisEntryExitList: RelayItemId?, + selectedByOtherEntryExitList: RelayItemId?, + depth: Int = 0, + isExpanded: (String) -> Boolean, +): List = buildList { + val expanded = isExpanded(item.id.expandKey()) + + add( + RelayListItem.GeoLocationItem( + item = item, + isSelected = selectedByThisEntryExitList == item.id, + state = + item.createState( + relayListType = relayListType, + selectedByOther = selectedByOtherEntryExitList, + ), + depth = depth, + expanded = expanded, + ) + ) + + if (expanded) { + when (item) { + is RelayItem.Location.City -> + addAll( + item.relays.flatMap { + createGeoLocationEntry( + item = it, + relayListType = relayListType, + selectedByThisEntryExitList = selectedByThisEntryExitList, + selectedByOtherEntryExitList = selectedByOtherEntryExitList, + depth = depth + 1, + isExpanded = isExpanded, + ) + } + ) + is RelayItem.Location.Country -> + addAll( + item.cities.flatMap { + createGeoLocationEntry( + item = it, + relayListType = relayListType, + selectedByThisEntryExitList = selectedByThisEntryExitList, + selectedByOtherEntryExitList = selectedByOtherEntryExitList, + depth = depth + 1, + isExpanded = isExpanded, + ) + } + ) + is RelayItem.Location.Relay -> {} // Do nothing + } + } +} + +internal fun RelayItemId.expandKey(parent: CustomListId? = null) = + (parent?.value ?: "") + + when (this) { + is CustomListId -> value + is GeoLocationId -> code + } + +internal fun RelayItemSelection.selectedByThisEntryExitList(relayListType: RelayListType) = + when (this) { + is RelayItemSelection.Multiple -> + when (relayListType) { + RelayListType.ENTRY -> entryLocation + RelayListType.EXIT -> exitLocation + }.getOrNull() + is RelayItemSelection.Single -> exitLocation.getOrNull() + } + +internal fun RelayItemSelection.selectedByOtherEntryExitList( + relayListType: RelayListType, + customLists: List, +) = + when (this) { + is RelayItemSelection.Multiple -> { + val location = + when (relayListType) { + RelayListType.ENTRY -> exitLocation + RelayListType.EXIT -> entryLocation + }.getOrNull() + location.singleRelayId(customLists) + } + is RelayItemSelection.Single -> null + } + +// We only want to block selecting the same entry as exit if it is a relay. For country and +// city it is fine to have same entry and exit +// For custom lists we will block if the custom lists only contains one relay and +// nothing else +private fun RelayItemId?.singleRelayId(customLists: List): RelayItemId? = + when (this) { + is GeoLocationId.City, + is GeoLocationId.Country -> null + is GeoLocationId.Hostname -> this + is CustomListId -> + customLists + .firstOrNull { customList -> customList.id == this } + ?.locations + ?.singleOrNull() + ?.id as? GeoLocationId.Hostname + else -> null + } + +private fun String.isSearching() = length >= MIN_SEARCH_LENGTH + +private fun RelayItem.createState( + relayListType: RelayListType, + selectedByOther: RelayItemId?, +): RelayListItemState? { + val selectedByOther = + when (this) { + is RelayItem.CustomList -> { + selectedByOther == customList.id || + customList.locations.all { it == selectedByOther } + } + is RelayItem.Location.City -> selectedByOther == id + is RelayItem.Location.Country -> selectedByOther == id + is RelayItem.Location.Relay -> selectedByOther == id + } + return if (selectedByOther) { + when (relayListType) { + RelayListType.ENTRY -> RelayListItemState.USED_AS_EXIT + RelayListType.EXIT -> RelayListItemState.USED_AS_ENTRY + } + } else { + null + } +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModel.kt new file mode 100644 index 000000000000..74cecbfdda4f --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModel.kt @@ -0,0 +1,211 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.ramcosta.composedestinations.generated.destinations.SearchLocationDestination +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.compose.communication.CustomListAction +import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.model.RelayItemId +import net.mullvad.mullvadvpn.relaylist.MIN_SEARCH_LENGTH +import net.mullvad.mullvadvpn.relaylist.newFilterOnSearch +import net.mullvad.mullvadvpn.repository.CustomListsRepository +import net.mullvad.mullvadvpn.repository.RelayListFilterRepository +import net.mullvad.mullvadvpn.repository.RelayListRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.usecase.FilterChip +import net.mullvad.mullvadvpn.usecase.FilterChipUseCase +import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase +import net.mullvad.mullvadvpn.usecase.SelectedLocationUseCase +import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase +import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase +import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase +import net.mullvad.mullvadvpn.util.combine + +@Suppress("LongParameterList") +class SearchLocationViewModel( + private val wireguardConstraintsRepository: WireguardConstraintsRepository, + private val relayListRepository: RelayListRepository, + private val filteredRelayListUseCase: FilteredRelayListUseCase, + private val customListActionUseCase: CustomListActionUseCase, + private val customListsRepository: CustomListsRepository, + private val relayListFilterRepository: RelayListFilterRepository, + private val filterChipUseCase: FilterChipUseCase, + filteredCustomListRelayItemsUseCase: FilterCustomListsRelayItemUseCase, + selectedLocationUseCase: SelectedLocationUseCase, + customListsRelayItemUseCase: CustomListsRelayItemUseCase, + savedStateHandle: SavedStateHandle, +) : ViewModel() { + + private val relayListType: RelayListType = + SearchLocationDestination.argsFrom(savedStateHandle).relayListType + + private val _searchTerm = MutableStateFlow(EMPTY_SEARCH_TERM) + private val _expandedItems = MutableStateFlow>(emptySet()) + + val uiState: StateFlow = + combine( + _searchTerm, + searchRelayListLocations(), + filteredCustomListRelayItemsUseCase(relayListType = relayListType), + customListsRelayItemUseCase(), + selectedLocationUseCase(), + filterChips(), + _expandedItems, + ) { + searchTerm, + relayCountries, + filteredCustomLists, + customLists, + selectedItem, + filterChips, + expandedItems -> + if (searchTerm.length >= MIN_SEARCH_LENGTH) { + SearchLocationUiState.Content( + searchTerm = searchTerm, + relayListItems = + relayListItems( + searchTerm = searchTerm, + relayCountries = relayCountries, + relayListType = relayListType, + customLists = filteredCustomLists, + selectedByThisEntryExitList = + selectedItem.selectedByThisEntryExitList(relayListType), + selectedByOtherEntryExitList = + selectedItem.selectedByOtherEntryExitList( + relayListType, + customLists, + ), + expandedItems = expandedItems, + ), + customLists = customLists, + filterChips = filterChips, + ) + } else { + SearchLocationUiState.NoQuery(searchTerm, filterChips) + } + } + .stateIn( + viewModelScope, + SharingStarted.WhileSubscribed(), + SearchLocationUiState.NoQuery("", emptyList()), + ) + + private val _uiSideEffect = Channel() + val uiSideEffect = _uiSideEffect.receiveAsFlow() + + fun onSearchInputUpdated(searchTerm: String) { + viewModelScope.launch { _searchTerm.emit(searchTerm) } + } + + fun selectRelay(relayItem: RelayItem) { + viewModelScope.launch { + selectRelayItem( + relayItem = relayItem, + relayListType = relayListType, + selectEntryLocation = wireguardConstraintsRepository::setEntryLocation, + selectExitLocation = relayListRepository::updateSelectedRelayLocation, + ) + .fold( + { _uiSideEffect.send(SearchLocationSideEffect.GenericError) }, + { _uiSideEffect.send(SearchLocationSideEffect.LocationSelected(relayListType)) }, + ) + } + } + + private fun searchRelayListLocations() = + combine(_searchTerm, filteredRelayListUseCase(relayListType)) { searchTerm, relayCountries + -> + val (exp, filteredRelayCountries) = relayCountries.newFilterOnSearch(searchTerm) + exp.map { it.expandKey() }.toSet() to filteredRelayCountries + } + .onEach { _expandedItems.value = it.first } + .map { it.second } + + private fun filterChips() = + combine( + filterChipUseCase(relayListType), + wireguardConstraintsRepository.wireguardConstraints, + ) { filterChips, constraints -> + filterChips.toMutableList().apply { + // Do not show entry and exit filter chips if multihop is disabled + if (constraints?.isMultihopEnabled == true) { + add( + when (relayListType) { + RelayListType.ENTRY -> FilterChip.Entry + RelayListType.EXIT -> FilterChip.Exit + } + ) + } + } + } + + fun addLocationToList(item: RelayItem.Location, customList: RelayItem.CustomList) { + viewModelScope.launch { + val result = + addLocationToCustomList( + item = item, + customList = customList, + update = customListActionUseCase::invoke, + ) + _uiSideEffect.send(SearchLocationSideEffect.CustomListActionToast(result)) + } + } + + fun removeLocationFromList(item: RelayItem.Location, customListId: CustomListId) { + viewModelScope.launch { + val result = + removeLocationFromCustomList( + item = item, + customListId = customListId, + getCustomListById = customListsRepository::getCustomListById, + update = customListActionUseCase::invoke, + ) + _uiSideEffect.trySend(SearchLocationSideEffect.CustomListActionToast(result)) + } + } + + fun performAction(action: CustomListAction) { + viewModelScope.launch { customListActionUseCase(action) } + } + + fun removeOwnerFilter() { + viewModelScope.launch { relayListFilterRepository.updateSelectedOwnership(Constraint.Any) } + } + + fun removeProviderFilter() { + viewModelScope.launch { relayListFilterRepository.updateSelectedProviders(Constraint.Any) } + } + + fun onToggleExpand(item: RelayItemId, parent: CustomListId? = null, expand: Boolean) { + _expandedItems.onToggleExpand(item = item, parent = parent, expand = expand) + } + + companion object { + private const val EMPTY_SEARCH_TERM = "" + } +} + +sealed interface SearchLocationSideEffect { + data class LocationSelected(val relayListType: RelayListType) : SearchLocationSideEffect + + data class CustomListActionToast(val resultData: CustomListActionResultData) : + SearchLocationSideEffect + + data object GenericError : SearchLocationSideEffect +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModel.kt new file mode 100644 index 000000000000..d5063f0f4434 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModel.kt @@ -0,0 +1,89 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.GeoLocationId +import net.mullvad.mullvadvpn.lib.model.RelayItemId +import net.mullvad.mullvadvpn.repository.RelayListRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase +import net.mullvad.mullvadvpn.usecase.SelectedLocationUseCase +import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase +import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase + +class SelectLocationListViewModel( + private val relayListType: RelayListType, + private val filteredRelayListUseCase: FilteredRelayListUseCase, + private val filteredCustomListRelayItemsUseCase: FilterCustomListsRelayItemUseCase, + private val selectedLocationUseCase: SelectedLocationUseCase, + private val wireguardConstraintsRepository: WireguardConstraintsRepository, + private val relayListRepository: RelayListRepository, + customListsRelayItemUseCase: CustomListsRelayItemUseCase, +) : ViewModel() { + private val _expandedItems: MutableStateFlow> = + MutableStateFlow(initialExpand(initialSelection())) + + val uiState: StateFlow = + combine(relayListItems(), customListsRelayItemUseCase()) { relayListItems, customLists -> + SelectLocationListUiState.Content( + relayListItems = relayListItems, + customLists = customLists, + ) + } + .stateIn(viewModelScope, SharingStarted.Lazily, SelectLocationListUiState.Loading) + + fun onToggleExpand(item: RelayItemId, parent: CustomListId? = null, expand: Boolean) { + _expandedItems.onToggleExpand(item, parent, expand) + } + + private fun relayListItems() = + combine( + filteredRelayListUseCase(relayListType = relayListType), + filteredCustomListRelayItemsUseCase(relayListType = relayListType), + selectedLocationUseCase(), + _expandedItems, + ) { relayCountries, customLists, selectedItem, expandedItems -> + relayListItems( + relayCountries = relayCountries, + relayListType = relayListType, + customLists = customLists, + selectedByThisEntryExitList = + selectedItem.selectedByThisEntryExitList(relayListType), + selectedByOtherEntryExitList = + selectedItem.selectedByOtherEntryExitList(relayListType, customLists), + expandedItems = expandedItems, + ) + } + + private fun initialExpand(item: RelayItemId?): Set = buildSet { + when (item) { + is GeoLocationId.City -> { + add(item.country.code) + } + is GeoLocationId.Hostname -> { + add(item.country.code) + add(item.city.code) + } + is CustomListId, + is GeoLocationId.Country, + null -> { + /* No expands */ + } + } + } + + private fun initialSelection() = + when (relayListType) { + RelayListType.ENTRY -> + wireguardConstraintsRepository.wireguardConstraints.value?.entryLocation + RelayListType.EXIT -> relayListRepository.selectedLocation.value + }?.getOrNull() +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModel.kt new file mode 100644 index 000000000000..dd6736a45d9e --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModel.kt @@ -0,0 +1,145 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch +import net.mullvad.mullvadvpn.compose.communication.CustomListAction +import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.CustomListId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.repository.CustomListsRepository +import net.mullvad.mullvadvpn.repository.RelayListFilterRepository +import net.mullvad.mullvadvpn.repository.RelayListRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.usecase.FilterChipUseCase +import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase + +@OptIn(ExperimentalCoroutinesApi::class) +@Suppress("TooManyFunctions") +class SelectLocationViewModel( + private val relayListFilterRepository: RelayListFilterRepository, + private val customListsRepository: CustomListsRepository, + private val customListActionUseCase: CustomListActionUseCase, + private val relayListRepository: RelayListRepository, + private val wireguardConstraintsRepository: WireguardConstraintsRepository, + private val filterChipUseCase: FilterChipUseCase, +) : ViewModel() { + private val _relayListType: MutableStateFlow = + MutableStateFlow(initialRelayListSelection()) + + val uiState = + combine( + filterChips(), + wireguardConstraintsRepository.wireguardConstraints, + _relayListType, + ) { filterChips, wireguardConstraints, relayListSelection -> + SelectLocationUiState( + filterChips = filterChips, + multihopEnabled = wireguardConstraints?.isMultihopEnabled == true, + relayListType = relayListSelection, + ) + } + .stateIn( + viewModelScope, + SharingStarted.Lazily, + SelectLocationUiState( + filterChips = emptyList(), + multihopEnabled = false, + relayListType = RelayListType.EXIT, + ), + ) + + private val _uiSideEffect = Channel() + val uiSideEffect = _uiSideEffect.receiveAsFlow() + + private fun initialRelayListSelection() = + if (wireguardConstraintsRepository.wireguardConstraints.value?.isMultihopEnabled == true) { + RelayListType.ENTRY + } else { + RelayListType.EXIT + } + + private fun filterChips() = _relayListType.flatMapLatest { filterChipUseCase(it) } + + fun selectRelayList(relayListType: RelayListType) { + viewModelScope.launch { _relayListType.emit(relayListType) } + } + + fun selectRelay(relayItem: RelayItem) { + viewModelScope.launch { + selectRelayItem( + relayItem = relayItem, + relayListType = _relayListType.value, + selectEntryLocation = wireguardConstraintsRepository::setEntryLocation, + selectExitLocation = relayListRepository::updateSelectedRelayLocation, + ) + .fold( + { _uiSideEffect.send(SelectLocationSideEffect.GenericError) }, + { + when (_relayListType.value) { + RelayListType.ENTRY -> _relayListType.emit(RelayListType.EXIT) + RelayListType.EXIT -> + _uiSideEffect.send(SelectLocationSideEffect.CloseScreen) + } + }, + ) + } + } + + fun addLocationToList(item: RelayItem.Location, customList: RelayItem.CustomList) { + viewModelScope.launch { + val result = + addLocationToCustomList( + item = item, + customList = customList, + update = customListActionUseCase::invoke, + ) + _uiSideEffect.send(SelectLocationSideEffect.CustomListActionToast(result)) + } + } + + fun removeLocationFromList(item: RelayItem.Location, customListId: CustomListId) { + viewModelScope.launch { + val result = + removeLocationFromCustomList( + item = item, + customListId = customListId, + getCustomListById = customListsRepository::getCustomListById, + update = customListActionUseCase::invoke, + ) + _uiSideEffect.trySend(SelectLocationSideEffect.CustomListActionToast(result)) + } + } + + fun performAction(action: CustomListAction) { + viewModelScope.launch { customListActionUseCase(action) } + } + + fun removeOwnerFilter() { + viewModelScope.launch { relayListFilterRepository.updateSelectedOwnership(Constraint.Any) } + } + + fun removeProviderFilter() { + viewModelScope.launch { relayListFilterRepository.updateSelectedProviders(Constraint.Any) } + } +} + +sealed interface SelectLocationSideEffect { + data object CloseScreen : SelectLocationSideEffect + + data class CustomListActionToast(val resultData: CustomListActionResultData) : + SelectLocationSideEffect + + data object GenericError : SelectLocationSideEffect +} diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectRelay.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectRelay.kt new file mode 100644 index 000000000000..8d6c90961bb9 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectRelay.kt @@ -0,0 +1,21 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import arrow.core.Either +import arrow.core.raise.either +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.model.RelayItemId + +internal suspend fun selectRelayItem( + relayItem: RelayItem, + relayListType: RelayListType, + selectEntryLocation: suspend (RelayItemId) -> Either, + selectExitLocation: suspend (RelayItemId) -> Either, +) = + either { + val locationConstraint = relayItem.id + when (relayListType) { + RelayListType.ENTRY -> selectEntryLocation(locationConstraint) + RelayListType.EXIT -> selectExitLocation(locationConstraint) + } + } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCaseTest.kt new file mode 100644 index 000000000000..8b3d6d68a2ae --- /dev/null +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/FilterChipUseCaseTest.kt @@ -0,0 +1,146 @@ +package net.mullvad.mullvadvpn.usecase + +import app.cash.turbine.test +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.lib.common.test.assertLists +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.Ownership +import net.mullvad.mullvadvpn.lib.model.Provider +import net.mullvad.mullvadvpn.lib.model.ProviderId +import net.mullvad.mullvadvpn.lib.model.Providers +import net.mullvad.mullvadvpn.lib.model.Settings +import net.mullvad.mullvadvpn.lib.model.WireguardConstraints +import net.mullvad.mullvadvpn.repository.RelayListFilterRepository +import net.mullvad.mullvadvpn.repository.SettingsRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class FilterChipUseCaseTest { + + private val mockRelayListFilterRepository: RelayListFilterRepository = mockk() + private val mockAvailableProvidersUseCase: AvailableProvidersUseCase = mockk() + private val mockSettingRepository: SettingsRepository = mockk() + private val mockWireguardConstraintsRepository: WireguardConstraintsRepository = mockk() + + private val selectedOwnership = MutableStateFlow>(Constraint.Any) + private val selectedProviders = MutableStateFlow>(Constraint.Any) + private val availableProviders = MutableStateFlow>(emptyList()) + private val settings = MutableStateFlow(mockk(relaxed = true)) + private val wireguardConstraints = MutableStateFlow(mockk(relaxed = true)) + + private lateinit var filterChipUseCase: FilterChipUseCase + + @BeforeEach + fun setUp() { + every { mockRelayListFilterRepository.selectedOwnership } returns selectedOwnership + every { mockRelayListFilterRepository.selectedProviders } returns selectedProviders + every { mockAvailableProvidersUseCase() } returns availableProviders + every { mockSettingRepository.settingsUpdates } returns settings + every { mockWireguardConstraintsRepository.wireguardConstraints } returns + wireguardConstraints + + filterChipUseCase = + FilterChipUseCase( + relayListFilterRepository = mockRelayListFilterRepository, + availableProvidersUseCase = mockAvailableProvidersUseCase, + settingsRepository = mockSettingRepository, + wireguardConstraintsRepository = mockWireguardConstraintsRepository, + ) + } + + @Test + fun `when no filters are applied should return empty list`() = runTest { + filterChipUseCase(RelayListType.EXIT).test { assertLists(emptyList(), awaitItem()) } + } + + @Test + fun `when ownership filter is applied should return correct ownership`() = runTest { + // Arrange + val expectedOwnership = Ownership.MullvadOwned + selectedOwnership.value = Constraint.Only(expectedOwnership) + + filterChipUseCase(RelayListType.EXIT).test { + assertLists(listOf(FilterChip.Ownership(expectedOwnership)), awaitItem()) + } + } + + @Test + fun `when provider filter is applied should return correct number of providers`() = runTest { + // Arrange + val expectedProviders = Providers(providers = setOf(ProviderId("1"), ProviderId("2"))) + selectedProviders.value = Constraint.Only(expectedProviders) + availableProviders.value = + listOf( + Provider(ProviderId("1"), Ownership.MullvadOwned), + Provider(ProviderId("2"), Ownership.Rented), + ) + + filterChipUseCase(RelayListType.EXIT).test { + assertLists(listOf(FilterChip.Provider(2)), awaitItem()) + } + } + + @Test + fun `when provider and ownership filter is applied should return correct filter chips`() = + runTest { + // Arrange + val expectedProviders = Providers(providers = setOf(ProviderId("1"))) + val expectedOwnership = Ownership.MullvadOwned + selectedProviders.value = Constraint.Only(expectedProviders) + selectedOwnership.value = Constraint.Only(expectedOwnership) + availableProviders.value = + listOf( + Provider(ProviderId("1"), Ownership.MullvadOwned), + Provider(ProviderId("2"), Ownership.Rented), + ) + + filterChipUseCase(RelayListType.EXIT).test { + assertLists( + listOf(FilterChip.Ownership(expectedOwnership), FilterChip.Provider(1)), + awaitItem(), + ) + } + } + + @Test + fun `when Daita is enabled and multihop is disabled should return Daita filter chip`() = + runTest { + // Arrange + settings.value = mockk(relaxed = true) { every { isDaitaEnabled() } returns true } + wireguardConstraints.value = + mockk(relaxed = true) { every { isMultihopEnabled } returns false } + + filterChipUseCase(RelayListType.EXIT).test { + assertLists(listOf(FilterChip.Daita), awaitItem()) + } + } + + @Test + fun `when Daita is enabled and multihop is enabled and relay list type is entry should return Daita filter chip`() = + runTest { + // Arrange + settings.value = mockk(relaxed = true) { every { isDaitaEnabled() } returns true } + wireguardConstraints.value = + mockk(relaxed = true) { every { isMultihopEnabled } returns true } + + filterChipUseCase(RelayListType.ENTRY).test { + assertLists(listOf(FilterChip.Daita), awaitItem()) + } + } + + @Test + fun `when Daita is enabled and multihop is enabled and relay list type is exit should return no filter`() = + runTest { + // Arrange + settings.value = mockk(relaxed = true) { every { isDaitaEnabled() } returns true } + wireguardConstraints.value = + mockk(relaxed = true) { every { isMultihopEnabled } returns true } + + filterChipUseCase(RelayListType.EXIT).test { assertLists(emptyList(), awaitItem()) } + } +} diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCaseTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCaseTest.kt new file mode 100644 index 000000000000..deef7b7ab9fb --- /dev/null +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/usecase/SelectedLocationUseCaseTest.kt @@ -0,0 +1,71 @@ +package net.mullvad.mullvadvpn.usecase + +import app.cash.turbine.test +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.GeoLocationId +import net.mullvad.mullvadvpn.lib.model.RelayItemId +import net.mullvad.mullvadvpn.lib.model.RelayItemSelection +import net.mullvad.mullvadvpn.lib.model.WireguardConstraints +import net.mullvad.mullvadvpn.repository.RelayListRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class SelectedLocationUseCaseTest { + private val mockRelayListRepository: RelayListRepository = mockk() + private val mockWireguardConstraintsRepository: WireguardConstraintsRepository = mockk() + + private val selectedLocation = MutableStateFlow>(Constraint.Any) + private val wireguardConstraints = MutableStateFlow(mockk(relaxed = true)) + + private lateinit var selectLocationUseCase: SelectedLocationUseCase + + @BeforeEach + fun setup() { + every { mockRelayListRepository.selectedLocation } returns selectedLocation + every { mockWireguardConstraintsRepository.wireguardConstraints } returns + wireguardConstraints + + selectLocationUseCase = + SelectedLocationUseCase( + relayListRepository = mockRelayListRepository, + wireguardConstraintsRepository = mockWireguardConstraintsRepository, + ) + } + + @Test + fun `when wireguard constraints is multihop enabled should return Multiple`() = runTest { + // Arrange + val entryLocation: Constraint = Constraint.Only(GeoLocationId.Country("se")) + val exitLocation = Constraint.Only(GeoLocationId.Country("us")) + wireguardConstraints.value = + WireguardConstraints( + isMultihopEnabled = true, + entryLocation = entryLocation, + port = Constraint.Any, + ) + selectedLocation.value = exitLocation + + // Act, Assert + selectLocationUseCase().test { + assertEquals(RelayItemSelection.Multiple(entryLocation, exitLocation), awaitItem()) + } + } + + @Test + fun `when wireguard constraints is multihop disabled should return Single`() = runTest { + // Arrange + val exitLocation = Constraint.Only(GeoLocationId.Country("us")) + selectedLocation.value = exitLocation + + // Act, Assert + selectLocationUseCase().test { + assertEquals(RelayItemSelection.Single(exitLocation), awaitItem()) + } + } +} diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModelTest.kt new file mode 100644 index 000000000000..34cb1353bbca --- /dev/null +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/MultihopViewModelTest.kt @@ -0,0 +1,68 @@ +package net.mullvad.mullvadvpn.viewmodel + +import app.cash.turbine.test +import arrow.core.Either +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.WireguardConstraints +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestCoroutineRule::class) +class MultihopViewModelTest { + + private val mockWireguardConstraintsRepository: WireguardConstraintsRepository = mockk() + + private val wireguardConstraints = MutableStateFlow(mockk(relaxed = true)) + + private lateinit var multihopViewModel: MultihopViewModel + + @BeforeEach + fun setUp() { + every { mockWireguardConstraintsRepository.wireguardConstraints } returns + wireguardConstraints + + multihopViewModel = + MultihopViewModel(wireguardConstraintsRepository = mockWireguardConstraintsRepository) + } + + @Test + fun `default state should be multihop disabled`() { + assertEquals(false, multihopViewModel.uiState.value.enable) + } + + @Test + fun `when multihop enabled is true state should return multihop enabled true`() = runTest { + // Arrange + wireguardConstraints.value = + WireguardConstraints( + isMultihopEnabled = true, + entryLocation = Constraint.Any, + port = Constraint.Any, + ) + + // Act, Assert + multihopViewModel.uiState.test { assertEquals(MultihopUiState(true), awaitItem()) } + } + + @Test + fun `when set multihop is called should call repository set multihop`() = runTest { + // Arrange + coEvery { mockWireguardConstraintsRepository.setMultihop(any()) } returns Either.Right(Unit) + + // Act + multihopViewModel.setMultihop(true) + + // Assert + coVerify { mockWireguardConstraintsRepository.setMultihop(true) } + } +} diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt index 8857eb364a24..f2468cbb11e0 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SettingsViewModelTest.kt @@ -10,8 +10,11 @@ import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule +import net.mullvad.mullvadvpn.lib.model.Constraint import net.mullvad.mullvadvpn.lib.model.DeviceState +import net.mullvad.mullvadvpn.lib.model.WireguardConstraints import net.mullvad.mullvadvpn.lib.shared.DeviceRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository import net.mullvad.mullvadvpn.ui.VersionInfo import net.mullvad.mullvadvpn.ui.serviceconnection.AppVersionInfoRepository import org.junit.jupiter.api.AfterEach @@ -24,9 +27,11 @@ class SettingsViewModelTest { private val mockDeviceRepository: DeviceRepository = mockk() private val mockAppVersionInfoRepository: AppVersionInfoRepository = mockk() + private val mockWireguardConstraintsRepository: WireguardConstraintsRepository = mockk() private val versionInfo = MutableStateFlow(VersionInfo(currentVersion = "", isSupported = false)) + private val wireguardConstraints = MutableStateFlow(mockk(relaxed = true)) private lateinit var viewModel: SettingsViewModel @@ -36,11 +41,14 @@ class SettingsViewModelTest { every { mockDeviceRepository.deviceState } returns deviceState every { mockAppVersionInfoRepository.versionInfo } returns versionInfo + every { mockWireguardConstraintsRepository.wireguardConstraints } returns + wireguardConstraints viewModel = SettingsViewModel( deviceRepository = mockDeviceRepository, appVersionInfoRepository = mockAppVersionInfoRepository, + wireguardConstraintsRepository = mockWireguardConstraintsRepository, isPlayBuild = false, ) } @@ -84,4 +92,22 @@ class SettingsViewModelTest { assertEquals(false, result.isSupportedVersion) } } + + @Test + fun `when WireguardConstraintsRepository return multihop enabled uiState should return multihop enabled true`() = + runTest { + // Arrange + wireguardConstraints.value = + WireguardConstraints( + isMultihopEnabled = true, + entryLocation = Constraint.Any, + port = Constraint.Any, + ) + + // Act, Assert + viewModel.uiState.test { + val result = awaitItem() + assertEquals(true, result.multihopEnabled) + } + } } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt index 340809fbb3c7..427b003d332c 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt @@ -189,7 +189,7 @@ class VpnSettingsViewModelTest { val wireguardConstraints = WireguardConstraints( port = wireguardPort, - useMultihop = false, + isMultihopEnabled = false, entryLocation = Constraint.Any, ) coEvery { mockWireguardConstraintsRepository.setWireguardPort(any()) } returns diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModelTest.kt new file mode 100644 index 000000000000..be60f9d723f1 --- /dev/null +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModelTest.kt @@ -0,0 +1,161 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import app.cash.turbine.test +import com.ramcosta.composedestinations.generated.navargs.toSavedStateHandle +import io.mockk.every +import io.mockk.mockk +import kotlin.test.assertIs +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import net.mullvad.mullvadvpn.compose.screen.location.SearchLocationNavArgs +import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState +import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule +import net.mullvad.mullvadvpn.lib.common.test.assertLists +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.GeoLocationId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.model.RelayItemSelection +import net.mullvad.mullvadvpn.lib.model.WireguardConstraints +import net.mullvad.mullvadvpn.repository.CustomListsRepository +import net.mullvad.mullvadvpn.repository.RelayListFilterRepository +import net.mullvad.mullvadvpn.repository.RelayListRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.usecase.FilterChip +import net.mullvad.mullvadvpn.usecase.FilterChipUseCase +import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase +import net.mullvad.mullvadvpn.usecase.SelectedLocationUseCase +import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase +import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase +import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestCoroutineRule::class) +class SearchLocationViewModelTest { + + private val mockWireguardConstraintsRepository: WireguardConstraintsRepository = mockk() + private val mockRelayListRepository: RelayListRepository = mockk() + private val mockFilteredRelayListUseCase: FilteredRelayListUseCase = mockk() + private val mockCustomListActionUseCase: CustomListActionUseCase = mockk() + private val mockCustomListsRepository: CustomListsRepository = mockk() + private val mockRelayListFilterRepository: RelayListFilterRepository = mockk() + private val mockFilterChipUseCase: FilterChipUseCase = mockk() + private val mockFilteredCustomListRelayItemsUseCase: FilterCustomListsRelayItemUseCase = mockk() + private val mockSelectedLocationUseCase: SelectedLocationUseCase = mockk() + private val mockCustomListsRelayItemUseCase: CustomListsRelayItemUseCase = mockk() + + private val filteredRelayList = MutableStateFlow>(emptyList()) + private val selectedLocation = + MutableStateFlow(RelayItemSelection.Single(Constraint.Any)) + private val filteredCustomListRelayItems = + MutableStateFlow>(emptyList()) + private val customListRelayItems = MutableStateFlow>(emptyList()) + private val filterChips = MutableStateFlow>(emptyList()) + private val wireguardConstraints = MutableStateFlow(mockk(relaxed = true)) + + private lateinit var viewModel: SearchLocationViewModel + + @BeforeEach + fun setup() { + every { mockFilteredRelayListUseCase(any()) } returns filteredRelayList + every { mockSelectedLocationUseCase() } returns selectedLocation + every { mockFilteredCustomListRelayItemsUseCase(any()) } returns + filteredCustomListRelayItems + every { mockCustomListsRelayItemUseCase() } returns customListRelayItems + every { mockFilterChipUseCase(any()) } returns filterChips + every { mockWireguardConstraintsRepository.wireguardConstraints } returns + wireguardConstraints + + viewModel = + SearchLocationViewModel( + wireguardConstraintsRepository = mockWireguardConstraintsRepository, + relayListRepository = mockRelayListRepository, + filteredRelayListUseCase = mockFilteredRelayListUseCase, + customListActionUseCase = mockCustomListActionUseCase, + customListsRepository = mockCustomListsRepository, + relayListFilterRepository = mockRelayListFilterRepository, + filterChipUseCase = mockFilterChipUseCase, + filteredCustomListRelayItemsUseCase = mockFilteredCustomListRelayItemsUseCase, + selectedLocationUseCase = mockSelectedLocationUseCase, + customListsRelayItemUseCase = mockCustomListsRelayItemUseCase, + savedStateHandle = + SearchLocationNavArgs(relayListType = RelayListType.ENTRY).toSavedStateHandle(), + ) + } + + @Test + fun `on onSearchTermInput call uiState should emit with filtered countries`() = runTest { + // Arrange + val mockSearchString = "got" + filteredRelayList.value = testCountries + + // Act, Assert + viewModel.uiState.test() { + // Wait for first data + assertIs(awaitItem()) + + // Update search string + viewModel.onSearchInputUpdated(mockSearchString) + + // We get some unnecessary emissions for now + awaitItem() + + val actualState = awaitItem() + assertIs(actualState) + assertTrue( + actualState.relayListItems.filterIsInstance().any { + it.item is RelayItem.Location.City && it.item.name == "Gothenburg" + } + ) + } + } + + @Test + fun `when onSearchTermInput returns empty result uiState should return empty list`() = runTest { + // Arrange + filteredRelayList.value = testCountries + val mockSearchString = "SEARCH" + + // Act, Assert + viewModel.uiState.test { + // Wait for first data + assertIs(awaitItem()) + + // Update search string + viewModel.onSearchInputUpdated(mockSearchString) + + // We get some unnecessary emissions for now + awaitItem() + + // Assert + val actualState = awaitItem() + assertIs(actualState) + assertLists( + listOf(RelayListItem.LocationsEmptyText(mockSearchString)), + actualState.relayListItems, + ) + } + } + + companion object { + private val testCountries = + listOf( + RelayItem.Location.Country( + id = GeoLocationId.Country("se"), + "Sweden", + listOf( + RelayItem.Location.City( + id = GeoLocationId.City(GeoLocationId.Country("se"), "got"), + "Gothenburg", + emptyList(), + ) + ), + ), + RelayItem.Location.Country(id = GeoLocationId.Country("no"), "Norway", emptyList()), + ) + } +} diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModelTest.kt new file mode 100644 index 000000000000..358487717016 --- /dev/null +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModelTest.kt @@ -0,0 +1,158 @@ +package net.mullvad.mullvadvpn.viewmodel.location + +import app.cash.turbine.test +import io.mockk.every +import io.mockk.mockk +import kotlin.test.assertIs +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.test.runTest +import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListType +import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState +import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule +import net.mullvad.mullvadvpn.lib.common.test.assertLists +import net.mullvad.mullvadvpn.lib.model.Constraint +import net.mullvad.mullvadvpn.lib.model.GeoLocationId +import net.mullvad.mullvadvpn.lib.model.RelayItem +import net.mullvad.mullvadvpn.lib.model.RelayItemSelection +import net.mullvad.mullvadvpn.repository.RelayListRepository +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase +import net.mullvad.mullvadvpn.usecase.SelectedLocationUseCase +import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase +import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith + +@ExtendWith(TestCoroutineRule::class) +class SelectLocationListViewModelTest { + + private val mockFilteredRelayListUseCase: FilteredRelayListUseCase = mockk() + private val mockFilteredCustomListRelayItemsUseCase: FilterCustomListsRelayItemUseCase = mockk() + private val mockSelectedLocationUseCase: SelectedLocationUseCase = mockk() + private val mockWireguardConstraintsRepository: WireguardConstraintsRepository = mockk() + private val mockRelayListRepository: RelayListRepository = mockk() + private val mockCustomListRelayItemsUseCase: CustomListsRelayItemUseCase = mockk() + + private val filteredRelayList = MutableStateFlow>(emptyList()) + private val selectedLocationFlow = MutableStateFlow(mockk(relaxed = true)) + private val filteredCustomListRelayItems = + MutableStateFlow>(emptyList()) + private val customListRelayItems = MutableStateFlow>(emptyList()) + + private lateinit var viewModel: SelectLocationListViewModel + + @BeforeEach + fun setUp() { + // Used for initial selection + every { mockRelayListRepository.selectedLocation } returns MutableStateFlow(Constraint.Any) + every { mockWireguardConstraintsRepository.wireguardConstraints } returns + MutableStateFlow(null) + + every { mockSelectedLocationUseCase() } returns selectedLocationFlow + every { mockFilteredRelayListUseCase(any()) } returns filteredRelayList + every { mockFilteredCustomListRelayItemsUseCase(any()) } returns + filteredCustomListRelayItems + every { mockCustomListRelayItemsUseCase() } returns customListRelayItems + } + + @Test + fun `initial state should be loading`() = runTest { + // Arrange + viewModel = createSelectLocationListViewModel(relayListType = RelayListType.ENTRY) + + // Assert + assertEquals(SelectLocationListUiState.Loading, viewModel.uiState.value) + } + + @Test + fun `given filteredRelayList emits update uiState should contain new update`() = runTest { + // Arrange + viewModel = createSelectLocationListViewModel(RelayListType.EXIT) + filteredRelayList.value = testCountries + val selectedId = testCountries.first().id + selectedLocationFlow.value = RelayItemSelection.Single(Constraint.Only(selectedId)) + + // Act, Assert + viewModel.uiState.test { + val actualState = awaitItem() + assertIs(actualState) + assertLists( + testCountries.map { it.id }, + actualState.relayListItems.mapNotNull { it.relayItemId() }, + ) + assertTrue( + actualState.relayListItems + .filterIsInstance() + .first { it.relayItemId() == selectedId } + .isSelected + ) + } + } + + @Test + fun `given relay is not selected all relay items should not be selected`() = runTest { + // Arrange + viewModel = createSelectLocationListViewModel(RelayListType.EXIT) + filteredRelayList.value = testCountries + selectedLocationFlow.value = RelayItemSelection.Single(Constraint.Any) + + // Act, Assert + viewModel.uiState.test { + val actualState = awaitItem() + assertIs(actualState) + assertLists( + testCountries.map { it.id }, + actualState.relayListItems.mapNotNull { it.relayItemId() }, + ) + assertTrue( + actualState.relayListItems.filterIsInstance().all { + !it.isSelected + } + ) + } + } + + private fun createSelectLocationListViewModel(relayListType: RelayListType) = + SelectLocationListViewModel( + relayListType = relayListType, + filteredRelayListUseCase = mockFilteredRelayListUseCase, + filteredCustomListRelayItemsUseCase = mockFilteredCustomListRelayItemsUseCase, + selectedLocationUseCase = mockSelectedLocationUseCase, + wireguardConstraintsRepository = mockWireguardConstraintsRepository, + relayListRepository = mockRelayListRepository, + customListsRelayItemUseCase = mockCustomListRelayItemsUseCase, + ) + + private fun RelayListItem.relayItemId() = + when (this) { + is RelayListItem.CustomListFooter -> null + RelayListItem.CustomListHeader -> null + RelayListItem.LocationHeader -> null + is RelayListItem.LocationsEmptyText -> null + is RelayListItem.CustomListEntryItem -> item.id + is RelayListItem.CustomListItem -> item.id + is RelayListItem.GeoLocationItem -> item.id + } + + companion object { + private val testCountries = + listOf( + RelayItem.Location.Country( + id = GeoLocationId.Country("se"), + "Sweden", + listOf( + RelayItem.Location.City( + id = GeoLocationId.City(GeoLocationId.Country("se"), "got"), + "Gothenburg", + emptyList(), + ) + ), + ), + RelayItem.Location.Country(id = GeoLocationId.Country("no"), "Norway", emptyList()), + ) + } +} diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModelTest.kt similarity index 52% rename from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt rename to android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModelTest.kt index bee888d279c3..ef21eac13945 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModelTest.kt @@ -1,4 +1,4 @@ -package net.mullvad.mullvadvpn.viewmodel +package net.mullvad.mullvadvpn.viewmodel.location import androidx.lifecycle.viewModelScope import app.cash.turbine.test @@ -11,39 +11,35 @@ import io.mockk.mockkStatic import io.mockk.unmockkAll import kotlin.test.assertEquals import kotlin.test.assertIs -import kotlin.test.assertTrue import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import net.mullvad.mullvadvpn.compose.communication.CustomListAction import net.mullvad.mullvadvpn.compose.communication.CustomListActionResultData import net.mullvad.mullvadvpn.compose.communication.LocationsChanged -import net.mullvad.mullvadvpn.compose.state.RelayListItem +import net.mullvad.mullvadvpn.compose.state.RelayListType import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule -import net.mullvad.mullvadvpn.lib.common.test.assertLists import net.mullvad.mullvadvpn.lib.model.Constraint import net.mullvad.mullvadvpn.lib.model.CustomList import net.mullvad.mullvadvpn.lib.model.CustomListId import net.mullvad.mullvadvpn.lib.model.CustomListName import net.mullvad.mullvadvpn.lib.model.GeoLocationId import net.mullvad.mullvadvpn.lib.model.Ownership -import net.mullvad.mullvadvpn.lib.model.Provider import net.mullvad.mullvadvpn.lib.model.Providers import net.mullvad.mullvadvpn.lib.model.RelayItem import net.mullvad.mullvadvpn.lib.model.RelayItemId -import net.mullvad.mullvadvpn.lib.model.Settings +import net.mullvad.mullvadvpn.lib.model.WireguardConstraints import net.mullvad.mullvadvpn.relaylist.descendants import net.mullvad.mullvadvpn.repository.CustomListsRepository import net.mullvad.mullvadvpn.repository.RelayListFilterRepository import net.mullvad.mullvadvpn.repository.RelayListRepository -import net.mullvad.mullvadvpn.repository.SettingsRepository -import net.mullvad.mullvadvpn.usecase.AvailableProvidersUseCase -import net.mullvad.mullvadvpn.usecase.FilteredRelayListUseCase +import net.mullvad.mullvadvpn.repository.WireguardConstraintsRepository +import net.mullvad.mullvadvpn.usecase.FilterChip +import net.mullvad.mullvadvpn.usecase.FilterChipUseCase import net.mullvad.mullvadvpn.usecase.customlists.CustomListActionUseCase -import net.mullvad.mullvadvpn.usecase.customlists.CustomListsRelayItemUseCase -import net.mullvad.mullvadvpn.usecase.customlists.FilterCustomListsRelayItemUseCase import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith @@ -52,39 +48,25 @@ import org.junit.jupiter.api.extension.ExtendWith class SelectLocationViewModelTest { private val mockRelayListFilterRepository: RelayListFilterRepository = mockk() - private val mockAvailableProvidersUseCase: AvailableProvidersUseCase = mockk(relaxed = true) private val mockCustomListActionUseCase: CustomListActionUseCase = mockk(relaxed = true) - private val mockFilteredCustomListRelayItemsUseCase: FilterCustomListsRelayItemUseCase = mockk() - private val mockFilteredRelayListUseCase: FilteredRelayListUseCase = mockk() private val mockRelayListRepository: RelayListRepository = mockk() private val mockCustomListsRepository: CustomListsRepository = mockk() - private val mockCustomListsRelayItemUseCase: CustomListsRelayItemUseCase = mockk() - - private val mockSettingsRepository: SettingsRepository = mockk() - private val settingsFlow = MutableStateFlow(mockk(relaxed = true)) + private val mockWireguardConstraintsRepository: WireguardConstraintsRepository = mockk() + private val mockFilterChipUseCase: FilterChipUseCase = mockk() private lateinit var viewModel: SelectLocationViewModel - private val allProviders = MutableStateFlow>(emptyList()) - private val selectedOwnership = MutableStateFlow>(Constraint.Any) - private val selectedProviders = MutableStateFlow>(Constraint.Any) private val selectedRelayItemFlow = MutableStateFlow>(Constraint.Any) - private val filteredRelayList = MutableStateFlow>(emptyList()) - private val filteredCustomRelayListItems = - MutableStateFlow>(emptyList()) - private val customListsRelayItem = MutableStateFlow>(emptyList()) + private val wireguardConstraints = MutableStateFlow(mockk(relaxed = true)) + private val filterChips = MutableStateFlow>(emptyList()) @BeforeEach fun setup() { - every { mockRelayListFilterRepository.selectedOwnership } returns selectedOwnership - every { mockRelayListFilterRepository.selectedProviders } returns selectedProviders - every { mockAvailableProvidersUseCase() } returns allProviders every { mockRelayListRepository.selectedLocation } returns selectedRelayItemFlow - every { mockFilteredRelayListUseCase() } returns filteredRelayList - every { mockFilteredCustomListRelayItemsUseCase() } returns filteredCustomRelayListItems - every { mockCustomListsRelayItemUseCase() } returns customListsRelayItem - every { mockSettingsRepository.settingsUpdates } returns settingsFlow + every { mockWireguardConstraintsRepository.wireguardConstraints } returns + wireguardConstraints + every { mockFilterChipUseCase(any()) } returns filterChips mockkStatic(RELAY_LIST_EXTENSIONS) mockkStatic(RELAY_ITEM_EXTENSIONS) @@ -92,14 +74,11 @@ class SelectLocationViewModelTest { viewModel = SelectLocationViewModel( relayListFilterRepository = mockRelayListFilterRepository, - availableProvidersUseCase = mockAvailableProvidersUseCase, - filteredCustomListRelayItemsUseCase = mockFilteredCustomListRelayItemsUseCase, customListActionUseCase = mockCustomListActionUseCase, - filteredRelayListUseCase = mockFilteredRelayListUseCase, relayListRepository = mockRelayListRepository, customListsRepository = mockCustomListsRepository, - customListsRelayItemUseCase = mockCustomListsRelayItemUseCase, - settingsRepository = mockSettingsRepository, + filterChipUseCase = mockFilterChipUseCase, + wireguardConstraintsRepository = mockWireguardConstraintsRepository, ) } @@ -110,131 +89,59 @@ class SelectLocationViewModelTest { } @Test - fun `initial state should be loading`() = runTest { - assertEquals(SelectLocationUiState.Loading, viewModel.uiState.value) - } - - @Test - fun `given filteredRelayList emits update uiState should contain new update`() = runTest { - // Arrange - filteredRelayList.value = testCountries - val selectedId = testCountries.first().id - selectedRelayItemFlow.value = Constraint.Only(selectedId) - - // Act, Assert - viewModel.uiState.test { - val actualState = awaitItem() - assertIs(actualState) - assertLists( - testCountries.map { it.id }, - actualState.relayListItems.mapNotNull { it.relayItemId() }, - ) - assertTrue( - actualState.relayListItems - .filterIsInstance() - .first { it.relayItemId() == selectedId } - .isSelected - ) - } - } - - @Test - fun `given relay is selected all relay items should not be selected`() = runTest { - // Arrange - filteredRelayList.value = testCountries - selectedRelayItemFlow.value = Constraint.Any - - // Act, Assert - viewModel.uiState.test { - val actualState = awaitItem() - assertIs(actualState) - assertLists( - testCountries.map { it.id }, - actualState.relayListItems.mapNotNull { it.relayItemId() }, - ) - assertTrue( - actualState.relayListItems.filterIsInstance().all { - !it.isSelected - } - ) - } - } - - @Test - fun `on selectRelay call uiSideEffect should emit CloseScreen and connect`() = runTest { - // Arrange - val mockRelayItem: RelayItem.Location.Country = mockk() - val relayItemId: GeoLocationId.Country = mockk(relaxed = true) - every { mockRelayItem.id } returns relayItemId - coEvery { mockRelayListRepository.updateSelectedRelayLocation(relayItemId) } returns - Unit.right() - - // Act, Assert - viewModel.uiSideEffect.test { - viewModel.selectRelay(mockRelayItem) - // Await an empty item - assertEquals(SelectLocationSideEffect.CloseScreen, awaitItem()) - coVerify { mockRelayListRepository.updateSelectedRelayLocation(relayItemId) } - } + fun `initial state should be correct`() = runTest { + Assertions.assertEquals( + SelectLocationUiState( + filterChips = emptyList(), + multihopEnabled = false, + relayListType = RelayListType.EXIT, + ), + viewModel.uiState.value, + ) } @Test - fun `on onSearchTermInput call uiState should emit with filtered countries`() = runTest { - // Arrange - val mockSearchString = "got" - filteredRelayList.value = testCountries - selectedRelayItemFlow.value = Constraint.Any - - // Act, Assert - viewModel.uiState.test { - // Wait for first data - assertIs(awaitItem()) - - // Update search string - viewModel.onSearchTermInput(mockSearchString) - - // We get some unnecessary emissions for now - awaitItem() - awaitItem() - awaitItem() + fun `on selectRelay when relay list type is exit call uiSideEffect should emit CloseScreen and connect`() = + runTest { + // Arrange + val mockRelayItem: RelayItem.Location.Country = mockk() + val relayItemId: GeoLocationId.Country = mockk(relaxed = true) + every { mockRelayItem.id } returns relayItemId + coEvery { mockRelayListRepository.updateSelectedRelayLocation(relayItemId) } returns + Unit.right() - val actualState = awaitItem() - assertIs(actualState) - assertTrue( - actualState.relayListItems.filterIsInstance().any { - it.item is RelayItem.Location.City && it.item.name == "Gothenburg" - } - ) + // Act, Assert + viewModel.uiSideEffect.test { + viewModel.selectRelay(mockRelayItem) + // Await an empty item + assertEquals(SelectLocationSideEffect.CloseScreen, awaitItem()) + coVerify { mockRelayListRepository.updateSelectedRelayLocation(relayItemId) } + } } - } @Test - fun `when onSearchTermInput returns empty result uiState should return empty list`() = runTest { - // Arrange - filteredRelayList.value = testCountries - val mockSearchString = "SEARCH" - - // Act, Assert - viewModel.uiState.test { - // Wait for first data - assertIs(awaitItem()) - - // Update search string - viewModel.onSearchTermInput(mockSearchString) - - // We get some unnecessary emissions for now - awaitItem() - awaitItem() + fun `on selectRelay when relay list type is entry call uiSideEffect should switch relay list type to exit`() = + runTest { + // Arrange + val mockRelayItem: RelayItem.Location.Country = mockk() + val relayItemId: GeoLocationId.Country = mockk(relaxed = true) + every { mockRelayItem.id } returns relayItemId + coEvery { mockWireguardConstraintsRepository.setEntryLocation(relayItemId) } returns + Unit.right() - // Assert - val actualState = awaitItem() - assertIs(actualState) - assertEquals( - listOf(RelayListItem.LocationsEmptyText(mockSearchString)), - actualState.relayListItems, - ) + // Act, Assert + viewModel.uiState.test { + awaitItem() // Default value + viewModel.selectRelayList(RelayListType.ENTRY) + // Assert relay list type is entry + assertEquals(RelayListType.ENTRY, awaitItem().relayListType) + // Select entry + viewModel.selectRelay(mockRelayItem) + // Await an empty item + assertEquals(RelayListType.EXIT, awaitItem().relayListType) + coVerify { mockWireguardConstraintsRepository.setEntryLocation(relayItemId) } + } } - } @Test fun `removeOwnerFilter should invoke use case with Constraint Any Ownership`() = runTest { @@ -372,17 +279,6 @@ class SelectLocationViewModelTest { } } - private fun RelayListItem.relayItemId() = - when (this) { - is RelayListItem.CustomListFooter -> null - RelayListItem.CustomListHeader -> null - RelayListItem.LocationHeader -> null - is RelayListItem.LocationsEmptyText -> null - is RelayListItem.CustomListEntryItem -> item.id - is RelayListItem.CustomListItem -> item.id - is RelayListItem.GeoLocationItem -> item.id - } - companion object { private const val RELAY_LIST_EXTENSIONS = "net.mullvad.mullvadvpn.relaylist.RelayListExtensionsKt" @@ -390,21 +286,5 @@ class SelectLocationViewModelTest { "net.mullvad.mullvadvpn.relaylist.RelayItemExtensionsKt" private const val CUSTOM_LIST_EXTENSIONS = "net.mullvad.mullvadvpn.relaylist.CustomListExtensionsKt" - - private val testCountries = - listOf( - RelayItem.Location.Country( - id = GeoLocationId.Country("se"), - "Sweden", - listOf( - RelayItem.Location.City( - id = GeoLocationId.City(GeoLocationId.Country("se"), "got"), - "Gothenburg", - emptyList(), - ) - ), - ), - RelayItem.Location.Country(id = GeoLocationId.Country("no"), "Norway", emptyList()), - ) } } diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt index ad4fb20a227f..bd27574cbeb2 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt @@ -95,6 +95,7 @@ import net.mullvad.mullvadvpn.lib.model.RedeemVoucherSuccess import net.mullvad.mullvadvpn.lib.model.RelayConstraints import net.mullvad.mullvadvpn.lib.model.RelayItem import net.mullvad.mullvadvpn.lib.model.RelayItemId as ModelRelayItemId +import net.mullvad.mullvadvpn.lib.model.RelayItemId import net.mullvad.mullvadvpn.lib.model.RelayList as ModelRelayList import net.mullvad.mullvadvpn.lib.model.RelayList import net.mullvad.mullvadvpn.lib.model.RelaySettings @@ -122,6 +123,8 @@ import net.mullvad.mullvadvpn.lib.model.WebsiteAuthToken import net.mullvad.mullvadvpn.lib.model.WireguardEndpointData as ModelWireguardEndpointData import net.mullvad.mullvadvpn.lib.model.addresses import net.mullvad.mullvadvpn.lib.model.customOptions +import net.mullvad.mullvadvpn.lib.model.entryLocation +import net.mullvad.mullvadvpn.lib.model.isMultihopEnabled import net.mullvad.mullvadvpn.lib.model.location import net.mullvad.mullvadvpn.lib.model.ownership import net.mullvad.mullvadvpn.lib.model.port @@ -131,7 +134,6 @@ import net.mullvad.mullvadvpn.lib.model.selectedObfuscationMode import net.mullvad.mullvadvpn.lib.model.shadowsocks import net.mullvad.mullvadvpn.lib.model.state import net.mullvad.mullvadvpn.lib.model.udp2tcp -import net.mullvad.mullvadvpn.lib.model.useMultihop import net.mullvad.mullvadvpn.lib.model.wireguardConstraints @Suppress("TooManyFunctions") @@ -757,7 +759,7 @@ class ManagementService( Either.catch { val relaySettings = getSettings().relaySettings val updated = - RelaySettings.relayConstraints.wireguardConstraints.useMultihop.set( + RelaySettings.relayConstraints.wireguardConstraints.isMultihopEnabled.set( relaySettings, enabled, ) @@ -767,6 +769,22 @@ class ManagementService( .mapLeft(SetWireguardConstraintsError::Unknown) .mapEmpty() + suspend fun setEntryLocation( + entryLocation: RelayItemId + ): Either = + Either.catch { + val relaySettings = getSettings().relaySettings + val updated = + RelaySettings.relayConstraints.wireguardConstraints.entryLocation.set( + relaySettings, + Constraint.Only(entryLocation), + ) + grpc.setRelaySettings(updated.fromDomain()) + } + .onLeft { Logger.e("Set multihop error") } + .mapLeft(SetWireguardConstraintsError::Unknown) + .mapEmpty() + private fun Either.mapEmpty() = map {} private inline fun Either.mapLeftStatus( diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt index 622e95d9dd0d..b3fe88bdc8f2 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt @@ -126,7 +126,7 @@ internal fun CustomList.fromDomain(): ManagementInterface.CustomList = internal fun WireguardConstraints.fromDomain(): ManagementInterface.WireguardConstraints = ManagementInterface.WireguardConstraints.newBuilder() - .setUseMultihop(useMultihop) + .setUseMultihop(isMultihopEnabled) .setEntryLocation(entryLocation.fromDomain()) .apply { when (val port = this@fromDomain.port) { diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt index 9c54bc5bc5c4..c2946a89988b 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt @@ -336,7 +336,7 @@ internal fun ManagementInterface.WireguardConstraints.toDomain(): WireguardConst } else { Constraint.Any }, - useMultihop = useMultihop, + isMultihopEnabled = useMultihop, entryLocation = entryLocation.toDomain(), ) @@ -644,8 +644,8 @@ internal fun ManagementInterface.FeatureIndicator.toDomain() = ManagementInterface.FeatureIndicator.CUSTOM_MTU -> FeatureIndicator.CUSTOM_MTU ManagementInterface.FeatureIndicator.DAITA -> FeatureIndicator.DAITA ManagementInterface.FeatureIndicator.SHADOWSOCKS -> FeatureIndicator.SHADOWSOCKS + ManagementInterface.FeatureIndicator.MULTIHOP -> FeatureIndicator.MULTIHOP ManagementInterface.FeatureIndicator.LOCKDOWN_MODE, - ManagementInterface.FeatureIndicator.MULTIHOP, ManagementInterface.FeatureIndicator.BRIDGE_MODE, ManagementInterface.FeatureIndicator.CUSTOM_MSS_FIX, ManagementInterface.FeatureIndicator.UNRECOGNIZED -> diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt index 3c8df824f48a..0da5704b4baa 100644 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt @@ -4,7 +4,7 @@ package net.mullvad.mullvadvpn.lib.model enum class FeatureIndicator { DAITA, QUANTUM_RESISTANCE, - // MULTIHOP, + MULTIHOP, SPLIT_TUNNELING, UDP_2_TCP, SHADOWSOCKS, diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItemSelection.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItemSelection.kt new file mode 100644 index 000000000000..c4c78ffe4cbe --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RelayItemSelection.kt @@ -0,0 +1,12 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface RelayItemSelection { + val exitLocation: Constraint + + data class Single(override val exitLocation: Constraint) : RelayItemSelection + + data class Multiple( + val entryLocation: Constraint, + override val exitLocation: Constraint, + ) : RelayItemSelection +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardConstraints.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardConstraints.kt index 7af0144cf44f..dcc3a957dfd2 100644 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardConstraints.kt +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/WireguardConstraints.kt @@ -5,7 +5,7 @@ import arrow.optics.optics @optics data class WireguardConstraints( val port: Constraint, - val useMultihop: Boolean, + val isMultihopEnabled: Boolean, val entryLocation: Constraint, ) { companion object diff --git a/android/lib/resource/src/main/res/drawable-hdpi/multihop_illustration.png b/android/lib/resource/src/main/res/drawable-hdpi/multihop_illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..4b39420e31f08c079e14a1606e226b79b6371984 GIT binary patch literal 45568 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 literal 0 HcmV?d00001 diff --git a/android/lib/resource/src/main/res/drawable-mdpi/multihop_illustration.png b/android/lib/resource/src/main/res/drawable-mdpi/multihop_illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..50d3064f25394748cff47d8e79a0e876b95aa7b4 GIT binary patch literal 24763 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 a@c#pWXE14#kQI>t0000; literal 0 HcmV?d00001 diff --git a/android/lib/resource/src/main/res/drawable-xhdpi/multihop_illustration.png b/android/lib/resource/src/main/res/drawable-xhdpi/multihop_illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..c7cdd85f7e2ff0838fb629a609f887e35b3c41c9 GIT binary patch literal 71127 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
#(^7wC0w)lsi}JnzMDc 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 literal 0 HcmV?d00001 diff --git a/android/lib/resource/src/main/res/drawable-xxxhdpi/multihop_illustration.png b/android/lib/resource/src/main/res/drawable-xxxhdpi/multihop_illustration.png new file mode 100644 index 0000000000000000000000000000000000000000..9246fad11ced6f89a075ca1e8a8e104d0eb267c2 GIT binary patch literal 220713 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

cgO2N8bY-=+ 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

X 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%0AvNCdxB_U*bg6lbw2!z|N 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%0DniY3}C+LVxd{MuI8#KgN9$kgLWeKmJ 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