Skip to content

Implement IAN activation flow#9705

Open
rablador wants to merge 1 commit intomainfrom
implement-includeallnetworks-activation-flow-ios-1422
Open

Implement IAN activation flow#9705
rablador wants to merge 1 commit intomainfrom
implement-includeallnetworks-activation-flow-ios-1422

Conversation

@rablador
Copy link
Contributor

@rablador rablador commented Jan 26, 2026

Acceptance criteria

  • Written in SwiftUI
  • Feature can only be enabled once the user has given their consent
  • If the feature is enabled a notification is sent to remind the user that an app update is available and that they should disable IAN before proceeding
    • This notification should bring them to the relevant view where they can turn off IAN.

How should this be tested?

  • Unit test the view model where it makes sense
  • E2E test will most likely not work to to IAN

This change is Reviewable

@rablador rablador self-assigned this Jan 26, 2026
@rablador rablador added the iOS Issues related to iOS label Jan 26, 2026
@linear
Copy link

linear bot commented Jan 26, 2026

@github-actions
Copy link

🚨 End to end tests failed. Please check the failed workflow run.

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch 5 times, most recently from 2c22e51 to 5a509d5 Compare January 28, 2026 13:55
@rablador rablador requested review from acb-mv and mojganii January 28, 2026 13:56
@rablador rablador marked this pull request as ready for review January 28, 2026 13:56
Copy link
Collaborator

@pinkisemils pinkisemils left a comment

Choose a reason for hiding this comment

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

On first run, the packet tunnel failed to start.

@pinkisemils made 1 comment.
Reviewable status: 0 of 64 files reviewed, all discussions resolved.

Copy link
Collaborator

@pinkisemils pinkisemils left a comment

Choose a reason for hiding this comment

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

And sometimes the tunnel monitor gets stuck in a state - I wonder if this is due to it not properly stopping to listen for the old tunnel profile or seeing updates from the old packet tunnel after the new one had already started. Could we detect that better? Probably best resolved in a new PR.

@pinkisemils made 1 comment.
Reviewable status: 0 of 64 files reviewed, all discussions resolved.

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch from 5a509d5 to 8e5e27c Compare January 30, 2026 08:21
Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

I re-ran a fresh install, but no failing packet tunnel so far. Can't see how this would be related to the current PR though, unless the new .noReconnect strategy for some reason is invoked when it shouldn't.

@rablador made 1 comment.
Reviewable status: 0 of 64 files reviewed, all discussions resolved.

Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

Info button at Local network sharing doesn't work

@mojganii made 1 comment.
Reviewable status: 0 of 64 files reviewed, all discussions resolved.

Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

I wonder if we still keep the switches disabled when it's already enabled, shouldn't the checkmark be marked by default when it's enabled?
Screenshot 2026-02-04 at 14.56.36.png

@mojganii made 1 comment.
Reviewable status: 0 of 64 files reviewed, all discussions resolved.

Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

@mojganii made 1 comment.
Reviewable status: 0 of 64 files reviewed, 1 unresolved discussion (waiting on @rablador).


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 239 at r2 (raw file):

        completion: @escaping () -> Void
    ) -> MullvadAlert {
        let message = [

I get the alert even when the VPN is not connected.

Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

@mojganii made 1 comment.
Reviewable status: 0 of 64 files reviewed, 2 unresolved discussions (waiting on @rablador).


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 145 at r2 (raw file):

                MullvadAlert.Action(
                    type: .default,
                    title: "Got it!",

is it part of the spect to allow users to enable the IAN while user doesn't enable the notification?

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch from 8e5e27c to 0947997 Compare February 4, 2026 21:19
Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

The info button was only clickable when the feature is enabled. Fixed now.

Regarding the states, good question. My thought was that consent is the overarching failsafe, so if consent is turned off the feature is turned off too. But perhaps we should automatically set switches to off then too? @pinkisemils @waahlnaden ?

@rablador made 3 comments.
Reviewable status: 0 of 66 files reviewed, 2 unresolved discussions (waiting on @mojganii).


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 145 at r2 (raw file):

Previously, mojganii wrote…

is it part of the spect to allow users to enable the IAN while user doesn't enable the notification?

Yes, they can decline the notification and still enable IAN.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 239 at r2 (raw file):

Previously, mojganii wrote…

I get the alert even when the VPN is not connected.

Ah, forgot to add the conditon. Fixed now. I the for tunne state being "secured", just like in the language alert PR. If we decided to change the condition for showing the alert there, I'll update the condition likewise here too.

Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

@rablador made 1 comment.
Reviewable status: 0 of 66 files reviewed, 3 unresolved discussions (waiting on @mojganii).


ios/MullvadVPN/Coordinators/Settings/Views/SettingsInfoView.swift line 1 at r3 (raw file):

//

The changes in this file relate to https://linear.app/mullvad/issue/IOS-1139/fix-the-gap-between-images-in-daita-settings.

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch 3 times, most recently from d7fb79d to b3f0ba5 Compare February 6, 2026 16:14
Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

I’m wondering: if the user taps the consent checkbox again, should it become unchecked? If so, do we then disable the features that were enabled? If not, then tapping it again shouldn’t change the enabling state of the toggles.
ScreenRecording_02-06-2026 17-24-25_1.MP4

@mojganii made 1 comment and resolved 1 discussion.
Reviewable status: 0 of 72 files reviewed, 2 unresolved discussions.

Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

We decided today that the checkbox is a one-time only interaction. It will not be tappable again.

@rablador made 1 comment.
Reviewable status: 0 of 72 files reviewed, 2 unresolved discussions (waiting on @mojganii).

Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

@mojganii made 5 comments.
Reviewable status: 0 of 72 files reviewed, 7 unresolved discussions (waiting on @rablador).


ios/MullvadSettings/InclueAllNetworksSettings.swift line 33 at r6 (raw file):

}

public struct InclueAllNetworksSettings: Codable, Equatable, Sendable {

typo: Inclue


ios/MullvadSettings/InclueAllNetworksSettings.swift line 36 at r6 (raw file):

    public var includeAllNetworksState: InclueAllNetworksState
    public var localNetworkSharingState: LocalNetworkSharingState
    public var consent: Bool

do we really need to save is as part of TunnelSettings? I think this flag can reside in AppPreference


ios/MullvadSettings/SettingsManager.swift line 154 at r6 (raw file):

                .ipOverrides,
                .customRelayLists,
                .recentConnections,

as I remember, we were not supposed to remove recents with logging out. is there any particular reason hrere?


ios/MullvadSettings/TunnelSettingsStrategy.swift line 38 at r6 (raw file):

    ) -> TunnelSettingsReconnectionStrategy {
        // Don't reconnect the tunnel If IAN consent was the setting that triggered the settings update.
        if oldSettings.includeAllNetworks.consent != newSettings.includeAllNetworks.consent {

I think the consent and the logic around it should live on the UI side. We only need to care about the values of the flags, and ensure users couldn't enable them without giving consent in advance.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 160 at r6 (raw file):

                        ExternalLinkView(
                            url: blogUrl,
                            label: "For details, please see our blog post",

I see it as the footer on the design. which one is the reference?

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch from b3f0ba5 to b19eaa5 Compare February 9, 2026 08:25
@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch from b19eaa5 to cdf0267 Compare February 9, 2026 11:54
Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

@rablador made 5 comments.
Reviewable status: 0 of 73 files reviewed, 7 unresolved discussions (waiting on @mojganii).


ios/MullvadSettings/TunnelSettingsStrategy.swift line 38 at r6 (raw file):

Previously, mojganii wrote…

I think the consent and the logic around it should live on the UI side. We only need to care about the values of the flags, and ensure users couldn't enable them without giving consent in advance.

Consent is now part of app preferences instead, so this check has been removed.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 160 at r6 (raw file):

Previously, mojganii wrote…

I see it as the footer on the design. which one is the reference?

This is a link on page 2 in the IAN view.


ios/MullvadSettings/SettingsManager.swift line 154 at r6 (raw file):

Previously, mojganii wrote…

as I remember, we were not supposed to remove recents with logging out. is there any particular reason hrere?

No, my bad. Removed.


ios/MullvadSettings/InclueAllNetworksSettings.swift line 33 at r6 (raw file):

Previously, mojganii wrote…

typo: Inclue

Oof, a bad one at that! Fixed.


ios/MullvadSettings/InclueAllNetworksSettings.swift line 36 at r6 (raw file):

Previously, mojganii wrote…

do we really need to save is as part of TunnelSettings? I think this flag can reside in AppPreference

I agree. It was bound to the other settings before, but now we only check for it once in the IAN view.

Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

this issue might be irrelevant to this feature but after pressing Done button the logger says ' Dismissing .daita.'
ScreenRecording_02-09-2026 16-06-14_1.MP4

@mojganii reviewed 3 files, made 9 comments, and resolved 5 discussions.
Reviewable status: 3 of 73 files reviewed, 10 unresolved discussions (waiting on @rablador).


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 100 at r7 (raw file):

    }

    func showEnableNofiticationsAlert() {

typo: Notifications


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 104 at r7 (raw file):

        // two alerts with no delay between them, add a short delay
        // here.
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {

what is the case might end up to showing two alerts?


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 111 at r7 (raw file):

    }

    func showReconsiderNofiticationsAlert() {

typo: Notifications


ios/MullvadSettings/TunnelSettingsStrategy.swift line 37 at r7 (raw file):

        newSettings: LatestTunnelSettings
    ) -> TunnelSettingsReconnectionStrategy {
        if oldSettings.includeAllNetworks.localNetworkSharingState

can't we simply it here?

Code snippet:

        switch (oldSettings, newSettings) {
        case let (old, new) where old.includeAllNetworks != new.includeAllNetworks:
            return .hardReconnect
        case let (old, new) where old != new:
            return .newRelayReconnect
        default:
            return .currentRelayReconnect
        }

ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 21 at r7 (raw file):

    var consent: Bool { get set }

    var showEnableNotificationsAlert: Bool { get set }

the doesn't imply it's a bool value


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 22 at r7 (raw file):

    var showEnableNotificationsAlert: Bool { get set }
    var showReconsiderNotificationsAlert: Bool { get set }

the doesn't imply it's a bool value


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 23 at r7 (raw file):

    var showEnableNotificationsAlert: Bool { get set }
    var showReconsiderNotificationsAlert: Bool { get set }
    var tunnelIsSecured: Bool { get }

isTunnelSecured?


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 209 at r7 (raw file):

        let ipList = [
            " ∙ 10.0.0.0/8",

nit:we could keep private ips with the built in types out side the object.

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch 2 times, most recently from 5413228 to eac976f Compare February 10, 2026 09:01
Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

Good catch, fixed!

@rablador made 9 comments and resolved 2 discussions.
Reviewable status: 1 of 73 files reviewed, 8 unresolved discussions (waiting on @mojganii).


ios/MullvadSettings/TunnelSettingsStrategy.swift line 37 at r7 (raw file):

Previously, mojganii wrote…

can't we simply it here?

You're right. Now that we use a shared container object for them.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 100 at r7 (raw file):

Previously, mojganii wrote…

typo: Notifications

Done.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 104 at r7 (raw file):

Previously, mojganii wrote…

what is the case might end up to showing two alerts?

The leak warning and if notifications are disabled.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsView.swift line 111 at r7 (raw file):

Previously, mojganii wrote…

typo: Notifications

Done.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 21 at r7 (raw file):

Previously, mojganii wrote…

the doesn't imply it's a bool value

Done.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 22 at r7 (raw file):

Previously, mojganii wrote…

the doesn't imply it's a bool value

Done.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 23 at r7 (raw file):

Previously, mojganii wrote…

isTunnelSecured?

I much prefer keeping readability, ie "if tunnelIsSecured" feels more readable than "if isTunnelSecured" to me.


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 209 at r7 (raw file):

Previously, mojganii wrote…

nit:we could keep private ips with the built in types out side the object.

Hmm, I see your point, but doing so would need me to first create address objects from strings, then convert the address data back to strings again. It's not worth it, is it?

Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

PR looks good! It just needs to be rebased and updated to use UNUserNotificationCenter.isAllowed and UNUserNotificationCenter.isDisabled to be in sync with main.

@mojganii partially reviewed 10 files, made 2 comments, and resolved 6 discussions.
Reviewable status: 11 of 73 files reviewed, 2 unresolved discussions (waiting on @rablador).


ios/MullvadVPN/Coordinators/Settings/IncludeAllNetworks/IncludeAllNetworksSettingsViewModel.swift line 209 at r7 (raw file):

Previously, rablador (Jon Petersson) wrote…

Hmm, I see your point, but doing so would need me to first create address objects from strings, then convert the address data back to strings again. It's not worth it, is it?

the whole point is keeping all is one place if we need to have or tweak them later . but it's not critical to make this change. they are private ips and

Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

@rablador resolved 2 discussions.
Reviewable status: 11 of 73 files reviewed, all discussions resolved (waiting on @mojganii).

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch from eac976f to ad855a9 Compare February 12, 2026 10:59
Copy link
Collaborator

@pinkisemils pinkisemils left a comment

Choose a reason for hiding this comment

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

@pinkisemils reviewed 2 files and made 1 comment.
Reviewable status: 9 of 73 files reviewed, all discussions resolved (waiting on @mojganii).


ios/MullvadSettings/AppPreferences.swift line 63 at r9 (raw file):

    @AppStorage(key: AppStorageKey.includeAllNetworksConsent.rawValue, container: .standard)
    public var includeAllNetworksConsent = false

This will clash with Mojgan's changes.

Copy link
Collaborator

@pinkisemils pinkisemils left a comment

Choose a reason for hiding this comment

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

@pinkisemils partially reviewed 14 files and all commit messages.
Reviewable status: 16 of 73 files reviewed, all discussions resolved (waiting on @mojganii).

@waahlnaden
Copy link
Collaborator

waahlnaden commented Feb 13, 2026

Given that we moved the local network sharing toggle into the view, the text that explains that you need to read all the information in order to activate the feature was pushed down so that it wasn't visible on my SE anymore without scrolling. I suggest we use the empty text space we have on the first slide to make a (literally) bold statement, this would also help at larger text sizes:
image

In addition, I had a talk with Matilda regarding the checkbox and we suggest some minor copy changes so as to not confuse users that checking the box might actually turn on the feature:
image

Lastly, I was a bit confused by the disabled state of the checkbox after ticking it. My gut reaction was that it was maybe invalidated or something, but I totally agree with not being able to detick the box afterwards - just wondering if there is a different state we could use instead. Will investigate

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch from ad855a9 to 6e00db1 Compare February 13, 2026 12:59
Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

👍

@rablador made 1 comment.
Reviewable status: 16 of 73 files reviewed, all discussions resolved (waiting on @mojganii).

pinkisemils
pinkisemils previously approved these changes Feb 13, 2026
Copy link
Collaborator

@pinkisemils pinkisemils left a comment

Choose a reason for hiding this comment

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

@pinkisemils reviewed 57 files and all commit messages.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved.

@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch 2 times, most recently from 57e93ff to 58144f5 Compare February 16, 2026 11:18
@rablador rablador force-pushed the implement-includeallnetworks-activation-flow-ios-1422 branch from 58144f5 to e9b8154 Compare February 16, 2026 11:46
Copy link
Contributor

@mojganii mojganii left a comment

Choose a reason for hiding this comment

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

@mojganii reviewed 5 files and all commit messages, and made 1 comment.
Reviewable status: 68 of 73 files reviewed, 1 unresolved discussion (waiting on pinkisemils and rablador).


ios/MullvadVPN/Coordinators/Settings/SettingsViewControllerFactory.swift line 164 at r11 (raw file):

        let viewModel = IncludeAllNetworksSettingsViewModelImpl(
            tunnelManager: interactorFactory.tunnelManager,
            appPreferences: appPreferences

nit: we could get notified the consent value changes like what we are doing in makeNotificationSettingsCoordinator to aggregate all storing in Application coordinator

Copy link
Contributor Author

@rablador rablador left a comment

Choose a reason for hiding this comment

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

@rablador made 1 comment.
Reviewable status: 68 of 73 files reviewed, 1 unresolved discussion (waiting on mojganii and pinkisemils).


ios/MullvadVPN/Coordinators/Settings/SettingsViewControllerFactory.swift line 164 at r11 (raw file):

Previously, mojganii wrote…

nit: we could get notified the consent value changes like what we are doing in makeNotificationSettingsCoordinator to aggregate all storing in Application coordinator

Sunce the keychain changes are made in the view model as well, I'd rather keep all settings manipulation in one place if possible. Also, there's nothing to notify by enabling consent, so it would mean creating a whole callback chain for just storing one value.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

iOS Issues related to iOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants