merge
This commit is contained in:
commit
e4c69d59f7
@ -272,6 +272,7 @@
|
||||
AAE7270E24AC8B9300A3ED0E /* HeadersH2CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */; };
|
||||
AAE96FA225341F6A0037A989 /* ListStoreLocatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */; };
|
||||
AAE96FA525341F7D0037A989 /* ListStoreLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */; };
|
||||
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */; };
|
||||
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; };
|
||||
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; };
|
||||
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; };
|
||||
@ -858,6 +859,7 @@
|
||||
AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2CaretLink.swift; sourceTree = "<group>"; };
|
||||
AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocatorModel.swift; sourceTree = "<group>"; };
|
||||
AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = "<group>"; };
|
||||
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = "<group>"; };
|
||||
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSColorTokens.xcframework; path = ../SharedFrameworks/VDSColorTokens.xcframework; sourceTree = "<group>"; };
|
||||
BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = "<group>"; };
|
||||
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = "<group>"; };
|
||||
@ -1538,6 +1540,15 @@
|
||||
path = Miscellaneous;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
AFE4A1D427DFBB2700C458D0 /* NavigationController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
|
||||
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */,
|
||||
);
|
||||
path = NavigationController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D202AFE2242A5F1400E5BEDF /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -2076,9 +2087,9 @@
|
||||
D29DF11921E68467003B2FB9 /* Containers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
AFE4A1D427DFBB2700C458D0 /* NavigationController */,
|
||||
0ABD1369237B18EE0081388D /* Views */,
|
||||
D29DF2B621E7BE66003B2FB9 /* SplitViewController */,
|
||||
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
|
||||
);
|
||||
path = Containers;
|
||||
sourceTree = "<group>";
|
||||
@ -2641,6 +2652,7 @@
|
||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
||||
D2ED27FC254B0E0300A1C293 /* MVMCoreAlertObject+Swift.swift in Sources */,
|
||||
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
|
||||
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */,
|
||||
AAC23FAD24D92A0D009208DF /* ListThreeColumnSpeedTestModel.swift in Sources */,
|
||||
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
|
||||
01F2C20527C81F9700DC3D36 /* SubNavSwipeAnimator.swift in Sources */,
|
||||
|
||||
@ -18,10 +18,6 @@ import UIKit
|
||||
get { return model as? LineModel }
|
||||
}
|
||||
|
||||
var lineBackgroundColor: Color? {
|
||||
return (lineModel?.inverted ?? false) ? lineModel?.backgroundColor_inverted : lineModel?.backgroundColor
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//--------------------------------------------------
|
||||
@ -50,28 +46,33 @@ import UIKit
|
||||
addLine(to: view, edge: edge, useMargin: useMargin)
|
||||
}
|
||||
|
||||
public init() {
|
||||
super.init(frame: .zero)
|
||||
model = LineModel(type: .standard)
|
||||
}
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
model = LineModel(type: .standard)
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
model = LineModel(type: .standard)
|
||||
}
|
||||
|
||||
public required init(model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable : Any]?) {
|
||||
super.init(model: model, delegateObject, additionalData)
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
|
||||
open func setStyle(_ style: LineModel.Style) {
|
||||
|
||||
switch style {
|
||||
case .standard:
|
||||
updateLineConstraints(constant: 1)
|
||||
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmCoolGray3
|
||||
case .thin:
|
||||
updateLineConstraints(constant: 1)
|
||||
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
|
||||
case .medium:
|
||||
updateLineConstraints(constant: 2)
|
||||
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
|
||||
case .heavy:
|
||||
updateLineConstraints(constant: 4)
|
||||
backgroundColor = lineModel?.backgroundColor?.uiColor ?? .mvmBlack
|
||||
case .none:
|
||||
updateLineConstraints(constant: 0)
|
||||
}
|
||||
lineModel?.type = style
|
||||
backgroundColor = lineModel?.backgroundColor?.uiColor
|
||||
updateLineConstraints(constant: lineModel?.thickness ?? 1)
|
||||
}
|
||||
|
||||
open func shouldBeVisible() -> Bool {
|
||||
@ -90,12 +91,10 @@ import UIKit
|
||||
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
|
||||
heightConstraint = heightAnchor.constraint(equalToConstant: 1)
|
||||
heightConstraint?.isActive = true
|
||||
widthConstraint = widthAnchor.constraint(equalToConstant: 1)
|
||||
widthConstraint?.isActive = false
|
||||
setStyle(.standard)
|
||||
}
|
||||
|
||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
@ -111,19 +110,7 @@ import UIKit
|
||||
}
|
||||
|
||||
public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||
|
||||
guard let type = (model as? LineModel)?.type else { return 1 }
|
||||
|
||||
switch type {
|
||||
case .none:
|
||||
return 0
|
||||
case .medium:
|
||||
return 2
|
||||
case .heavy:
|
||||
return 4
|
||||
default:
|
||||
return 1
|
||||
}
|
||||
return (model as? LineModel)?.thickness ?? 1
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ open class TabBarModel: MoleculeModelProtocol {
|
||||
if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedTab) {
|
||||
selectedTab = index
|
||||
}
|
||||
style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) ?? .dark
|
||||
style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style)
|
||||
}
|
||||
|
||||
open func encode(to encoder: Encoder) throws {
|
||||
|
||||
@ -20,4 +20,5 @@ public protocol NavigationItemModelProtocol {
|
||||
var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
|
||||
var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
|
||||
var titleView: MoleculeModelProtocol? { get set }
|
||||
var titleOffset: UIOffset? { get }
|
||||
}
|
||||
|
||||
@ -1,201 +0,0 @@
|
||||
//
|
||||
// NavigationController.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 10/24/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class NavigationController: UINavigationController, MVMCoreViewManagerViewControllerProtocol {
|
||||
public var separatorView: Line?
|
||||
public weak var manager: (UIViewController & MVMCoreViewManagerProtocol)?
|
||||
|
||||
/// Getter for the main navigation controller
|
||||
public static func navigationController() -> Self? {
|
||||
return MVMCoreActionUtility.initializerClassCheck(MVMCoreUISession.sharedGlobal()?.navigationController, classToVerify: self) as? Self
|
||||
}
|
||||
|
||||
/// Provides MVM styling to the navigation bar. Returns a reference to the line.
|
||||
public static func style(_ navigationBar: UINavigationBar) -> Line {
|
||||
navigationBar.backgroundColor = .white
|
||||
navigationBar.shadowImage = UIImage()
|
||||
navigationBar.isOpaque = true
|
||||
navigationBar.tintColor = .black
|
||||
navigationBar.titleTextAttributes = [NSAttributedString.Key.font: MFStyler.fontBoldBodySmall(false)];
|
||||
return Line(pinTo: navigationBar, edge: .bottom, useMargin: false)
|
||||
}
|
||||
|
||||
/// Sets up the application with a navigation controller
|
||||
public static func setupNavigationController() -> Self? {
|
||||
let navigationController = self.init()
|
||||
navigationController.separatorView = style(navigationController.navigationBar)
|
||||
MVMCoreUISession.sharedGlobal()?.navigationController = navigationController
|
||||
MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController
|
||||
MVMCoreNavigationHandler.shared()?.navigationController = navigationController
|
||||
MVMCoreNavigationHandler.shared()?.addDelegate(navigationController)
|
||||
return navigationController
|
||||
}
|
||||
|
||||
/// Sets up the application with a navigation controller as the main container.
|
||||
public static func setupNavigationControllerAsMainController() -> Self? {
|
||||
guard let navigationController = setupNavigationController() else { return nil }
|
||||
MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController)
|
||||
return navigationController
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation item.
|
||||
public static func setNavigationItem(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) {
|
||||
viewController.navigationItem.title = navigationItemModel.title
|
||||
viewController.navigationItem.accessibilityLabel = navigationItemModel.title
|
||||
viewController.navigationItem.hidesBackButton = navigationItemModel.hidesSystemBackButton
|
||||
viewController.navigationItem.leftItemsSupplementBackButton = !navigationItemModel.hidesSystemBackButton
|
||||
setNavigationButtons(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||
setNavigationTitleView(navigationController: navigationController, navigationItemModel: navigationItemModel, viewController: viewController)
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation buttons.
|
||||
public static func setNavigationButtons(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) {
|
||||
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
|
||||
var leftItems: [UIBarButtonItem] = []
|
||||
if navigationItemModel.hidesSystemBackButton,
|
||||
navigationItemModel.alwaysShowBackButton != false {
|
||||
if let backButtonModel = navigationItemModel.backButton,
|
||||
MVMCoreNavigationHandler.shared()?.getViewControllers(for: navigationController)?.count ?? 0 > 1 || navigationItemModel.alwaysShowBackButton ?? false {
|
||||
leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
||||
}
|
||||
if let leftItemModels = navigationItemModel.additionalLeftButtons {
|
||||
for item in leftItemModels {
|
||||
leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
viewController.navigationItem.leftBarButtonItems = leftItems.count > 0 ? leftItems : nil
|
||||
|
||||
var rightItems: [UIBarButtonItem] = []
|
||||
if let rightItemModels = navigationItemModel.additionalRightButtons {
|
||||
for item in rightItemModels {
|
||||
rightItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
||||
}
|
||||
}
|
||||
viewController.navigationItem.rightBarButtonItems = rightItems.count > 0 ? rightItems : nil
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation bar ui, except for the buttons.
|
||||
public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) {
|
||||
navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true)
|
||||
navigationController.navigationBar.barTintColor = navigationItemModel.backgroundColor?.uiColor ?? .white
|
||||
|
||||
let tint = navigationItemModel.tintColor.uiColor
|
||||
navigationController.navigationBar.tintColor = tint
|
||||
|
||||
// Have the navigation title match the tint color
|
||||
navigationController.navigationBar.titleTextAttributes?.updateValue(tint, forKey: .foregroundColor)
|
||||
|
||||
// Update line.
|
||||
if let navigationController = navigationController as? NavigationController {
|
||||
navigationController.separatorView?.isHidden = navigationItemModel.line?.type ?? .standard == .none
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation titleView.
|
||||
public static func setNavigationTitleView(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol?, viewController: UIViewController) {
|
||||
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
|
||||
if let titleViewModel = navigationItemModel?.titleView, let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) {
|
||||
viewController.navigationItem.titleView = molecule
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience function to return the navigation model of the lowest controller traversing managers if applicable.
|
||||
public func getNavigationModel(from viewController: UIViewController) -> NavigationItemModelProtocol? {
|
||||
return (viewController as? PageProtocol)?.pageModel?.navigationBar
|
||||
}
|
||||
|
||||
/// Verifies the controller is the currently displayed controller.
|
||||
public func isDisplayed(viewController: UIViewController) -> Bool {
|
||||
guard let topViewController = topViewController,
|
||||
viewController == MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension NavigationController: MVMCoreViewManagerProtocol {
|
||||
public func getCurrentViewController() -> UIViewController? {
|
||||
guard let topViewController = topViewController else { return nil }
|
||||
return MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController)
|
||||
}
|
||||
|
||||
public func containsPage(withPageType pageType: String?) -> Bool {
|
||||
for controller in viewControllers {
|
||||
if let manager = controller as? MVMCoreViewManagerProtocol,
|
||||
manager.containsPage(withPageType: pageType) {
|
||||
return true
|
||||
} else if let controller = controller as? MVMCoreViewControllerProtocol,
|
||||
controller.pageType == pageType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func newDataReceived(in viewController: UIViewController) {
|
||||
|
||||
if isDisplayed(viewController: viewController),
|
||||
let topViewController = topViewController,
|
||||
let model = getNavigationModel(from: viewController) {
|
||||
Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: topViewController)
|
||||
Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: topViewController)
|
||||
}
|
||||
manager?.newDataReceived?(in: viewController)
|
||||
}
|
||||
|
||||
public func willDisplay(_ viewController: UIViewController) {
|
||||
if let topViewController = topViewController,
|
||||
let model = getNavigationModel(from: viewController) {
|
||||
Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: topViewController)
|
||||
}
|
||||
manager?.willDisplay?(viewController)
|
||||
}
|
||||
|
||||
public func displayedViewController(_ viewController: UIViewController) {
|
||||
if isDisplayed(viewController: viewController),
|
||||
let topViewController = topViewController,
|
||||
let model = getNavigationModel(from: viewController) {
|
||||
Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: topViewController)
|
||||
}
|
||||
manager?.displayedViewController?(viewController)
|
||||
}
|
||||
}
|
||||
|
||||
extension NavigationController: MVMCorePresentationDelegateProtocol {
|
||||
public func navigationController(_ navigationController: UINavigationController, prepareDisplayFor viewController: UIViewController) {
|
||||
guard self == navigationController,
|
||||
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController),
|
||||
let model = getNavigationModel(from: newViewController) else { return }
|
||||
Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: viewController)
|
||||
}
|
||||
|
||||
public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) {
|
||||
guard self == navigationController,
|
||||
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
|
||||
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
|
||||
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
|
||||
}
|
||||
manager?.willDisplay?(newViewController)
|
||||
}
|
||||
|
||||
public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) {
|
||||
guard self == navigationController,
|
||||
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
|
||||
if let model = getNavigationModel(from: newViewController) {
|
||||
Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: viewController)
|
||||
}
|
||||
manager?.displayedViewController?(newViewController)
|
||||
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
|
||||
controller.viewControllerReady?(inManager: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,136 @@
|
||||
//
|
||||
// NavigationController.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 10/24/19.
|
||||
// Copyright © 2019 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class NavigationController: UINavigationController, MVMCoreViewManagerViewControllerProtocol {
|
||||
public weak var manager: (UIViewController & MVMCoreViewManagerProtocol)?
|
||||
|
||||
/// Getter for the main navigation controller
|
||||
public static func navigationController() -> Self? {
|
||||
return MVMCoreActionUtility.initializerClassCheck(MVMCoreUISession.sharedGlobal()?.navigationController, classToVerify: self) as? Self
|
||||
}
|
||||
|
||||
/// Sets up the application with a navigation controller
|
||||
public static func setupNavigationController() -> Self? {
|
||||
let navigationController = self.init()
|
||||
MVMCoreUISession.sharedGlobal()?.navigationController = navigationController
|
||||
MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController
|
||||
MVMCoreNavigationHandler.shared()?.navigationController = navigationController
|
||||
MVMCoreNavigationHandler.shared()?.addDelegate(navigationController)
|
||||
navigationController.setNavigationBarUI(with: NavigationItemModel())
|
||||
return navigationController
|
||||
}
|
||||
|
||||
/// Sets up the application with a navigation controller as the main container.
|
||||
public static func setupNavigationControllerAsMainController() -> Self? {
|
||||
guard let navigationController = setupNavigationController() else { return nil }
|
||||
MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController)
|
||||
return navigationController
|
||||
}
|
||||
|
||||
/// Convenience function to return the navigation model of the lowest controller traversing managers if applicable.
|
||||
public func getNavigationModel(from viewController: UIViewController) -> NavigationItemModelProtocol? {
|
||||
return (viewController as? PageProtocol)?.pageModel?.navigationBar
|
||||
}
|
||||
|
||||
/// Verifies the controller is the currently displayed controller.
|
||||
public func isDisplayed(viewController: UIViewController) -> Bool {
|
||||
guard let topViewController = topViewController,
|
||||
viewController == MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController) else {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
extension NavigationController: MVMCoreViewManagerProtocol {
|
||||
public func getCurrentViewController() -> UIViewController? {
|
||||
guard let topViewController = topViewController else { return nil }
|
||||
return MVMCoreUIUtility.getViewControllerTraversingManagers(topViewController)
|
||||
}
|
||||
|
||||
public func containsPage(withPageType pageType: String?) -> Bool {
|
||||
for controller in viewControllers {
|
||||
if let manager = controller as? MVMCoreViewManagerProtocol,
|
||||
manager.containsPage(withPageType: pageType) {
|
||||
return true
|
||||
} else if let controller = controller as? MVMCoreViewControllerProtocol,
|
||||
controller.pageType == pageType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
public func newDataReceived(in viewController: UIViewController) {
|
||||
|
||||
if isDisplayed(viewController: viewController),
|
||||
let topViewController = topViewController,
|
||||
let model = getNavigationModel(from: viewController) {
|
||||
setNavigationItem(with: model, for: topViewController)
|
||||
setNavigationBarUI(with: model)
|
||||
}
|
||||
manager?.newDataReceived?(in: viewController)
|
||||
}
|
||||
|
||||
public func willDisplay(_ viewController: UIViewController) {
|
||||
if let topViewController = topViewController,
|
||||
let model = getNavigationModel(from: viewController) {
|
||||
setNavigationItem(with: model, for: topViewController)
|
||||
}
|
||||
manager?.willDisplay?(viewController)
|
||||
}
|
||||
|
||||
public func displayedViewController(_ viewController: UIViewController) {
|
||||
if isDisplayed(viewController: viewController),
|
||||
let model = getNavigationModel(from: viewController) {
|
||||
setNavigationBarUI(with: model)
|
||||
}
|
||||
manager?.displayedViewController?(viewController)
|
||||
}
|
||||
}
|
||||
|
||||
extension NavigationController: MVMCorePresentationDelegateProtocol {
|
||||
public func navigationController(_ navigationController: UINavigationController, prepareDisplayFor viewController: UIViewController) {
|
||||
guard self == navigationController,
|
||||
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController),
|
||||
let model = getNavigationModel(from: newViewController) else { return }
|
||||
setNavigationItem(with: model, for: viewController)
|
||||
}
|
||||
|
||||
public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) {
|
||||
guard self == navigationController,
|
||||
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
|
||||
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
|
||||
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
|
||||
}
|
||||
manager?.willDisplay?(newViewController)
|
||||
}
|
||||
|
||||
public func navigationController(_ navigationController: UINavigationController, displayedViewController viewController: UIViewController) {
|
||||
guard self == navigationController,
|
||||
let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return }
|
||||
if let model = getNavigationModel(from: newViewController) {
|
||||
setNavigationBarUI(with: model)
|
||||
}
|
||||
manager?.displayedViewController?(newViewController)
|
||||
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
|
||||
controller.viewControllerReady?(inManager: self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UIColor {
|
||||
func image(_ size: CGSize = CGSize(width: 1, height: 1)) -> UIImage {
|
||||
return UIGraphicsImageRenderer(size: size).image { rendererContext in
|
||||
self.setFill()
|
||||
rendererContext.fill(CGRect(origin: .zero, size: size))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
//
|
||||
// UINavigationController+Extension.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Scott Pfeil on 3/14/22.
|
||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension UINavigationController {
|
||||
|
||||
/// Convenience function for setting the navigation item.
|
||||
func setNavigationItem(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
|
||||
viewController.navigationItem.title = model.title
|
||||
viewController.navigationItem.accessibilityLabel = model.title
|
||||
viewController.navigationItem.hidesBackButton = model.hidesSystemBackButton
|
||||
viewController.navigationItem.leftItemsSupplementBackButton = !model.hidesSystemBackButton
|
||||
setNavigationButtons(with: model, for: viewController)
|
||||
setNavigationTitleView(with: model, for: viewController)
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation buttons.
|
||||
func setNavigationButtons(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
|
||||
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
|
||||
var leftItems: [UIBarButtonItem] = []
|
||||
if model.hidesSystemBackButton,
|
||||
model.alwaysShowBackButton != false {
|
||||
if let backButtonModel = model.backButton,
|
||||
MVMCoreNavigationHandler.shared()?.getViewControllers(for: self)?.count ?? 0 > 1 || model.alwaysShowBackButton ?? false {
|
||||
leftItems.append(backButtonModel.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
||||
}
|
||||
if let leftItemModels = model.additionalLeftButtons {
|
||||
for item in leftItemModels {
|
||||
leftItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
viewController.navigationItem.leftBarButtonItems = leftItems.count > 0 ? leftItems : nil
|
||||
|
||||
var rightItems: [UIBarButtonItem] = []
|
||||
if let rightItemModels = model.additionalRightButtons {
|
||||
for item in rightItemModels {
|
||||
rightItems.append(item.createNavigationItemButton(delegateObject: delegate, additionalData: nil))
|
||||
}
|
||||
}
|
||||
viewController.navigationItem.rightBarButtonItems = rightItems.count > 0 ? rightItems : nil
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation titleView.
|
||||
func setNavigationTitleView(with model: NavigationItemModelProtocol, for viewController: UIViewController) {
|
||||
let delegate = (viewController as? MVMCoreViewControllerProtocol)?.delegateObject?() as? MVMCoreUIDelegateObject
|
||||
if let titleViewModel = model.titleView,
|
||||
let molecule = ModelRegistry.createMolecule(titleViewModel, delegateObject: delegate, additionalData: nil) {
|
||||
viewController.navigationItem.titleView = molecule
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a ShadowImage based on the line property of NavigationItemModelProtocol
|
||||
func getNavigationBarShadowImage(for navigationItemModel: NavigationItemModelProtocol) -> UIImage? {
|
||||
guard let thickness = navigationItemModel.line?.thickness,
|
||||
let backgroundColor = navigationItemModel.line?.backgroundColor else { return nil }
|
||||
return backgroundColor.uiColor.image(CGSize(width: thickness, height: thickness))
|
||||
}
|
||||
|
||||
/// Convenience function for setting the navigation bar ui
|
||||
func setNavigationBarUI(with model: NavigationItemModelProtocol) {
|
||||
let navigationBar = navigationBar
|
||||
let font = MFStyler.fontBoldBodySmall(false)
|
||||
let backgroundColor = model.backgroundColor?.uiColor
|
||||
let tint = model.tintColor.uiColor
|
||||
navigationBar.tintColor = tint
|
||||
|
||||
let appearance = UINavigationBarAppearance()
|
||||
appearance.configureWithOpaqueBackground()
|
||||
appearance.titleTextAttributes = [NSAttributedString.Key.font: font,
|
||||
NSAttributedString.Key.foregroundColor: tint];
|
||||
appearance.backgroundColor = backgroundColor
|
||||
appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor)
|
||||
appearance.titlePositionAdjustment = model.titleOffset ?? .zero
|
||||
appearance.shadowColor = model.line?.backgroundColor?.uiColor ?? .clear
|
||||
appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate)
|
||||
navigationBar.standardAppearance = appearance
|
||||
navigationBar.scrollEdgeAppearance = appearance
|
||||
|
||||
setNavigationBarHidden(model.hidden, animated: true)
|
||||
}
|
||||
}
|
||||
@ -7,23 +7,19 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
// Navigation bar update functions
|
||||
public extension MVMCoreUISplitViewController {
|
||||
|
||||
/// Convenience function. Sets the navigation and split view properties for the view controller. Panel access is determined if view controller is a detail view protocol.
|
||||
static func setNavigationBarUI(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
|
||||
guard let splitView = MVMCoreUISplitViewController.main(),
|
||||
navigationController == splitView.navigationController,
|
||||
viewController == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() else {
|
||||
func setNavigationBar(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
|
||||
guard navigationController == self.navigationController,
|
||||
viewController == getCurrentDetailViewController() else {
|
||||
/// Not the split view navigation controller, skip split functions.
|
||||
return
|
||||
}
|
||||
splitView.set(for: viewController, navigationController: navigationController, navigationItemModel: navigationItemModel)
|
||||
}
|
||||
|
||||
/// Sets the navigation item for the view controller based on the model and splitview controller
|
||||
private func set(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
|
||||
|
||||
setLeftPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
|
||||
setRightPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
|
||||
|
||||
@ -121,7 +117,30 @@ public extension MVMCoreUISplitViewController {
|
||||
guard let navigationController = navigationController,
|
||||
navigationController.isDisplayed(viewController: viewController),
|
||||
let model = navigationController.getNavigationModel(from: viewController) else { return }
|
||||
set(for: viewController, navigationController: navigationController, navigationItemModel: model)
|
||||
setNavigationBar(for: viewController, navigationController: navigationController, navigationItemModel: model)
|
||||
guard !(topAlertView?.overridingStatusBar() ?? false) else { return }
|
||||
setStatusBarForCurrentViewController()
|
||||
}
|
||||
|
||||
/// Returns the bar style for the background color. Light if on a dark background, otherwise default.
|
||||
func getStatusBarStyle(for backgroundColor: UIColor?) -> UIStatusBarStyle {
|
||||
var greyScale: CGFloat = 0
|
||||
if backgroundColor?.getWhite(&greyScale, alpha: nil) == true,
|
||||
greyScale < 0.5 { return .lightContent }
|
||||
return .default
|
||||
}
|
||||
|
||||
/// Updates the status bar background color and style.
|
||||
@objc func setStatusBarForCurrentViewController() {
|
||||
let viewController = getCurrentViewController() as? MVMCoreUIDetailViewProtocol
|
||||
let backgroundColor = viewController?.defaultStatusBarBackgroundColor?() ??
|
||||
navigationController?.navigationBar.standardAppearance.backgroundColor ??
|
||||
statusBarView?.backgroundColor
|
||||
|
||||
let style = viewController?.defaultStatusBarStyle?() ??
|
||||
getStatusBarStyle(for: backgroundColor)
|
||||
|
||||
setStatusBarBackgroundColor(backgroundColor, style: style)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -44,6 +44,9 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
|
||||
// Reference to the top alert view
|
||||
@property (nullable, weak, nonatomic) MVMCoreUITopAlertView *topAlertView;
|
||||
|
||||
// Reference to the status bar view
|
||||
@property (nullable, weak, nonatomic) UIView *statusBarView;
|
||||
|
||||
// References to the current navigation item settings.
|
||||
@property (nonatomic, readonly) BOOL leftPanelIsAccessible;
|
||||
@property (nonatomic, readonly) BOOL rightPanelIsAccessible;
|
||||
@ -122,10 +125,6 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
|
||||
+ (CGFloat)getApplicationViewWidth;
|
||||
+ (CGFloat)getApplicationViewMaxSize;
|
||||
|
||||
// return subviewcontrollers' prefer status bar style
|
||||
- (UIStatusBarStyle)getDefaultStatusBarStyle;
|
||||
- (nullable UIColor *)getDefaultStatusBarBackgroundColor;
|
||||
|
||||
/// Returns true if a panel is showing.
|
||||
- (BOOL)isAPanelShowing;
|
||||
|
||||
@ -166,4 +165,15 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
|
||||
/// Updates if the tab bar is showing or not.
|
||||
- (void)updateTabBarShowing:(BOOL)showing;
|
||||
|
||||
#pragma mark - Status Bar
|
||||
|
||||
/// Updates the status bar with the given style and background color
|
||||
- (void)setStatusBarBackgroundColor:(nullable UIColor *)backgroundColor style:(UIStatusBarStyle)style;
|
||||
|
||||
/// Shows the view under the status bar.
|
||||
- (void)expandStatusBarView;
|
||||
|
||||
/// Hides the view under the status bar.
|
||||
- (void)collapseStatusBarView;
|
||||
|
||||
@end
|
||||
|
||||
@ -63,6 +63,10 @@ typedef NS_OPTIONS(NSInteger, MFExtendedDrawer) {
|
||||
@property (weak, nonatomic, readwrite) UIViewController *navigationItemViewController;
|
||||
@property (strong, nonatomic) NSNumber *transitionWidth;
|
||||
|
||||
@property (nonatomic) UIStatusBarStyle statusBarStyle;
|
||||
@property (strong, nonatomic) NSLayoutConstraint *statusBarHeightConstraint;
|
||||
@property (strong, nonatomic) NSLayoutConstraint *statusBarBottomConstraint;
|
||||
|
||||
// Dismisses any panel
|
||||
- (void)dismissPanels:(id)sender;
|
||||
|
||||
@ -841,6 +845,38 @@ CGFloat const PanelAnimationDuration = 0.2;
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Status Bar
|
||||
|
||||
- (void)setStatusBarBackgroundColor:(UIColor *)backgroundColor style:(UIStatusBarStyle)style {
|
||||
self.statusBarView.backgroundColor = backgroundColor;
|
||||
self.statusBarStyle = style;
|
||||
|
||||
// Triggers preferredStatusBarStyle
|
||||
[self.parentViewController setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle {
|
||||
return self.statusBarStyle;
|
||||
}
|
||||
|
||||
- (void)expandStatusBarView {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
weakSelf.statusBarBottomConstraint.active = YES;
|
||||
weakSelf.statusBarHeightConstraint.active = NO;
|
||||
[weakSelf.view layoutIfNeeded];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)collapseStatusBarView {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
weakSelf.statusBarBottomConstraint.active = NO;
|
||||
weakSelf.statusBarHeightConstraint.active = YES;
|
||||
[weakSelf.view layoutIfNeeded];
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - View Cyle
|
||||
|
||||
- (void)loadView {
|
||||
@ -849,6 +885,17 @@ CGFloat const PanelAnimationDuration = 0.2;
|
||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
self.view = view;
|
||||
|
||||
// Status bar
|
||||
UIView *statusBarView = [MVMCoreUICommonViewsUtility commonView];
|
||||
statusBarView.backgroundColor = [UIColor whiteColor];
|
||||
[self.view addSubview:statusBarView];
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[statusBarView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView)]];
|
||||
id topGuide = view.safeAreaLayoutGuide;
|
||||
self.statusBarBottomConstraint = [NSLayoutConstraint constraintWithItem:statusBarView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
|
||||
self.statusBarBottomConstraint.active = YES;
|
||||
self.statusBarHeightConstraint = [statusBarView.heightAnchor constraintEqualToConstant:0];
|
||||
self.statusBarView = statusBarView;
|
||||
|
||||
// Top Alert
|
||||
MVMCoreUITopAlertView *topAlertView = nil;
|
||||
if ([[CoreUIObject sharedInstance].globalTopAlertDelegate respondsToSelector:@selector(getTopAlertView)]) {
|
||||
@ -894,9 +941,9 @@ CGFloat const PanelAnimationDuration = 0.2;
|
||||
self.bottomProgressBarHeightConstraint = bottomProgressHeight;
|
||||
|
||||
if (topAlertView) {
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[topAlertView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(topAlertView, mainView, progressView)]];
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[statusBarView]-0-[topAlertView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView,topAlertView, mainView, progressView)]];
|
||||
} else {
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(mainView, progressView)]];
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[statusBarView]-0-[mainView]-0-[progressView]" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView,mainView, progressView)]];
|
||||
}
|
||||
|
||||
// Add tabbar if we have it.
|
||||
@ -924,7 +971,6 @@ CGFloat const PanelAnimationDuration = 0.2;
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
[self.topAlertView pinATopViewController:self];
|
||||
|
||||
// Creates the back button
|
||||
self.backButton = [[UIBarButtonItem alloc] initWithImage:[self imageForBackButton] style:UIBarButtonItemStylePlain target:self action:@selector(backButtonPressed:)];
|
||||
@ -1008,36 +1054,6 @@ CGFloat const PanelAnimationDuration = 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle {
|
||||
if (self.topAlertView.topAlertObject) {
|
||||
return self.topAlertView.statusBarStyle;
|
||||
} else {
|
||||
UIStatusBarStyle style = [self getDefaultStatusBarStyle];
|
||||
[self.topAlertView resetDefaultBackgroundColor:[self getDefaultStatusBarBackgroundColor] basedOnStatusBarStyle:style];
|
||||
return style;
|
||||
}
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)getDefaultStatusBarStyle {
|
||||
UIViewController *viewController = [self getCurrentDetailViewController];
|
||||
if ([viewController conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)]
|
||||
&& [viewController respondsToSelector:@selector(defaultStatusBarStyle)]
|
||||
&& [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarStyle]) {
|
||||
return [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarStyle];
|
||||
}
|
||||
return UIStatusBarStyleDefault;
|
||||
}
|
||||
|
||||
- (UIColor *)getDefaultStatusBarBackgroundColor {
|
||||
UIViewController *viewController = [self getCurrentDetailViewController];
|
||||
if ([viewController conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)]
|
||||
&& [viewController respondsToSelector:@selector(defaultStatusBarBackgroundColor)]
|
||||
&& [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarBackgroundColor]) {
|
||||
return [((UIViewController <MVMCoreUIDetailViewProtocol> *)viewController) defaultStatusBarBackgroundColor];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BOOL)isAPanelShowing {
|
||||
return fabs(self.mainViewLeading.constant) > 1;
|
||||
}
|
||||
|
||||
@ -78,7 +78,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
|
||||
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
|
||||
}
|
||||
hideNavigationBarLine(for: viewController)
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
@ -111,16 +110,27 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
}
|
||||
}
|
||||
|
||||
open override func pageShown() {
|
||||
// Currently not calling super until we can decouple page shown logics for managers.
|
||||
hideNavigationBarLine(true)
|
||||
}
|
||||
|
||||
open override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
// Notify showing view we will disappear.
|
||||
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.managerWillDisappear?(self)
|
||||
}
|
||||
|
||||
/// Hides the navigation bar for the page.
|
||||
open func hideNavigationBarLine(for viewController: UIViewController) {
|
||||
(viewController as? PageProtocol)?.pageModel?.navigationBar?.line?.type = .none
|
||||
/// Hides/Shows the navigation bar for the page.
|
||||
open func hideNavigationBarLine(_ isHidden: Bool) {
|
||||
guard self == navigationController?.topViewController else { return }
|
||||
var color = UIColor.clear
|
||||
if !isHidden,
|
||||
let backgroundColor = (getCurrentViewController() as? PageProtocol)?.pageModel?.navigationBar?.line?.backgroundColor?.uiColor {
|
||||
color = backgroundColor
|
||||
}
|
||||
navigationController?.navigationBar.standardAppearance.shadowColor = color
|
||||
navigationController?.navigationBar.scrollEdgeAppearance?.shadowColor = color
|
||||
}
|
||||
|
||||
open override func updateViews() {
|
||||
@ -213,7 +223,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
index != tabs.selectedIndex else { return }
|
||||
viewController = controller
|
||||
pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType
|
||||
hideNavigationBarLine(for: controller)
|
||||
if let viewController = getCurrentViewController() {
|
||||
manager?.willDisplay?(viewController)
|
||||
}
|
||||
@ -253,6 +262,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
if let viewController = getCurrentViewController() {
|
||||
manager?.displayedViewController?(viewController)
|
||||
}
|
||||
hideNavigationBarLine(true)
|
||||
}
|
||||
|
||||
// MARK: - TabsDelegate
|
||||
@ -279,6 +289,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
||||
|
||||
open override func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
||||
super.viewControllerReady(inManager: manager)
|
||||
// Pass on down
|
||||
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.viewControllerReady?(inManager: self)
|
||||
}
|
||||
@ -297,19 +308,17 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
||||
}
|
||||
|
||||
open func newDataReceived(in viewController: UIViewController) {
|
||||
if viewController == self.viewController {
|
||||
hideNavigationBarLine(for: viewController)
|
||||
}
|
||||
manager?.newDataReceived?(in: viewController)
|
||||
hideNavigationBarLine(true)
|
||||
}
|
||||
|
||||
public func willDisplay(_ viewController: UIViewController) {
|
||||
hideNavigationBarLine(for: viewController)
|
||||
manager?.willDisplay?(viewController)
|
||||
}
|
||||
|
||||
public func displayedViewController(_ viewController: UIViewController) {
|
||||
manager?.displayedViewController?(viewController)
|
||||
hideNavigationBarLine(true)
|
||||
}
|
||||
|
||||
// MARK: - MVMCoreUISwipeNavigationProtocol
|
||||
|
||||
@ -13,16 +13,19 @@
|
||||
|
||||
@optional
|
||||
|
||||
// Show based on the object
|
||||
/// Show based on the object
|
||||
- (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
|
||||
|
||||
// Hides
|
||||
/// Removes the notification
|
||||
- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
|
||||
|
||||
// Collapses the notification if it has a short top message. Otherwise removes notification.
|
||||
/// Collapses the notification if it has a short top message. Otherwise removes notification.
|
||||
- (void)collapseNotification;
|
||||
|
||||
/// Updates the existing top alert with the new object
|
||||
- (void)updateTopAlertWith:(nullable MVMCoreTopAlertObject *)topAlertObject;
|
||||
|
||||
/// Returns if the top alert is currently utilizing the status bar.
|
||||
- (BOOL)overridingStatusBar;
|
||||
|
||||
@end
|
||||
|
||||
@ -109,7 +109,7 @@ public extension MVMCoreUITopAlertView {
|
||||
// Update status bar.
|
||||
guard let statusBarDelegate = molecule as? StatusBarUI else { return }
|
||||
let statusBarUI = statusBarDelegate.getStatusBarUI()
|
||||
self.setStatusBarColor(statusBarUI.color, statusBarStyle: statusBarUI.style)
|
||||
MVMCoreUISplitViewController.main()?.setStatusBarBackgroundColor(statusBarUI.color, style: statusBarUI.style)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -19,8 +19,6 @@
|
||||
|
||||
@interface MVMCoreUITopAlertView : UIView <MVMCoreViewProtocol, MVMCoreTopAlertViewProtocol, MVMCoreLoadDelegateProtocol, MVMCoreActionDelegateProtocol, MVMCorePresentationDelegateProtocol, ButtonDelegateProtocol>
|
||||
|
||||
@property (nonatomic, readonly) UIStatusBarStyle statusBarStyle;
|
||||
|
||||
// Delegate for the top alert view
|
||||
@property (nonatomic, nullable, weak) id <MVMCoreTopAlertAnimationDelegateProtocol> animationDelegate;
|
||||
|
||||
@ -36,16 +34,6 @@
|
||||
// Returns a TopAlertView with the mvm styling. Also sets the property in the session.
|
||||
+ (nullable instancetype)setupTopAlertView;
|
||||
|
||||
// Pins the status bar view at the top of the passed in view controller.
|
||||
- (void)pinATopViewController:(nonnull UIViewController *)viewController;
|
||||
|
||||
// For controlling the status bar view
|
||||
- (void)expandStatusBarView;
|
||||
- (void)collapseStatusBarView;
|
||||
|
||||
/// reset status bar background color, when backgroundColor is nil corresponding background color will be set based on style
|
||||
- (void)resetDefaultBackgroundColor:(nullable UIColor *)backgroundColor basedOnStatusBarStyle:(UIStatusBarStyle)style;
|
||||
|
||||
// Can be subclassed for custom views.
|
||||
- (nonnull UIView *)topAlertViewForTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate statusBarColor:(UIColor *_Nullable *_Nullable)statusBarColor statusBarStyle:(UIStatusBarStyle *_Nullable)statusBarStyle;
|
||||
|
||||
@ -55,7 +43,4 @@
|
||||
/// Get the content color based on the type
|
||||
- (nonnull UIColor *)getContentColorForType:(nullable NSString *)type;
|
||||
|
||||
// Set the status bar color. Used for updating the status bar when the view changes.
|
||||
- (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style;
|
||||
|
||||
@end
|
||||
|
||||
@ -33,12 +33,6 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
|
||||
@interface MVMCoreUITopAlertView ()
|
||||
|
||||
@property (nonatomic, readwrite) UIStatusBarStyle statusBarStyle;
|
||||
@property (weak, nonatomic) UIView *statusBarView;
|
||||
@property (strong, nonatomic) NSLayoutConstraint *statusBarHeightConstraint;
|
||||
@property (strong, nonatomic) NSLayoutConstraint *statusBarBottomConstraint;
|
||||
|
||||
@property (weak, nonatomic) UIView *alertView;
|
||||
@property (weak, nullable, nonatomic, readwrite) UIView *currentAlert;
|
||||
@property (strong, nonatomic) NSLayoutConstraint *height;
|
||||
|
||||
@ -48,6 +42,8 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
/// Used if we delayed the collapse due to accessibility.
|
||||
@property (copy, nonatomic) void (^ hideCompletionHandler)(BOOL finished);
|
||||
|
||||
@property (nonatomic) BOOL currentAlertOverridingStatusBar;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MVMCoreUITopAlertView
|
||||
@ -88,34 +84,11 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
}
|
||||
|
||||
- (void)setupView {
|
||||
if (!self.statusBarView) {
|
||||
self.clipsToBounds = YES;
|
||||
|
||||
UIView *statusBarView = [MVMCoreUICommonViewsUtility commonView];
|
||||
UIView *alertView = [MVMCoreUICommonViewsUtility commonView];
|
||||
[self addSubview:alertView];
|
||||
[self addSubview:statusBarView];
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[statusBarView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView)]];
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-0-[alertView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(alertView)]];
|
||||
[NSLayoutConstraint activateConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[statusBarView]-0-[alertView]-0-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(statusBarView,alertView)]];
|
||||
self.statusBarHeightConstraint = [statusBarView.heightAnchor constraintEqualToConstant:0];
|
||||
self.statusBarHeightConstraint.active = YES;
|
||||
self.height = [alertView.heightAnchor constraintEqualToConstant:0];
|
||||
self.height.active = YES;
|
||||
self.alertView = alertView;
|
||||
self.statusBarView = statusBarView;
|
||||
|
||||
[self setStatusBarColor:[UIColor whiteColor] statusBarStyle:UIStatusBarStyleDefault];
|
||||
|
||||
[self registerWithNotificationCenter];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pinATopViewController:(UIViewController *)viewController {
|
||||
self.statusBarHeightConstraint.active = NO;
|
||||
id topGuide = viewController.view.safeAreaLayoutGuide;
|
||||
self.statusBarBottomConstraint = [NSLayoutConstraint constraintWithItem:self.statusBarView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:topGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:0];
|
||||
self.statusBarBottomConstraint.active = YES;
|
||||
if (self.height) { return; }
|
||||
self.clipsToBounds = YES;
|
||||
self.height = [self.heightAnchor constraintEqualToConstant:0];
|
||||
self.height.active = YES;
|
||||
[self registerWithNotificationCenter];
|
||||
}
|
||||
|
||||
- (void)updateView:(CGFloat)size {
|
||||
@ -159,38 +132,6 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
||||
|
||||
self.animationDelegate = animationDelegate;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
self.topAlertObject = topAlertObject;
|
||||
self.topAlertClearspotView = nil;
|
||||
|
||||
UIColor *statusBarColor = nil;
|
||||
UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault;
|
||||
UIView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle];
|
||||
if ([view conformsToProtocol:@protocol(MVMCoreViewProtocol)]) {
|
||||
[((UIView <MVMCoreViewProtocol>*)view) updateView:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
if (!statusBarColor) {
|
||||
statusBarColor = [UIColor whiteColor];
|
||||
}
|
||||
[self setStatusBarColor:statusBarColor statusBarStyle:statusBarStyle];
|
||||
[self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)updateTopAlertWith:(MVMCoreTopAlertObject *)topAlertObject {
|
||||
[self updateMoleculeWith:topAlertObject];
|
||||
}
|
||||
|
||||
- (void)setStatusBarColor:(nullable UIColor *)statusBarColor statusBarStyle:(UIStatusBarStyle)style {
|
||||
self.statusBarView.backgroundColor = statusBarColor;
|
||||
self.statusBarStyle = style;
|
||||
[[MVMCoreUISession sharedGlobal].splitViewController.parentViewController setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
|
||||
- (void)updateAccessibilityForTopAlert:(nullable UIView *)view {
|
||||
// Update accessibility with top alert
|
||||
if ([view isKindOfClass:[MVMCoreUITopAlertBaseView class]]) {
|
||||
@ -212,7 +153,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
if (weakSelf.currentAlert.superview) {
|
||||
[weakSelf.currentAlert removeFromSuperview];
|
||||
}
|
||||
[weakSelf.alertView addSubview:view];
|
||||
[weakSelf addSubview:view];
|
||||
[NSLayoutConstraint constraintPinSubviewToSuperview:view];
|
||||
weakSelf.currentAlert = view;
|
||||
|
||||
@ -241,6 +182,40 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation];
|
||||
}
|
||||
|
||||
|
||||
/// If the voice over user leaves top alert focus, hide.
|
||||
- (void)accessibilityFocusChanged:(NSNotification *)notification {
|
||||
if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil];
|
||||
[self hideAlertView:YES completionHandler:self.hideCompletionHandler];
|
||||
self.hideCompletionHandler = nil;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - MVMCoreTopAlertViewProtocol
|
||||
|
||||
- (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
||||
|
||||
self.animationDelegate = animationDelegate;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
self.topAlertObject = topAlertObject;
|
||||
self.topAlertClearspotView = nil;
|
||||
|
||||
UIColor *statusBarColor = nil;
|
||||
UIStatusBarStyle statusBarStyle = UIStatusBarStyleDefault;
|
||||
UIView *view = [self topAlertViewForTopAlertObject:topAlertObject animationDelegate:animationDelegate statusBarColor:&statusBarColor statusBarStyle:&statusBarStyle];
|
||||
if ([view conformsToProtocol:@protocol(MVMCoreViewProtocol)]) {
|
||||
[((UIView <MVMCoreViewProtocol>*)view) updateView:CGRectGetWidth(self.bounds)];
|
||||
}
|
||||
if (statusBarColor) {
|
||||
self.currentAlertOverridingStatusBar = YES;
|
||||
[[MVMCoreUISplitViewController mainSplitViewController] setStatusBarBackgroundColor:statusBarColor style:statusBarStyle];
|
||||
}
|
||||
[self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
||||
// If accessible and focused, do not collapse until unfocused.
|
||||
if (!forceful && [MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
|
||||
@ -278,9 +253,12 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
completionHandler(finished);
|
||||
}
|
||||
weakSelf.topAlertObject = nil;
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
[weakSelf setStatusBarColor:[UIColor whiteColor] statusBarStyle:UIStatusBarStyleDefault];
|
||||
}];
|
||||
if (weakSelf.currentAlertOverridingStatusBar) {
|
||||
weakSelf.currentAlertOverridingStatusBar = NO;
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
[[MVMCoreUISplitViewController mainSplitViewController] setStatusBarForCurrentViewController];
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
@ -288,6 +266,11 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
[[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation];
|
||||
}
|
||||
|
||||
|
||||
- (void)updateTopAlertWith:(MVMCoreTopAlertObject *)topAlertObject {
|
||||
[self updateMoleculeWith:topAlertObject];
|
||||
}
|
||||
|
||||
- (void)collapseNotification {
|
||||
if (self.currentAlert) {
|
||||
if ([self.currentAlert isKindOfClass:[MVMCoreUITopAlertExpandableView class]] && ((MVMCoreUITopAlertExpandableView *)self.currentAlert).shortView.label.text.length > 0) {
|
||||
@ -301,45 +284,8 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
||||
}
|
||||
}
|
||||
|
||||
- (void)expandStatusBarView {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
weakSelf.statusBarBottomConstraint.active = YES;
|
||||
weakSelf.statusBarHeightConstraint.active = NO;
|
||||
[weakSelf.superview layoutIfNeeded];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)collapseStatusBarView {
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||
weakSelf.statusBarBottomConstraint.active = NO;
|
||||
weakSelf.statusBarHeightConstraint.active = YES;
|
||||
[weakSelf.superview layoutIfNeeded];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)resetDefaultBackgroundColor:(UIColor *)backgroundColor basedOnStatusBarStyle:(UIStatusBarStyle)style {
|
||||
if (!self.topAlertObject) {
|
||||
UIColor *defaultStatusBarBackgroundColor = backgroundColor;
|
||||
if (!defaultStatusBarBackgroundColor) {
|
||||
defaultStatusBarBackgroundColor = style == UIStatusBarStyleDefault ? [UIColor whiteColor] : [UIColor blackColor];
|
||||
}
|
||||
|
||||
//color doesn't match the current default value
|
||||
if (!CGColorEqualToColor(defaultStatusBarBackgroundColor.CGColor, self.statusBarView.backgroundColor.CGColor)) {
|
||||
self.statusBarView.backgroundColor = defaultStatusBarBackgroundColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If the voice over user leaves top alert focus, hide.
|
||||
- (void)accessibilityFocusChanged:(NSNotification *)notification {
|
||||
if (notification.userInfo[UIAccessibilityFocusedElementKey] && ![MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIAccessibilityElementFocusedNotification object:nil];
|
||||
[self hideAlertView:YES completionHandler:self.hideCompletionHandler];
|
||||
self.hideCompletionHandler = nil;
|
||||
}
|
||||
- (BOOL)overridingStatusBar {
|
||||
return self.currentAlertOverridingStatusBar;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user