summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJon Petersson <jon.petersson@mullvad.net>2025-06-17 12:52:18 +0200
committerJon Petersson <jon.petersson@mullvad.net>2025-06-23 11:39:40 +0200
commit4fd6195df4202aa1cc0d7f3eb3bfd90c66620eda (patch)
treed95e6404ab8324b6d75187fd644b4dcb875edb3a
parent741cfd8a3ffe1152738773c8ac256ac78c2e28cb (diff)
downloadmullvadvpn-4fd6195df4202aa1cc0d7f3eb3bfd90c66620eda.tar.xz
mullvadvpn-4fd6195df4202aa1cc0d7f3eb3bfd90c66620eda.zip
Disable add time button when app is in blocked state
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelState.swift9
-rw-r--r--ios/MullvadVPN/View controllers/Account/AccountInteractor.swift16
-rw-r--r--ios/MullvadVPN/View controllers/Account/AccountViewController.swift14
-rw-r--r--ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeContentView.swift4
-rw-r--r--ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift1
5 files changed, 38 insertions, 6 deletions
diff --git a/ios/MullvadVPN/TunnelManager/TunnelState.swift b/ios/MullvadVPN/TunnelManager/TunnelState.swift
index 648dfd78c9..8d5e7f12f1 100644
--- a/ios/MullvadVPN/TunnelManager/TunnelState.swift
+++ b/ios/MullvadVPN/TunnelManager/TunnelState.swift
@@ -146,6 +146,15 @@ enum TunnelState: Equatable, CustomStringConvertible, Sendable {
}
}
+ var isBlockingInternet: Bool {
+ switch self {
+ case .connected, .disconnected:
+ false
+ default:
+ true
+ }
+ }
+
var relays: SelectedRelays? {
switch self {
case let .connected(relays, _, _),
diff --git a/ios/MullvadVPN/View controllers/Account/AccountInteractor.swift b/ios/MullvadVPN/View controllers/Account/AccountInteractor.swift
index 043c734fd8..8a8e7de313 100644
--- a/ios/MullvadVPN/View controllers/Account/AccountInteractor.swift
+++ b/ios/MullvadVPN/View controllers/Account/AccountInteractor.swift
@@ -19,6 +19,7 @@ final class AccountInteractor: Sendable {
let apiProxy: APIQuerying
let deviceProxy: DeviceHandling
+ nonisolated(unsafe) var didReceiveTunnelState: (() -> Void)?
nonisolated(unsafe) var didReceiveDeviceState: (@Sendable (DeviceState) -> Void)?
nonisolated(unsafe) private var tunnelObserver: TunnelObserver?
@@ -35,15 +36,24 @@ final class AccountInteractor: Sendable {
self.deviceProxy = deviceProxy
let tunnelObserver =
- TunnelBlockObserver(didUpdateDeviceState: { [weak self] _, deviceState, _ in
- self?.didReceiveDeviceState?(deviceState)
- })
+ TunnelBlockObserver(
+ didUpdateTunnelStatus: { [weak self] _, _ in
+ self?.didReceiveTunnelState?()
+ },
+ didUpdateDeviceState: { [weak self] _, deviceState, _ in
+ self?.didReceiveDeviceState?(deviceState)
+ }
+ )
tunnelManager.addObserver(tunnelObserver)
self.tunnelObserver = tunnelObserver
}
+ var tunnelState: TunnelState {
+ tunnelManager.tunnelStatus.state
+ }
+
var deviceState: DeviceState {
tunnelManager.deviceState
}
diff --git a/ios/MullvadVPN/View controllers/Account/AccountViewController.swift b/ios/MullvadVPN/View controllers/Account/AccountViewController.swift
index 4c347b573c..7d6c1302fa 100644
--- a/ios/MullvadVPN/View controllers/Account/AccountViewController.swift
+++ b/ios/MullvadVPN/View controllers/Account/AccountViewController.swift
@@ -94,6 +94,13 @@ class AccountViewController: UIViewController, @unchecked Sendable {
self?.actionHandler?(.restorePurchasesInfo)
}
+ interactor.didReceiveTunnelState = { [weak self] in
+ guard let self else { return }
+ Task { @MainActor in
+ applyViewState(animated: true)
+ }
+ }
+
interactor.didReceiveDeviceState = { [weak self] deviceState in
Task { @MainActor in
self?.updateView(from: deviceState)
@@ -160,7 +167,7 @@ class AccountViewController: UIViewController, @unchecked Sendable {
applyViewState(animated: animated)
}
- private func updateView(from deviceState: DeviceState?) {
+ private func updateView(from deviceState: DeviceState) {
guard case let .loggedIn(accountData, deviceData) = deviceState else {
return
}
@@ -172,9 +179,10 @@ class AccountViewController: UIViewController, @unchecked Sendable {
private func applyViewState(animated: Bool) {
let isInteractionEnabled = paymentState.allowsViewInteraction
- let purchaseButton = contentView.purchaseButton
- purchaseButton.isEnabled = !isFetchingProducts && isInteractionEnabled
+ contentView.purchaseButton.isEnabled = !isFetchingProducts
+ && isInteractionEnabled
+ && !interactor.tunnelState.isBlockingInternet
contentView.accountDeviceRow.setButtons(enabled: isInteractionEnabled)
contentView.accountTokenRowView.setButtons(enabled: isInteractionEnabled)
contentView.restorePurchasesView.setButtons(enabled: isInteractionEnabled)
diff --git a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeContentView.swift b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeContentView.swift
index 4e2bb87763..11cb3bcbbf 100644
--- a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeContentView.swift
+++ b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeContentView.swift
@@ -113,6 +113,10 @@ class OutOfTimeContentView: UIView {
}
}
+ func enablePurchaseButton(_ enabled: Bool) {
+ purchaseButton.isEnabled = enabled
+ }
+
// MARK: - Private Functions
func setUpSubviews() {
diff --git a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift
index 19260838ab..4a9906a429 100644
--- a/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift
+++ b/ios/MullvadVPN/View controllers/OutOfTime/OutOfTimeViewController.swift
@@ -106,6 +106,7 @@ class OutOfTimeViewController: UIViewController, RootContainment {
private func applyViewState() {
let tunnelState = interactor.tunnelStatus.state
contentView.enableDisconnectButton(tunnelState.isSecured, animated: true)
+ contentView.enablePurchaseButton(!tunnelState.isSecured)
if tunnelState.isSecured {
contentView.setBodyLabelText(