Skip to content

Commit

Permalink
Add trailing status indicators for daita and multihop cells
Browse files Browse the repository at this point in the history
  • Loading branch information
rablador committed Dec 4, 2024
1 parent b3d61b2 commit 9c27913
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 45 deletions.
18 changes: 16 additions & 2 deletions ios/MullvadVPN/View controllers/Settings/SettingsCellFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,14 @@ final class SettingsCellFactory: CellFactoryProtocol {
value: "DAITA",
comment: ""
)
cell.detailTitleLabel.text = nil

cell.detailTitleLabel.text = NSLocalizedString(
"DAITA_CELL_DETAIL_LABEL",
tableName: "Settings",
value: viewModel.daitaSettings.daitaState.isEnabled ? "On" : "Off",
comment: ""
)

cell.accessibilityIdentifier = item.accessibilityIdentifier
cell.disclosureType = .chevron

Expand All @@ -124,7 +131,14 @@ final class SettingsCellFactory: CellFactoryProtocol {
value: "Multihop",
comment: ""
)
cell.detailTitleLabel.text = nil

cell.detailTitleLabel.text = NSLocalizedString(
"MULTIHOP_CELL_DETAIL_LABEL",
tableName: "Settings",
value: viewModel.multihopState.isEnabled ? "On" : "Off",
comment: ""
)

cell.accessibilityIdentifier = item.accessibilityIdentifier
cell.disclosureType = .chevron
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,14 @@ final class SettingsDataSource: UITableViewDiffableDataSource<SettingsDataSource
storedAccountData = interactor.deviceState.accountData
}

func reload(from tunnelSettings: LatestTunnelSettings) {
settingsCellFactory.viewModel = SettingsViewModel(from: tunnelSettings)

var snapshot = snapshot()
snapshot.reconfigureItems(snapshot.itemIdentifiers)
apply(snapshot, animatingDifferences: false)
}

// MARK: - UITableViewDelegate

func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
Expand Down Expand Up @@ -171,10 +179,4 @@ extension SettingsDataSource: SettingsCellEventHandler {
func showInfo(for button: SettingsInfoButtonItem) {
delegate?.showInfo(for: button)
}

private func reloadItem(_ item: Item) {
var snapshot = snapshot()
snapshot.reloadItems([item])
apply(snapshot, animatingDifferences: false)
}
}
41 changes: 9 additions & 32 deletions ios/MullvadVPN/View controllers/Settings/SettingsInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ final class SettingsInteractor {
private var tunnelObserver: TunnelObserver?

var didUpdateDeviceState: ((DeviceState) -> Void)?
var didUpdateTunnelSettings: ((LatestTunnelSettings) -> Void)?

var tunnelSettings: LatestTunnelSettings {
tunnelManager.settings
Expand All @@ -28,41 +29,17 @@ final class SettingsInteractor {
self.tunnelManager = tunnelManager

let tunnelObserver =
TunnelBlockObserver(didUpdateDeviceState: { [weak self] _, deviceState, _ in
self?.didUpdateDeviceState?(deviceState)
})
TunnelBlockObserver(
didUpdateDeviceState: { [weak self] _, deviceState, _ in
self?.didUpdateDeviceState?(deviceState)
},
didUpdateTunnelSettings: { [weak self] _, settings in
self?.didUpdateTunnelSettings?(settings)
}
)

tunnelManager.addObserver(tunnelObserver)

self.tunnelObserver = tunnelObserver
}

func updateDAITASettings(_ settings: DAITASettings) {
tunnelManager.updateSettings([.daita(settings)])
}

func evaluateDaitaSettingsCompatibility(_ settings: DAITASettings) -> DAITASettingsCompatibilityError? {
guard settings.daitaState.isEnabled else { return nil }

var tunnelSettings = tunnelSettings
tunnelSettings.daita = settings

var compatibilityError: DAITASettingsCompatibilityError?

do {
_ = try tunnelManager.selectRelays(tunnelSettings: tunnelSettings)
} catch let error as NoRelaysSatisfyingConstraintsError where error.reason == .noDaitaRelaysFound {
// Return error if no relays could be selected due to DAITA constraints.
compatibilityError = tunnelSettings.tunnelMultihopState.isEnabled ? .multihop : .singlehop
} catch _ as NoRelaysSatisfyingConstraintsError {
// Even if the constraints error is not DAITA specific, if both DAITA and Direct only are enabled,
// we should return a DAITA related error since the current settings would have resulted in the
// relay selector not being able to select a DAITA relay anyway.
if settings.isDirectOnly {
compatibilityError = tunnelSettings.tunnelMultihopState.isEnabled ? .multihop : .singlehop
}
} catch {}

return compatibilityError
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class SettingsViewController: UITableViewController {

dataSource = SettingsDataSource(tableView: tableView, interactor: interactor)
dataSource?.delegate = self

interactor.didUpdateTunnelSettings = { [weak self] newSettings in
self?.dataSource?.reload(from: newSettings)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ import MullvadSettings

struct SettingsViewModel {
private(set) var daitaSettings: DAITASettings

mutating func setDAITASettings(_ newSettings: DAITASettings) {
daitaSettings = newSettings
}
private(set) var multihopState: MultihopState

init(from tunnelSettings: LatestTunnelSettings = LatestTunnelSettings()) {
daitaSettings = tunnelSettings.daita
multihopState = tunnelSettings.tunnelMultihopState
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -411,4 +411,4 @@ struct SingleChoiceList<Value>: View where Value: Equatable {
)
}
}
}
} // swiftlint:disable:this file_length
40 changes: 40 additions & 0 deletions ios/MullvadVPNUITests/Pages/SettingsPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ class SettingsPage: Page {
return self
}

@discardableResult func verifyDAITAOn() -> Self {
let textElement = app.tables[AccessibilityIdentifier.settingsTableView]
.cells[AccessibilityIdentifier.daitaCell]
.staticTexts["On"]

XCTAssertTrue(textElement.exists)

return self
}

@discardableResult func verifyDAITAOff() -> Self {
let textElement = app.tables[AccessibilityIdentifier.settingsTableView]
.cells[AccessibilityIdentifier.daitaCell]
.staticTexts["Off"]

XCTAssertTrue(textElement.exists)

return self
}

@discardableResult func tapMultihopCell() -> Self {
app.tables[AccessibilityIdentifier.settingsTableView]
.cells[AccessibilityIdentifier.multihopCell]
Expand All @@ -48,6 +68,26 @@ class SettingsPage: Page {
return self
}

@discardableResult func verifyMultihopOn() -> Self {
let textElement = app.tables[AccessibilityIdentifier.settingsTableView]
.cells[AccessibilityIdentifier.multihopCell]
.staticTexts["On"]

XCTAssertTrue(textElement.exists)

return self
}

@discardableResult func verifyMultihopOff() -> Self {
let textElement = app.tables[AccessibilityIdentifier.settingsTableView]
.cells[AccessibilityIdentifier.multihopCell]
.staticTexts["Off"]

XCTAssertTrue(textElement.exists)

return self
}

@discardableResult func tapVPNSettingsCell() -> Self {
app.tables[AccessibilityIdentifier.settingsTableView]
.cells[AccessibilityIdentifier.vpnSettingsCell]
Expand Down
4 changes: 4 additions & 0 deletions ios/MullvadVPNUITests/RelayTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ class RelayTests: LoggedInWithTimeUITestCase {
.tapSettingsButton()

SettingsPage(app)
.verifyDAITAOff()
.tapDAITACell()

DAITAPage(app)
Expand All @@ -313,6 +314,7 @@ class RelayTests: LoggedInWithTimeUITestCase {
.tapBackButton()

SettingsPage(app)
.verifyDAITAOn()
.tapDoneButton()

TunnelControlPage(app)
Expand Down Expand Up @@ -343,6 +345,7 @@ class RelayTests: LoggedInWithTimeUITestCase {
.tapSettingsButton()

SettingsPage(app)
.verifyMultihopOff()
.tapMultihopCell()

MultihopPage(app)
Expand All @@ -351,6 +354,7 @@ class RelayTests: LoggedInWithTimeUITestCase {
.tapBackButton()

SettingsPage(app)
.verifyMultihopOn()
.tapDoneButton()

TunnelControlPage(app)
Expand Down

0 comments on commit 9c27913

Please sign in to comment.