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

Update both RelayListeners and add use cases #5383

Conversation

Pururun
Copy link
Contributor

@Pururun Pururun commented Oct 30, 2023

  • Update app RelayListener to use events and state flows instead of the old system.
  • Update service RelayListener to use parsed messages instead.
  • Add use cases for relay list and port ranges.
  • Add filter to relay list based on ownership and selected providers.
  • Add the ability to set ownership and providers and send it to the daemon.
  • Get the selected ownership and providers from the daemon.
  • Get a list of all providers from the relay list and if they are Mullvad owned or not.

This change is Reviewable

@Pururun Pururun requested review from Rawa and albin-mullvad October 30, 2023 10:08
@linear
Copy link

linear bot commented Oct 30, 2023

@Pururun Pururun self-assigned this Oct 30, 2023
@Pururun Pururun added the Android Issues related to Android label Oct 30, 2023
Copy link
Contributor

@Rawa Rawa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 17 files reviewed, 1 unresolved discussion (waiting on @Pururun)


android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt line 197 at r1 (raw file):

        }
        valid
    }

I feel that this filter is not very intuitive, we sort of mash it into one big filter. Alternative would be:

private fun List<net.mullvad.mullvadvpn.model.Relay>.filterValidRelays2(
    ownership: Constraint<Ownership>,
    providers: Constraint<Providers>
): List<net.mullvad.mullvadvpn.model.Relay> =
    filter { it.isWireguardRelay }
        .filter {
            when(ownership) {
                is Constraint.Any -> true
                is Constraint.Only -> when(ownership.value) {
                    Ownership.MullvadOwned -> it.owned
                    Ownership.Rented -> !it.owned
                }
            }
        }
        .filter { relay ->
            when(providers) {
                is Constraint.Any -> true
                is Constraint.Only -> providers.value.providers.contains(relay.provider)
            }
        }

A bit more exotic solution would be the following, but I'm not sure I think it is more readable and it is almost a bit of a overkill since we only have two Constraints right now:

private fun List<net.mullvad.mullvadvpn.model.Relay>.filterValidRelays3(
    ownership: Constraint<Ownership>,
    providers: Constraint<Providers>
): List<net.mullvad.mullvadvpn.model.Relay> =
    filter { it.isWireguardRelay }
        .filterConstraint(ownership) { relay, requirement ->
            when (requirement) {
                Ownership.MullvadOwned -> relay.owned
                Ownership.Rented -> !relay.owned
            }
        }
        .filterConstraint(providers) { relay, requirement ->
            requirement.providers.contains(relay.provider)
        }

private inline fun <E, T> List<E>.filterConstraint(
    constraint: Constraint<T>,
    predicate: (E, onlyValue: T) -> Boolean
): List<E> {
    return when (constraint) {
        is Constraint.Any -> this
        is Constraint.Only -> filter { predicate(it, constraint.value) }
    }
}

@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch 2 times, most recently from 45a0f13 to 748393e Compare October 30, 2023 13:44
Copy link
Contributor Author

@Pururun Pururun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 17 files reviewed, 1 unresolved discussion (waiting on @Rawa)


android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt line 197 at r1 (raw file):

Previously, Rawa (David Göransson) wrote…

I feel that this filter is not very intuitive, we sort of mash it into one big filter. Alternative would be:

private fun List<net.mullvad.mullvadvpn.model.Relay>.filterValidRelays2(
    ownership: Constraint<Ownership>,
    providers: Constraint<Providers>
): List<net.mullvad.mullvadvpn.model.Relay> =
    filter { it.isWireguardRelay }
        .filter {
            when(ownership) {
                is Constraint.Any -> true
                is Constraint.Only -> when(ownership.value) {
                    Ownership.MullvadOwned -> it.owned
                    Ownership.Rented -> !it.owned
                }
            }
        }
        .filter { relay ->
            when(providers) {
                is Constraint.Any -> true
                is Constraint.Only -> providers.value.providers.contains(relay.provider)
            }
        }

A bit more exotic solution would be the following, but I'm not sure I think it is more readable and it is almost a bit of a overkill since we only have two Constraints right now:

private fun List<net.mullvad.mullvadvpn.model.Relay>.filterValidRelays3(
    ownership: Constraint<Ownership>,
    providers: Constraint<Providers>
): List<net.mullvad.mullvadvpn.model.Relay> =
    filter { it.isWireguardRelay }
        .filterConstraint(ownership) { relay, requirement ->
            when (requirement) {
                Ownership.MullvadOwned -> relay.owned
                Ownership.Rented -> !relay.owned
            }
        }
        .filterConstraint(providers) { relay, requirement ->
            requirement.providers.contains(relay.provider)
        }

private inline fun <E, T> List<E>.filterConstraint(
    constraint: Constraint<T>,
    predicate: (E, onlyValue: T) -> Boolean
): List<E> {
    return when (constraint) {
        is Constraint.Any -> this
        is Constraint.Only -> filter { predicate(it, constraint.value) }
    }
}

I will switch to suggestion filterValidRelays2

@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch from 748393e to 07ccc27 Compare October 30, 2023 13:49
Copy link
Contributor Author

@Pururun Pururun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 17 files reviewed, 1 unresolved discussion (waiting on @Rawa)


android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/RelayListExtensions.kt line 197 at r1 (raw file):

Previously, Pururun (Jonatan Rhodin) wrote…

I will switch to suggestion filterValidRelays2

Done

Copy link
Contributor

@Rawa Rawa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 17 of 17 files at r1, 2 of 2 files at r2, 4 of 4 files at r3, all commit messages.
Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @Pururun)


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListFilterUseCase.kt line 35 at r1 (raw file):

        }

    fun availableProviders(): Flow<List<Pair<String, Boolean>>> =

We should make a domain type to represent this, I helped the interns a bit with it and made a UiProvider but I think it would make sense to add something to our domain called "Provider" that we can use to represent a provider.


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListUseCase.kt line 47 at r1 (raw file):

                    relayCountries = relayCountries
                )
            Pair(relayCountries, selectedItem)

Imo it would be more clear with a data class than a Pair.

I'm also a bit torn whether maybe ViewModel should combine these or if we need it at this level. (E.g exposing RelayList and it's selection seperately but I think that part probably is fine for now.


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListUseCase.kt line 52 at r1 (raw file):

    private fun findSelectedRelayItem(
        relaySettings: RelaySettings?,
        relayCountries: List<RelayCountry>?

Does it make sense that everything can be null? Feels like we allow for nullability a bit too much in this case. Maybe we should have an extension function on List<RelayCountry> instead?

E.g relayCountries?.findItemFittingSettings(relaySettings) or something along that line.


android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt line 31 at r1 (raw file):

    val uiState =
        combine(relayListUseCase.relayListWithSelection(), _searchTerm) {

way nicer 👍

Copy link
Contributor

@Rawa Rawa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job! nice improvement, breaking it out to UseCases makes it may more simple to understand imo.

Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @Pururun)

Copy link
Contributor Author

@Pururun Pururun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: all files reviewed, 4 unresolved discussions (waiting on @Rawa)


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListFilterUseCase.kt line 35 at r1 (raw file):

Previously, Rawa (David Göransson) wrote…

We should make a domain type to represent this, I helped the interns a bit with it and made a UiProvider but I think it would make sense to add something to our domain called "Provider" that we can use to represent a provider.

Yeah sounds good


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListUseCase.kt line 47 at r1 (raw file):

Previously, Rawa (David Göransson) wrote…

Imo it would be more clear with a data class than a Pair.

I'm also a bit torn whether maybe ViewModel should combine these or if we need it at this level. (E.g exposing RelayList and it's selection seperately but I think that part probably is fine for now.

It is a pair because that is how it worked before. I think we can improve it a lot if we put some thought into it. :) So let's do that.

@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch 2 times, most recently from eb22ca4 to 5151571 Compare October 30, 2023 16:28
Copy link
Contributor Author

@Pururun Pururun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 13 of 20 files reviewed, 4 unresolved discussions (waiting on @Rawa)


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListFilterUseCase.kt line 35 at r1 (raw file):

Previously, Pururun (Jonatan Rhodin) wrote…

Yeah sounds good

Done


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListUseCase.kt line 52 at r1 (raw file):

Previously, Rawa (David Göransson) wrote…

Does it make sense that everything can be null? Feels like we allow for nullability a bit too much in this case. Maybe we should have an extension function on List<RelayCountry> instead?

E.g relayCountries?.findItemFittingSettings(relaySettings) or something along that line.

So I changed so that we get some kind of default value from the relay list listener instead of null. In general we should not get a relay list that is null from the daemon unless something is horribly wrong. I did keep null it for the location constraint since we are able to get null settings from the repository and I thought it might be a bit out of scope here to change that part as well. Made it into an extension function.

Copy link
Contributor

@Rawa Rawa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice clean up on the tests! 🙏

Reviewed 7 of 7 files at r4, all commit messages.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @Pururun)


android/app/src/main/kotlin/net/mullvad/mullvadvpn/relaylist/Provider.kt line 3 at r4 (raw file):

package net.mullvad.mullvadvpn.relaylist

data class Provider(val name: String, val mullvadOwned: Boolean)

Nice 🥇


android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/RelayListUseCase.kt line 52 at r1 (raw file):

Previously, Pururun (Jonatan Rhodin) wrote…

So I changed so that we get some kind of default value from the relay list listener instead of null. In general we should not get a relay list that is null from the daemon unless something is horribly wrong. I did keep null it for the location constraint since we are able to get null settings from the repository and I thought it might be a bit out of scope here to change that part as well. Made it into an extension function.

Yeah, makes sense from this perspective that findSelectRelayItem only is relevant if List<RelayCountry>isn't null. If relayCountries as null makes more sense i think it is fine. Now we can always call relayCountries?.findSelectedRelayItem() which would be more clear.

@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch 2 times, most recently from 040115c to 4f8c9cc Compare November 2, 2023 08:27
@Pururun Pururun marked this pull request as ready for review November 2, 2023 08:29
Copy link
Contributor

@Rawa Rawa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

Reviewed 7 of 7 files at r5, all commit messages.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @Pururun)

@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch from 4f8c9cc to b19fd23 Compare November 2, 2023 08:37
Copy link
Contributor

@Rawa Rawa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 5 of 5 files at r6, all commit messages.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @Pururun)

@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch 4 times, most recently from af97b74 to 2531f89 Compare November 6, 2023 11:47
Copy link
Contributor

@Rawa Rawa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 6 of 6 files at r7, all commit messages.
Reviewable status: all files reviewed, 2 unresolved discussions (waiting on @Pururun)

@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch from 2531f89 to f8bf8b5 Compare November 7, 2023 14:42
@Pururun Pururun force-pushed the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch from f8bf8b5 to 7b3812a Compare November 8, 2023 07:56
@Pururun Pururun merged commit 497ea3e into main Nov 8, 2023
9 of 10 checks passed
@Pururun Pururun deleted the filter-select-location-relay-list-on-ownership-and-selected-droid-466 branch November 8, 2023 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Android Issues related to Android
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants