Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show all locations for custom lists in edit locations and detail view #6135

Merged
merged 3 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package net.mullvad.mullvadvpn.compose.data

import net.mullvad.mullvadvpn.model.Constraint
import net.mullvad.mullvadvpn.model.CustomListName
import net.mullvad.mullvadvpn.model.PortRange
import net.mullvad.mullvadvpn.model.RelayEndpointData
Expand Down Expand Up @@ -43,7 +42,7 @@ val DUMMY_RELAY_COUNTRIES =
arrayListOf(DUMMY_RELAY_COUNTRY_1, DUMMY_RELAY_COUNTRY_2),
DUMMY_WIREGUARD_ENDPOINT_DATA,
)
.toRelayCountries(ownership = Constraint.Any(), providers = Constraint.Any())
.toRelayCountries()

val DUMMY_CUSTOM_LISTS =
listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ 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.model.GeographicLocationConstraint
import net.mullvad.mullvadvpn.model.Ownership
import net.mullvad.mullvadvpn.relaylist.RelayItem
import net.mullvad.mullvadvpn.viewmodel.EditCustomListViewModel
import org.koin.androidx.compose.koinViewModel
Expand All @@ -69,7 +70,9 @@ private fun PreviewEditCustomListScreen() {
"hostname",
"hostname",
"hostname"
)
),
"Provider",
Ownership.MullvadOwned
)
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package net.mullvad.mullvadvpn.compose.util

import net.mullvad.mullvadvpn.model.GeographicLocationConstraint
import net.mullvad.mullvadvpn.model.Ownership
import net.mullvad.mullvadvpn.relaylist.RelayItem

fun generateRelayItemCountry(
Expand Down Expand Up @@ -65,7 +66,9 @@ fun generateRelayItemRelay(
hostname = hostName,
),
locationName = "$cityCode $hostName",
active = active
active = active,
providerName = "Provider",
ownership = Ownership.MullvadOwned,
)

private fun String.generateCountryCode() = (take(1) + takeLast(1)).lowercase()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package net.mullvad.mullvadvpn.relaylist
import net.mullvad.mullvadvpn.model.CustomListName
import net.mullvad.mullvadvpn.model.GeoIpLocation
import net.mullvad.mullvadvpn.model.GeographicLocationConstraint
import net.mullvad.mullvadvpn.model.Ownership

