diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 081f4dfa9354..9bb283f5e6cd 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -108,7 +108,6 @@ 5846227326E22A160035F7C2 /* StorePaymentObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227226E22A160035F7C2 /* StorePaymentObserver.swift */; }; 5846227726E22A7C0035F7C2 /* StorePaymentManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5846227626E22A7C0035F7C2 /* StorePaymentManagerDelegate.swift */; }; 5847D58D29B7740F008C3808 /* RevokedCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5847D58C29B7740F008C3808 /* RevokedCoordinator.swift */; }; - 584D26C2270C8542004EA533 /* SettingsStaticTextFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26C1270C8542004EA533 /* SettingsStaticTextFooterView.swift */; }; 584D26C4270C855B004EA533 /* PreferencesDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26C3270C855A004EA533 /* PreferencesDataSource.swift */; }; 584D26C6270C8741004EA533 /* SettingsDNSTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584D26C5270C8741004EA533 /* SettingsDNSTextCell.swift */; }; 584EBDBD2747C98F00A0C9FD /* NSAttributedString+Markdown.swift in Sources */ = {isa = PBXBuildFile; fileRef = 584EBDBC2747C98F00A0C9FD /* NSAttributedString+Markdown.swift */; }; @@ -396,6 +395,7 @@ 7A7AD28F29DEDB1C00480EF1 /* SettingsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7AD28E29DEDB1C00480EF1 /* SettingsHeaderView.swift */; }; 7A818F1F29F0305800C7F0F4 /* RootConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A818F1E29F0305800C7F0F4 /* RootConfiguration.swift */; }; 7A83C3FF2A55B72E00DFB83A /* MullvadVPNApp.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = 7A83C3FE2A55B72E00DFB83A /* MullvadVPNApp.xctestplan */; }; + 7A83C4022A57FAA800DFB83A /* SettingsDNSInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A83C4012A57FAA800DFB83A /* SettingsDNSInfoCell.swift */; }; 7ABE318D2A1CDD4500DF4963 /* UIFont+Weight.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABE318C2A1CDD4500DF4963 /* UIFont+Weight.swift */; }; 7AE47E522A17972A000418DA /* CustomAlertViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE47E512A17972A000418DA /* CustomAlertViewController.swift */; }; 7AF0419E29E957EB00D492DD /* AccountCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF0419D29E957EB00D492DD /* AccountCoordinator.swift */; }; @@ -943,7 +943,6 @@ 584B26F3237434D00073B10E /* RelaySelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RelaySelectorTests.swift; sourceTree = ""; }; 584D0111299134AB00531822 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; 584D26BE270C550B004EA533 /* AnyIPAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyIPAddress.swift; sourceTree = ""; }; - 584D26C1270C8542004EA533 /* SettingsStaticTextFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsStaticTextFooterView.swift; sourceTree = ""; }; 584D26C3270C855A004EA533 /* PreferencesDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesDataSource.swift; sourceTree = ""; }; 584D26C5270C8741004EA533 /* SettingsDNSTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDNSTextCell.swift; sourceTree = ""; }; 584EBDBC2747C98F00A0C9FD /* NSAttributedString+Markdown.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSAttributedString+Markdown.swift"; sourceTree = ""; }; @@ -1181,6 +1180,7 @@ 7A818F1E29F0305800C7F0F4 /* RootConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootConfiguration.swift; sourceTree = ""; }; 7A83C3FE2A55B72E00DFB83A /* MullvadVPNApp.xctestplan */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MullvadVPNApp.xctestplan; sourceTree = ""; }; 7A83C4002A55B81A00DFB83A /* MullvadVPNCI.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = MullvadVPNCI.xctestplan; sourceTree = ""; }; + 7A83C4012A57FAA800DFB83A /* SettingsDNSInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsDNSInfoCell.swift; sourceTree = ""; }; 7ABE318C2A1CDD4500DF4963 /* UIFont+Weight.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Weight.swift"; sourceTree = ""; }; 7AE47E512A17972A000418DA /* CustomAlertViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomAlertViewController.swift; sourceTree = ""; }; 7AF0419D29E957EB00D492DD /* AccountCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountCoordinator.swift; sourceTree = ""; }; @@ -1582,20 +1582,20 @@ 583FE01829C19709006E85F9 /* Settings */ = { isa = PBXGroup; children = ( + 7A42DECC2A09064C00B209BE /* SelectableSettingsCell.swift */, 5819C2162729595500D6EC38 /* SettingsAddDNSEntryCell.swift */, 582BB1AE229566420055B6EF /* SettingsCell.swift */, 5864AF0029C7879B005B0CD9 /* SettingsCellFactory.swift */, - 7A7AD28E29DEDB1C00480EF1 /* SettingsHeaderView.swift */, 58EE2E38272FF814003BFF93 /* SettingsDataSource.swift */, 58EE2E39272FF814003BFF93 /* SettingsDataSourceDelegate.swift */, + 7A83C4012A57FAA800DFB83A /* SettingsDNSInfoCell.swift */, 584D26C5270C8741004EA533 /* SettingsDNSTextCell.swift */, + 7A7AD28E29DEDB1C00480EF1 /* SettingsHeaderView.swift */, + 7A42DEC82A05164100B209BE /* SettingsInputCell.swift */, 58677711290976FB006F721F /* SettingsInteractor.swift */, 5867770F290975E8006F721F /* SettingsInteractorFactory.swift */, - 584D26C1270C8542004EA533 /* SettingsStaticTextFooterView.swift */, 58ACF64A26553C3F00ACE4B7 /* SettingsSwitchCell.swift */, 58CCA01122424D11004F3011 /* SettingsViewController.swift */, - 7A42DEC82A05164100B209BE /* SettingsInputCell.swift */, - 7A42DECC2A09064C00B209BE /* SelectableSettingsCell.swift */, ); path = Settings; sourceTree = ""; @@ -3242,7 +3242,6 @@ E1FD0DF528AA7CE400299DB4 /* StatusActivityView.swift in Sources */, 0697D6E728F01513007A9E99 /* TransportMonitor.swift in Sources */, 58968FAE28743E2000B799DC /* TunnelInteractor.swift in Sources */, - 584D26C2270C8542004EA533 /* SettingsStaticTextFooterView.swift in Sources */, 587C93002986E2B600FB9664 /* TermsOfServiceCoordinator.swift in Sources */, 5864AF0929C78850005B0CD9 /* PreferencesCellFactory.swift in Sources */, 587B7536266528A200DEF7E9 /* NotificationManager.swift in Sources */, @@ -3358,6 +3357,7 @@ 58CCA01222424D11004F3011 /* SettingsViewController.swift in Sources */, F0E8CC0A2A4EE127007ED3B4 /* SetupAccountCompletedContentView.swift in Sources */, 581DA2752A1E283E0046ED47 /* WgKeyRotation.swift in Sources */, + 7A83C4022A57FAA800DFB83A /* SettingsDNSInfoCell.swift in Sources */, 06410DFE292CE18F00AFC18C /* KeychainSettingsStore.swift in Sources */, 58FB865526E8BF3100F188BC /* StorePaymentManagerError.swift in Sources */, 58FD5BF42428C67600112C88 /* InAppPurchaseButton.swift in Sources */, diff --git a/ios/MullvadVPN/UI appearance/UIMetrics.swift b/ios/MullvadVPN/UI appearance/UIMetrics.swift index 5eedb5b20bb7..fe20da05e45e 100644 --- a/ios/MullvadVPN/UI appearance/UIMetrics.swift +++ b/ios/MullvadVPN/UI appearance/UIMetrics.swift @@ -43,6 +43,11 @@ enum UIMetrics { enum Button { static let barButtonSize: CGFloat = 44.0 } + + enum SettingsCell { + static let textFieldContentInsets = UIEdgeInsets(top: 8, left: 24, bottom: 8, right: 24) + static let textFieldNonEditingContentInsetLeft: CGFloat = 40 + } } extension UIMetrics { diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift index 3fd3301a3620..722380886782 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift +++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesCellFactory.swift @@ -237,6 +237,14 @@ final class PreferencesCellFactory: CellFactoryProtocol { cell.onReturnKey = { cell in cell.endEditing(false) } + + case .dnsServerInfo: + guard let cell = cell as? SettingsDNSInfoCell else { return } + + cell.titleLabel.attributedText = viewModel.customDNSPrecondition.attributedLocalizedDescription( + isEditing: isEditing, + preferredFont: .systemFont(ofSize: 14) + ) } } diff --git a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift b/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift index fb70c8ab0a28..be24b99d53a9 100644 --- a/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift +++ b/ios/MullvadVPN/View controllers/Preferences/PreferencesDataSource.swift @@ -18,6 +18,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< case setting case settingSwitch case dnsServer + case dnsServerInfo case addDNSServer case wireGuardPort case wireGuardCustomPort @@ -30,6 +31,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< return SettingsSwitchCell.self case .dnsServer: return SettingsDNSTextCell.self + case .dnsServerInfo: + return SettingsDNSInfoCell.self case .addDNSServer: return SettingsAddDNSEntryCell.self case .wireGuardPort: @@ -43,15 +46,12 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< private enum HeaderFooterReuseIdentifiers: String, CaseIterable { case contentBlockerHeader case wireGuardPortHeader - case customDNSFooter case spacer var reusableViewClass: AnyClass { switch self { case .contentBlockerHeader, .wireGuardPortHeader: return SettingsHeaderView.self - case .customDNSFooter: - return SettingsStaticTextFooterView.self case .spacer: return EmptyTableViewHeaderFooterView.self } @@ -81,6 +81,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< case useCustomDNS case addDNSServer case dnsServer(_ uniqueID: UUID) + case dnsServerInfo static var contentBlockers: [Item] { [.blockAdvertising, .blockTracking, .blockMalware, .blockAdultContent, .blockGambling] @@ -119,6 +120,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< return "addDNSServer" case let .dnsServer(uuid): return "dnsServer(\(uuid.uuidString))" + case .dnsServerInfo: + return "dnsServerInfo" } } @@ -136,6 +139,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< return .addDNSServer case .dnsServer: return .dnsServer + case .dnsServerInfo: + return .dnsServerInfo case .wireGuardPort: return .wireGuardPort case .wireGuardCustomPort: @@ -200,8 +205,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.sanitizeCustomDNSEntries() } - updateSnapshot() - reloadCustomDNSFooter() + updateSnapshot(animated: true) viewModel.customDNSDomains.forEach { entry in self.reload(item: .dnsServer(entry.identifier)) @@ -247,9 +251,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel = mergedViewModel } - updateSnapshot { [weak self] in - self?.reloadCustomDNSFooter() - } + updateSnapshot() } // MARK: - UITableViewDataSource @@ -390,18 +392,13 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< case .contentBlockers: return nil - case .customDNS: - guard let view = tableView - .dequeueReusableHeaderFooterView( - withIdentifier: HeaderFooterReuseIdentifiers.customDNSFooter.rawValue - ) as? SettingsStaticTextFooterView else { return nil } - configureFooterView(view) - return view - case .wireGuardPorts: return tableView.dequeueReusableHeaderFooterView( withIdentifier: HeaderFooterReuseIdentifiers.spacer.rawValue ) + + default: + return nil } } @@ -421,19 +418,11 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< let sectionIdentifier = snapshot().sectionIdentifiers[section] switch sectionIdentifier { - case .contentBlockers: - return 0 - - case .customDNS: - switch viewModel.customDNSPrecondition { - case .satisfied: - return 0 - case .conflictsWithOtherSettings, .emptyDNSDomains: - return UITableView.automaticDimension - } - case .wireGuardPorts: return UIMetrics.sectionSpacing + + default: + return 0 } } @@ -509,6 +498,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< newSnapshot.appendSections(Section.allCases) + // Append sections + if oldSnapshot.sectionIdentifiers.contains(.contentBlockers) { newSnapshot.appendItems( oldSnapshot.itemIdentifiers(inSection: .contentBlockers), @@ -523,6 +514,8 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< ) } + // Append DNS settings + newSnapshot.appendItems([.useCustomDNS], toSection: .customDNS) let dnsServerItems = viewModel.customDNSDomains.map { entry in @@ -534,6 +527,18 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< newSnapshot.appendItems([.addDNSServer], toSection: .customDNS) } + // Append/update DNS server info. + + if viewModel.customDNSPrecondition == .satisfied { + newSnapshot.deleteItems([.dnsServerInfo]) + } else { + if newSnapshot.itemIdentifiers(inSection: .customDNS).contains(.dnsServerInfo) { + newSnapshot.reloadItems([.dnsServerInfo]) + } else { + newSnapshot.appendItems([.dnsServerInfo], toSection: .customDNS) + } + } + applySnapshot(newSnapshot, animated: animated, completion: completion) } @@ -561,7 +566,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.setBlockAdvertising(isEnabled) if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { - reloadCustomDNSFooter() + reloadDnsServerInfo() } if !isEditing { @@ -575,7 +580,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.setBlockTracking(isEnabled) if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { - reloadCustomDNSFooter() + reloadDnsServerInfo() } if !isEditing { @@ -589,7 +594,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.setBlockMalware(isEnabled) if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { - reloadCustomDNSFooter() + reloadDnsServerInfo() } if !isEditing { @@ -603,7 +608,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.setBlockAdultContent(isEnabled) if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { - reloadCustomDNSFooter() + reloadDnsServerInfo() } if !isEditing { @@ -617,7 +622,7 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.setBlockGambling(isEnabled) if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { - reloadCustomDNSFooter() + reloadDnsServerInfo() } if !isEditing { @@ -626,9 +631,13 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< } private func setEnableCustomDNS(_ isEnabled: Bool) { + let oldViewModel = viewModel + viewModel.setEnableCustomDNS(isEnabled) - reloadCustomDNSFooter() + if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { + reloadDnsServerInfo() + } if !isEditing { delegate?.preferencesDataSource(self, didChangeViewModel: viewModel) @@ -641,23 +650,17 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.updateDNSEntry(entryIdentifier: identifier, newAddress: inputString) if oldViewModel.customDNSPrecondition != viewModel.customDNSPrecondition { - reloadCustomDNSFooter() + reloadDnsServerInfo() } return viewModel.isDNSDomainUserInputValid(inputString) } private func addDNSServerEntry() { - let oldViewModel = viewModel - let newDNSEntry = DNSServerEntry(address: "") viewModel.customDNSDomains.append(newDNSEntry) updateSnapshot(animated: true) { [weak self] in - if oldViewModel.customDNSPrecondition != self?.viewModel.customDNSPrecondition { - self?.reloadCustomDNSFooter() - } - // Focus on the new entry text field. let lastDNSEntry = self?.snapshot().itemIdentifiers(inSection: .customDNS) .last { item in @@ -679,8 +682,6 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< } private func deleteDNSServerEntry(entryIdentifier: UUID) { - let oldViewModel = viewModel - let entryIndex = viewModel.customDNSDomains.firstIndex { entry in entry.identifier == entryIdentifier } @@ -689,23 +690,26 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< viewModel.customDNSDomains.remove(at: entryIndex) - updateSnapshot(animated: true) { [weak self] in - if oldViewModel.customDNSPrecondition != self?.viewModel.customDNSPrecondition { - self?.reloadCustomDNSFooter() - } - } + reload(item: .useCustomDNS) + updateSnapshot(animated: true) } - private func reloadCustomDNSFooter() { - reload(item: .useCustomDNS) + private func reloadDnsServerInfo() { + var snapshot = snapshot() - let sectionIndex = snapshot().indexOfSection(.customDNS)! + reload(item: .useCustomDNS) - UIView.performWithoutAnimation { - if let reusableView = tableView?.footerView(forSection: sectionIndex) as? SettingsStaticTextFooterView { - configureFooterView(reusableView) + if viewModel.customDNSPrecondition == .satisfied { + snapshot.deleteItems([.dnsServerInfo]) + } else { + if snapshot.itemIdentifiers(inSection: .customDNS).contains(.dnsServerInfo) { + snapshot.reloadItems([.dnsServerInfo]) + } else { + snapshot.appendItems([.dnsServerInfo], toSection: .customDNS) } } + + apply(snapshot, animatingDifferences: true) } private func configureContentBlockersHeader(_ reusableView: SettingsHeaderView) { @@ -779,18 +783,6 @@ final class PreferencesDataSource: UITableViewDiffableDataSource< } } - private func configureFooterView(_ reusableView: SettingsStaticTextFooterView) { - let font = reusableView.titleLabel.font ?? UIFont.systemFont(ofSize: UIFont.systemFontSize) - - reusableView.titleLabel.attributedText = viewModel.customDNSPrecondition - .attributedLocalizedDescription(isEditing: isEditing, preferredFont: font) - - reusableView.titleLabel.sizeToFit() - - // Applying background color of table view hides overflow from contracting cells below. - reusableView.contentView.backgroundColor = tableView?.backgroundColor - } - private func selectRow(at indexPath: IndexPath?, animated: Bool = false) { tableView?.selectRow(at: indexPath, animated: false, scrollPosition: .none) } diff --git a/ios/MullvadVPN/View controllers/Settings/SettingsDNSInfoCell.swift b/ios/MullvadVPN/View controllers/Settings/SettingsDNSInfoCell.swift new file mode 100644 index 000000000000..455396acd847 --- /dev/null +++ b/ios/MullvadVPN/View controllers/Settings/SettingsDNSInfoCell.swift @@ -0,0 +1,32 @@ +// +// SettingsDNSInfoCell.swift +// MullvadVPN +// +// Created by Jon Petersson on 2023-07-07. +// Copyright © 2023 Mullvad VPN AB. All rights reserved. +// + +import UIKit + +class SettingsDNSInfoCell: UITableViewCell { + let titleLabel = UILabel() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + backgroundColor = .secondaryColor + contentView.directionalLayoutMargins = UIMetrics.settingsCellLayoutMargins + + titleLabel.translatesAutoresizingMaskIntoConstraints = false + titleLabel.textColor = UIColor.Cell.titleTextColor + titleLabel.numberOfLines = 0 + + contentView.addConstrainedSubviews([titleLabel]) { + titleLabel.pinEdgesToSuperviewMargins() + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/ios/MullvadVPN/View controllers/Settings/SettingsDNSTextCell.swift b/ios/MullvadVPN/View controllers/Settings/SettingsDNSTextCell.swift index b6a3fe6bb269..cbb3c552bc44 100644 --- a/ios/MullvadVPN/View controllers/Settings/SettingsDNSTextCell.swift +++ b/ios/MullvadVPN/View controllers/Settings/SettingsDNSTextCell.swift @@ -24,11 +24,10 @@ class SettingsDNSTextCell: SettingsCell, UITextFieldDelegate { override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) - textField.translatesAutoresizingMaskIntoConstraints = false textField.font = UIFont.systemFont(ofSize: 17) textField.backgroundColor = .clear textField.textColor = UIColor.TextField.textColor - textField.textMargins = UIMetrics.contentInsets + textField.textMargins = UIMetrics.SettingsCell.textFieldContentInsets textField.placeholder = NSLocalizedString( "DNS_TEXT_CELL_PLACEHOLDER", tableName: "Settings", @@ -58,12 +57,9 @@ class SettingsDNSTextCell: SettingsCell, UITextFieldDelegate { overrideUserInterfaceStyle = .light - NSLayoutConstraint.activate([ - textField.topAnchor.constraint(equalTo: contentView.topAnchor), - textField.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), - textField.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), - textField.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), - ]) + contentView.addConstrainedSubviews([textField]) { + textField.pinEdgesToSuperview() + } updateCellAppearance(animated: false) } @@ -106,6 +102,8 @@ class SettingsDNSTextCell: SettingsCell, UITextFieldDelegate { textField.isEnabled = isEditing if isEditing { + textField.textMargins.left = UIMetrics.SettingsCell.textFieldContentInsets.left + if isValidInput { textField.textColor = UIColor.TextField.textColor } else { @@ -114,8 +112,9 @@ class SettingsDNSTextCell: SettingsCell, UITextFieldDelegate { backgroundView?.backgroundColor = UIColor.TextField.backgroundColor } else { - textField.textColor = .white + textField.textMargins.left = UIMetrics.SettingsCell.textFieldNonEditingContentInsetLeft + textField.textColor = .white backgroundView?.backgroundColor = UIColor.SubCell.backgroundColor } } diff --git a/ios/MullvadVPN/View controllers/Settings/SettingsStaticTextFooterView.swift b/ios/MullvadVPN/View controllers/Settings/SettingsStaticTextFooterView.swift deleted file mode 100644 index e99932dbebbf..000000000000 --- a/ios/MullvadVPN/View controllers/Settings/SettingsStaticTextFooterView.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// SettingsStaticTextFooterView.swift -// MullvadVPN -// -// Created by pronebird on 05/10/2021. -// Copyright © 2021 Mullvad VPN AB. All rights reserved. -// - -import UIKit - -class SettingsStaticTextFooterView: UITableViewHeaderFooterView { - let titleLabel: UILabel = { - let titleLabel = UILabel() - titleLabel.translatesAutoresizingMaskIntoConstraints = false - titleLabel.font = UIFont.systemFont(ofSize: 14) - titleLabel.textColor = .white - titleLabel.numberOfLines = 0 - return titleLabel - }() - - override init(reuseIdentifier: String?) { - super.init(reuseIdentifier: reuseIdentifier) - - contentView.directionalLayoutMargins = UIMetrics.settingsCellLayoutMargins - contentView.addSubview(titleLabel) - - contentView.addConstraints([ - titleLabel.topAnchor.constraint(equalTo: contentView.layoutMarginsGuide.topAnchor), - titleLabel.leadingAnchor - .constraint(equalTo: contentView.layoutMarginsGuide.leadingAnchor), - titleLabel.trailingAnchor - .constraint(equalTo: contentView.layoutMarginsGuide.trailingAnchor), - contentView.layoutMarginsGuide.bottomAnchor.constraint( - equalToSystemSpacingBelow: titleLabel.bottomAnchor, - multiplier: 1 - ) - .withPriority(.defaultLow), - ]) - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } -}