diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2020-09-17 17:51:42 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2021-02-24 11:19:07 +0100 |
| commit | cbf5a1ce71893522af5e79ed4e655ae7e487dd30 (patch) | |
| tree | e0e11ce84e62b7883aa3761d80c91d15de91582c | |
| parent | d3816ce772bf1a050f8a33d73e25ed3efec7c885 (diff) | |
| download | mullvadvpn-cbf5a1ce71893522af5e79ed4e655ae7e487dd30.tar.xz mullvadvpn-cbf5a1ce71893522af5e79ed4e655ae7e487dd30.zip | |
Add custom navigation controller
| -rw-r--r-- | ios/MullvadVPN.xcodeproj/project.pbxproj | 4 | ||||
| -rw-r--r-- | ios/MullvadVPN/CustomNavigationController.swift | 102 | ||||
| -rw-r--r-- | ios/MullvadVPN/SettingsNavigationController.swift | 2 |
3 files changed, 107 insertions, 1 deletions
diff --git a/ios/MullvadVPN.xcodeproj/project.pbxproj b/ios/MullvadVPN.xcodeproj/project.pbxproj index 4ccdcc0649..6f4e0914b3 100644 --- a/ios/MullvadVPN.xcodeproj/project.pbxproj +++ b/ios/MullvadVPN.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ 581CBCEE229826FD00727D7F /* StaticTableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 581CBCED229826FD00727D7F /* StaticTableViewDataSource.swift */; }; 58293FB125124117005D0BB5 /* CustomTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FB025124117005D0BB5 /* CustomTextField.swift */; }; 58293FB3251241B4005D0BB5 /* CustomTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FB2251241B3005D0BB5 /* CustomTextView.swift */; }; + 58293FB725138B88005D0BB5 /* CustomNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 58293FB625138B88005D0BB5 /* CustomNavigationController.swift */; }; 582AE3102440A6CA00E6733A /* AccountTokenInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 582AE30F2440A6CA00E6733A /* AccountTokenInput.swift */; }; 582AE3122440CA0D00E6733A /* AccountTokenInputTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 582AE3112440CA0D00E6733A /* AccountTokenInputTests.swift */; }; 582AE3132440CA2700E6733A /* AccountTokenInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 582AE30F2440A6CA00E6733A /* AccountTokenInput.swift */; }; @@ -288,6 +289,7 @@ 581CBCED229826FD00727D7F /* StaticTableViewDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticTableViewDataSource.swift; sourceTree = "<group>"; }; 58293FB025124117005D0BB5 /* CustomTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextField.swift; sourceTree = "<group>"; }; 58293FB2251241B3005D0BB5 /* CustomTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTextView.swift; sourceTree = "<group>"; }; + 58293FB625138B88005D0BB5 /* CustomNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomNavigationController.swift; sourceTree = "<group>"; }; 582AE30F2440A6CA00E6733A /* AccountTokenInput.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccountTokenInput.swift; sourceTree = "<group>"; }; 582AE3112440CA0D00E6733A /* AccountTokenInputTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTokenInputTests.swift; sourceTree = "<group>"; }; 582BB1AE229566420055B6EF /* SettingsCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsCell.swift; sourceTree = "<group>"; }; @@ -551,6 +553,7 @@ 58AB9DEB2501040C006C5526 /* ConsentViewController.xib */, 5896AE83246D5889005B36CB /* CustomDateComponentsFormatting.swift */, 582BB1B0229569620055B6EF /* CustomNavigationBar.swift */, + 58293FB625138B88005D0BB5 /* CustomNavigationController.swift */, 58293FB025124117005D0BB5 /* CustomTextField.swift */, 58293FB2251241B3005D0BB5 /* CustomTextView.swift */, 58C6B35D22BBBFE3003C19AD /* Data+HexCoding.swift */, @@ -1049,6 +1052,7 @@ 58CCA01E2242787B004F3011 /* AccountTextField.swift in Sources */, 587AD7CA2342283900E93A53 /* Account.swift in Sources */, 58F840AF2464382C0044E708 /* KeychainItemRevision.swift in Sources */, + 58293FB725138B88005D0BB5 /* CustomNavigationController.swift in Sources */, 587425C12299833500CA2045 /* RootContainerViewController.swift in Sources */, 580EE20124B321D500F9D8A1 /* OperationProtocol.swift in Sources */, 5896AE84246D5889005B36CB /* CustomDateComponentsFormatting.swift in Sources */, diff --git a/ios/MullvadVPN/CustomNavigationController.swift b/ios/MullvadVPN/CustomNavigationController.swift new file mode 100644 index 0000000000..1a7e7bb49d --- /dev/null +++ b/ios/MullvadVPN/CustomNavigationController.swift @@ -0,0 +1,102 @@ +// +// CustomNavigationController.swift +// MullvadVPN +// +// Created by pronebird on 17/09/2020. +// Copyright © 2020 Mullvad VPN AB. All rights reserved. +// + +import Foundation +import UIKit + +enum NavigationPopTrigger { + case backButton + case interactiveGesture +} + +protocol ConditionalNavigation: class { + func shouldPopNavigationItem(_ navigationItem: UINavigationItem, trigger: NavigationPopTrigger) -> Bool +} + +class CustomNavigationController: UINavigationController, UINavigationBarDelegate { + + private static let classInit: Void = { + swizzleMethod( + aClass: CustomNavigationController.self, + originalSelector: #selector(UINavigationBarDelegate.navigationBar(_:shouldPop:)), + newSelector: #selector(customNavigationController_navigationBar(_:shouldPop:)) + ) + }() + + private var popGestureRecognizerDelegate: CustomPopGestureRecognizerDelegate? + + override func viewDidLoad() { + super.viewDidLoad() + + _ = Self.classInit + + popGestureRecognizerDelegate = CustomPopGestureRecognizerDelegate(navigationController: self, systemGestureRecognizerDelegate: interactivePopGestureRecognizer?.delegate) + + // Replace the system interactive gesture recognizer + interactivePopGestureRecognizer?.delegate = popGestureRecognizerDelegate + } + + @objc dynamic func customNavigationController_navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool { + var shouldPop = true + + if let conformingViewController = topViewController as? ConditionalNavigation { + shouldPop = conformingViewController.shouldPopNavigationItem(item, trigger: .backButton) + } + + // Only call super implementation when we want to pop the controller + if shouldPop { + // Call super implementation + return customNavigationController_navigationBar(navigationBar, shouldPop: item) + } else { + return shouldPop + } + } +} + +private class CustomPopGestureRecognizerDelegate: NSObject, UIGestureRecognizerDelegate { + + private let systemGestureRecognizerDelegate: UIGestureRecognizerDelegate? + private weak var navigationController: UINavigationController? + + init(navigationController: UINavigationController, systemGestureRecognizerDelegate: UIGestureRecognizerDelegate?) { + self.navigationController = navigationController + self.systemGestureRecognizerDelegate = systemGestureRecognizerDelegate + } + + override func responds(to aSelector: Selector!) -> Bool { + if Self.instancesRespond(to: aSelector) { + return true + } else { + return systemGestureRecognizerDelegate?.responds(to: aSelector) ?? false + } + } + + override func forwardingTarget(for aSelector: Selector!) -> Any? { + let shouldForward = systemGestureRecognizerDelegate?.responds(to: aSelector) ?? false + + if shouldForward { + return systemGestureRecognizerDelegate + } else { + return nil + } + } + + // MARK: - UIGestureRecognizerDelegate + + func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { + let shouldBegin = systemGestureRecognizerDelegate?.gestureRecognizerShouldBegin?(gestureRecognizer) ?? true + + guard let navigationController = navigationController, + let topItem = navigationController.navigationBar.topItem, + let conformingViewController = navigationController.topViewController as? ConditionalNavigation else { + return shouldBegin + } + + return shouldBegin && conformingViewController.shouldPopNavigationItem(topItem, trigger: .interactiveGesture) + } +} diff --git a/ios/MullvadVPN/SettingsNavigationController.swift b/ios/MullvadVPN/SettingsNavigationController.swift index 87527b77cb..b582b78bca 100644 --- a/ios/MullvadVPN/SettingsNavigationController.swift +++ b/ios/MullvadVPN/SettingsNavigationController.swift @@ -9,7 +9,7 @@ import Foundation import UIKit -class SettingsNavigationController: UINavigationController { +class SettingsNavigationController: CustomNavigationController { override func viewDidLoad() { super.viewDidLoad() |