sealed interface RelayItem {
val name: String
Expand Down Expand Up @@ -66,6 +67,8 @@ sealed interface RelayItem {
override val locationName: String,
override val active: Boolean,
val location: GeographicLocationConstraint.Hostname,
val providerName: String,
val ownership: Ownership,
) : RelayItem {
override val code = name
override val hasChildren = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package net.mullvad.mullvadvpn.relaylist

data class RelayList(
val customLists: List<RelayItem.CustomList>,
val country: List<RelayItem.Country>,
val allCountries: List<RelayItem.Country>,
val filteredCountries: List<RelayItem.Country>,
val selectedItem: RelayItem?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ import net.mullvad.mullvadvpn.model.RelayList
* filtered out and also relays that do not fit the ownership and provider list So are also cities
* that only contains non-wireguard relays Countries, cities and relays are ordered by name
*/
fun RelayList.toRelayCountries(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>
): List<RelayItem.Country> {
fun RelayList.toRelayCountries(): List<RelayItem.Country> {
val relayCountries =
this.countries
.map { country ->
Expand All @@ -33,8 +30,7 @@ fun RelayList.toRelayCountries(
relays = relays
)

val validCityRelays =
city.relays.filterValidRelays(ownership = ownership, providers = providers)
val validCityRelays = city.relays.filterValidRelays()

for (relay in validCityRelays) {
relays.add(
Expand All @@ -47,7 +43,10 @@ fun RelayList.toRelayCountries(
relay.hostname
),
locationName = "${city.name} (${relay.hostname})",
active = relay.active
active = relay.active,
providerName = relay.provider,
ownership =
if (relay.owned) Ownership.MullvadOwned else Ownership.Rented
)
)
}
Expand Down Expand Up @@ -172,25 +171,40 @@ fun List<RelayItem.Country>.filterOnSearchTerm(
}
}

private fun List<DaemonRelay>.filterValidRelays(
private fun List<DaemonRelay>.filterValidRelays(): List<DaemonRelay> = filter {
it.isWireguardRelay
}

fun List<RelayItem.Country>.filterOnOwnershipAndProviders(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>
): List<DaemonRelay> =
filter { it.isWireguardRelay }
.filter {
): List<RelayItem.Country> {
return map { country ->
val cities =
country.cities.map { city ->
val relays =
city.relays.filterRelayByOwnershipAndProviders(ownership, providers)
city.copy(relays = relays)
}
country.copy(cities = cities.filter { it.relays.isNotEmpty() })
}
.filter { it.cities.isNotEmpty() }
}

private fun List<RelayItem.Relay>.filterRelayByOwnershipAndProviders(
ownership: Constraint<Ownership>,
providers: Constraint<Providers>
): List<RelayItem.Relay> =
filter {
when (ownership) {
is Constraint.Any -> true
is Constraint.Only ->
when (ownership.value) {
Ownership.MullvadOwned -> it.owned
Ownership.Rented -> !it.owned
}
is Constraint.Only -> it.ownership == ownership.value
}
}
.filter { relay ->
when (providers) {
is Constraint.Any -> true
is Constraint.Only -> providers.value.providers.contains(relay.provider)
is Constraint.Only -> providers.value.providers.contains(relay.providerName)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import net.mullvad.mullvadvpn.model.RelaySettings
import net.mullvad.mullvadvpn.model.WireguardConstraints
import net.mullvad.mullvadvpn.relaylist.RelayItem
import net.mullvad.mullvadvpn.relaylist.RelayList
import net.mullvad.mullvadvpn.relaylist.filterOnOwnershipAndProviders
import net.mullvad.mullvadvpn.relaylist.findItemForGeographicLocationConstraint
import net.mullvad.mullvadvpn.relaylist.toRelayCountries
import net.mullvad.mullvadvpn.relaylist.toRelayItemLists
Expand Down Expand Up @@ -36,22 +37,29 @@ class RelayListUseCase(
settings?.relaySettings?.relayConstraints()?.ownership ?: Constraint.Any()
val providers =
settings?.relaySettings?.relayConstraints()?.providers ?: Constraint.Any()
val relayCountries =
relayList.toRelayCountries(ownership = ownership, providers = providers)
val relayCountries = relayList.toRelayCountries()
val customLists =
settings?.customLists?.customLists?.toRelayItemLists(relayCountries) ?: emptyList()
val relayCountriesFiltered =
relayCountries.filterOnOwnershipAndProviders(ownership, providers)
val selectedItem =
findSelectedRelayItem(
relaySettings = settings?.relaySettings,
relayCountries = relayCountries,
relayCountries = relayCountriesFiltered,
customLists = customLists,
)
RelayList(customLists, relayCountries, selectedItem)
RelayList(
customLists = customLists,
allCountries = relayCountries,
filteredCountries = relayCountriesFiltered,
selectedItem = selectedItem
)
}

fun selectedRelayItem(): Flow<RelayItem?> = relayListWithSelection().map { it.selectedItem }

fun relayList(): Flow<List<RelayItem.Country>> = relayListWithSelection().map { it.country }
fun fullRelayList(): Flow<List<RelayItem.Country>> =
relayListWithSelection().map { it.allCountries }

fun customLists(): Flow<List<RelayItem.CustomList>> =
relayListWithSelection().map { it.customLists }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ class CustomListActionUseCase(
)
val locationNames =
relayListUseCase
.relayList()
.fullRelayList()
.firstOrNull()
?.getRelayItemsByCodes(action.locations)
?.map { it.name }
Result.success(
CustomListResult.Created(
id = result.id,
name = action.name,
locationName = locationNames?.first(),
locationName = locationNames?.firstOrNull(),
undo = action.not(result.id)
)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class CustomListLocationsViewModel(
private val _searchTerm = MutableStateFlow(EMPTY_SEARCH_TERM)

val uiState =
combine(relayListUseCase.relayList(), _searchTerm, _selectedLocations) {
combine(relayListUseCase.fullRelayList(), _searchTerm, _selectedLocations) {
relayCountries,
searchTerm,
selectedLocations ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class SelectLocationViewModel(
) : ViewModel() {
private val _searchTerm = MutableStateFlow(EMPTY_SEARCH_TERM)

@Suppress("DestructuringDeclarationWithTooManyEntries")
val uiState =
combine(
relayListUseCase.relayListWithSelection(),
Expand All @@ -43,7 +44,7 @@ class SelectLocationViewModel(
relayListFilterUseCase.availableProviders(),
relayListFilterUseCase.selectedProviders(),
) {
(customLists, relayCountries, selectedItem),
(customLists, _, relayCountries, selectedItem),
searchTerm,
selectedOwnership,
allProviders,
Expand All @@ -63,7 +64,15 @@ class SelectLocationViewModel(
val filteredRelayCountries =
relayCountries.filterOnSearchTerm(searchTerm, selectedItem)

val filteredCustomLists = customLists.filterOnSearchTerm(searchTerm)
val filteredCustomLists =
customLists.filterOnSearchTerm(searchTerm).map { customList ->
customList.copy(
locations =
customList.locations.filter { location ->
filteredRelayCountries.any { it.code == location.code }
}
)
}

SelectLocationUiState.Content(
searchTerm = searchTerm,
Expand Down
Loading
Loading