merge
This commit is contained in:
commit
e4c69d59f7
@ -272,6 +272,7 @@
|
|||||||
AAE7270E24AC8B9300A3ED0E /* HeadersH2CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */; };
|
AAE7270E24AC8B9300A3ED0E /* HeadersH2CaretLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */; };
|
||||||
AAE96FA225341F6A0037A989 /* ListStoreLocatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */; };
|
AAE96FA225341F6A0037A989 /* ListStoreLocatorModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */; };
|
||||||
AAE96FA525341F7D0037A989 /* ListStoreLocator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAE96FA425341F7D0037A989 /* ListStoreLocator.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 */; };
|
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */; };
|
||||||
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; };
|
BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; };
|
||||||
BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = "<group>"; };
|
||||||
@ -1538,6 +1540,15 @@
|
|||||||
path = Miscellaneous;
|
path = Miscellaneous;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
AFE4A1D427DFBB2700C458D0 /* NavigationController */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
|
||||||
|
AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */,
|
||||||
|
);
|
||||||
|
path = NavigationController;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
D202AFE2242A5F1400E5BEDF /* Extensions */ = {
|
D202AFE2242A5F1400E5BEDF /* Extensions */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -2076,9 +2087,9 @@
|
|||||||
D29DF11921E68467003B2FB9 /* Containers */ = {
|
D29DF11921E68467003B2FB9 /* Containers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
AFE4A1D427DFBB2700C458D0 /* NavigationController */,
|
||||||
0ABD1369237B18EE0081388D /* Views */,
|
0ABD1369237B18EE0081388D /* Views */,
|
||||||
D29DF2B621E7BE66003B2FB9 /* SplitViewController */,
|
D29DF2B621E7BE66003B2FB9 /* SplitViewController */,
|
||||||
D2B18B93236214AD00A9AEDC /* NavigationController.swift */,
|
|
||||||
);
|
);
|
||||||
path = Containers;
|
path = Containers;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2641,6 +2652,7 @@
|
|||||||
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
DBC4391922442197001AB423 /* DashLine.swift in Sources */,
|
||||||
D2ED27FC254B0E0300A1C293 /* MVMCoreAlertObject+Swift.swift in Sources */,
|
D2ED27FC254B0E0300A1C293 /* MVMCoreAlertObject+Swift.swift in Sources */,
|
||||||
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
|
D264FAAA2440F97600D98315 /* CollectionView.swift in Sources */,
|
||||||
|
AFE4A1D627DFBB6F00C458D0 /* UINavigationController+Extension.swift in Sources */,
|
||||||
AAC23FAD24D92A0D009208DF /* ListThreeColumnSpeedTestModel.swift in Sources */,
|
AAC23FAD24D92A0D009208DF /* ListThreeColumnSpeedTestModel.swift in Sources */,
|
||||||
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
|
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
|
||||||
01F2C20527C81F9700DC3D36 /* SubNavSwipeAnimator.swift in Sources */,
|
01F2C20527C81F9700DC3D36 /* SubNavSwipeAnimator.swift in Sources */,
|
||||||
|
|||||||
@ -18,10 +18,6 @@ import UIKit
|
|||||||
get { return model as? LineModel }
|
get { return model as? LineModel }
|
||||||
}
|
}
|
||||||
|
|
||||||
var lineBackgroundColor: Color? {
|
|
||||||
return (lineModel?.inverted ?? false) ? lineModel?.backgroundColor_inverted : lineModel?.backgroundColor
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Constraints
|
// MARK: - Constraints
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
@ -50,28 +46,33 @@ import UIKit
|
|||||||
addLine(to: view, edge: edge, useMargin: useMargin)
|
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
|
// MARK: - Methods
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
open func setStyle(_ style: LineModel.Style) {
|
open func setStyle(_ style: LineModel.Style) {
|
||||||
|
lineModel?.type = style
|
||||||
switch style {
|
backgroundColor = lineModel?.backgroundColor?.uiColor
|
||||||
case .standard:
|
updateLineConstraints(constant: lineModel?.thickness ?? 1)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open func shouldBeVisible() -> Bool {
|
open func shouldBeVisible() -> Bool {
|
||||||
@ -90,12 +91,10 @@ import UIKit
|
|||||||
|
|
||||||
open override func setupView() {
|
open override func setupView() {
|
||||||
super.setupView()
|
super.setupView()
|
||||||
|
|
||||||
heightConstraint = heightAnchor.constraint(equalToConstant: 1)
|
heightConstraint = heightAnchor.constraint(equalToConstant: 1)
|
||||||
heightConstraint?.isActive = true
|
heightConstraint?.isActive = true
|
||||||
widthConstraint = widthAnchor.constraint(equalToConstant: 1)
|
widthConstraint = widthAnchor.constraint(equalToConstant: 1)
|
||||||
widthConstraint?.isActive = false
|
widthConstraint?.isActive = false
|
||||||
setStyle(.standard)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
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? {
|
public override static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
|
return (model as? LineModel)?.thickness ?? 1
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,7 +86,7 @@ open class TabBarModel: MoleculeModelProtocol {
|
|||||||
if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedTab) {
|
if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedTab) {
|
||||||
selectedTab = index
|
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 {
|
open func encode(to encoder: Encoder) throws {
|
||||||
|
|||||||
@ -20,4 +20,5 @@ public protocol NavigationItemModelProtocol {
|
|||||||
var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
|
var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
|
||||||
var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
|
var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? { get set }
|
||||||
var titleView: 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 Foundation
|
||||||
|
import UIKit
|
||||||
|
|
||||||
// Navigation bar update functions
|
// Navigation bar update functions
|
||||||
public extension MVMCoreUISplitViewController {
|
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.
|
/// 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) {
|
func setNavigationBar(for viewController: UIViewController, navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) {
|
||||||
guard let splitView = MVMCoreUISplitViewController.main(),
|
guard navigationController == self.navigationController,
|
||||||
navigationController == splitView.navigationController,
|
viewController == getCurrentDetailViewController() else {
|
||||||
viewController == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() else {
|
|
||||||
/// Not the split view navigation controller, skip split functions.
|
/// Not the split view navigation controller, skip split functions.
|
||||||
return
|
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)
|
setLeftPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isLeftPanelAccessible?() ?? false, for: viewController, updateNavigationButtons: false)
|
||||||
setRightPanelIsAccessible((viewController as? MVMCoreUIDetailViewProtocol)?.isRightPanelAccessible?() ?? 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,
|
guard let navigationController = navigationController,
|
||||||
navigationController.isDisplayed(viewController: viewController),
|
navigationController.isDisplayed(viewController: viewController),
|
||||||
let model = navigationController.getNavigationModel(from: viewController) else { return }
|
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
|
// Reference to the top alert view
|
||||||
@property (nullable, weak, nonatomic) MVMCoreUITopAlertView *topAlertView;
|
@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.
|
// References to the current navigation item settings.
|
||||||
@property (nonatomic, readonly) BOOL leftPanelIsAccessible;
|
@property (nonatomic, readonly) BOOL leftPanelIsAccessible;
|
||||||
@property (nonatomic, readonly) BOOL rightPanelIsAccessible;
|
@property (nonatomic, readonly) BOOL rightPanelIsAccessible;
|
||||||
@ -122,10 +125,6 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
|
|||||||
+ (CGFloat)getApplicationViewWidth;
|
+ (CGFloat)getApplicationViewWidth;
|
||||||
+ (CGFloat)getApplicationViewMaxSize;
|
+ (CGFloat)getApplicationViewMaxSize;
|
||||||
|
|
||||||
// return subviewcontrollers' prefer status bar style
|
|
||||||
- (UIStatusBarStyle)getDefaultStatusBarStyle;
|
|
||||||
- (nullable UIColor *)getDefaultStatusBarBackgroundColor;
|
|
||||||
|
|
||||||
/// Returns true if a panel is showing.
|
/// Returns true if a panel is showing.
|
||||||
- (BOOL)isAPanelShowing;
|
- (BOOL)isAPanelShowing;
|
||||||
|
|
||||||
@ -166,4 +165,15 @@ typedef NS_ENUM(NSInteger, MFNumberOfDrawers) {
|
|||||||
/// Updates if the tab bar is showing or not.
|
/// Updates if the tab bar is showing or not.
|
||||||
- (void)updateTabBarShowing:(BOOL)showing;
|
- (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
|
@end
|
||||||
|
|||||||
@ -63,6 +63,10 @@ typedef NS_OPTIONS(NSInteger, MFExtendedDrawer) {
|
|||||||
@property (weak, nonatomic, readwrite) UIViewController *navigationItemViewController;
|
@property (weak, nonatomic, readwrite) UIViewController *navigationItemViewController;
|
||||||
@property (strong, nonatomic) NSNumber *transitionWidth;
|
@property (strong, nonatomic) NSNumber *transitionWidth;
|
||||||
|
|
||||||
|
@property (nonatomic) UIStatusBarStyle statusBarStyle;
|
||||||
|
@property (strong, nonatomic) NSLayoutConstraint *statusBarHeightConstraint;
|
||||||
|
@property (strong, nonatomic) NSLayoutConstraint *statusBarBottomConstraint;
|
||||||
|
|
||||||
// Dismisses any panel
|
// Dismisses any panel
|
||||||
- (void)dismissPanels:(id)sender;
|
- (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
|
#pragma mark - View Cyle
|
||||||
|
|
||||||
- (void)loadView {
|
- (void)loadView {
|
||||||
@ -849,6 +885,17 @@ CGFloat const PanelAnimationDuration = 0.2;
|
|||||||
view.translatesAutoresizingMaskIntoConstraints = NO;
|
view.translatesAutoresizingMaskIntoConstraints = NO;
|
||||||
self.view = view;
|
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
|
// Top Alert
|
||||||
MVMCoreUITopAlertView *topAlertView = nil;
|
MVMCoreUITopAlertView *topAlertView = nil;
|
||||||
if ([[CoreUIObject sharedInstance].globalTopAlertDelegate respondsToSelector:@selector(getTopAlertView)]) {
|
if ([[CoreUIObject sharedInstance].globalTopAlertDelegate respondsToSelector:@selector(getTopAlertView)]) {
|
||||||
@ -894,9 +941,9 @@ CGFloat const PanelAnimationDuration = 0.2;
|
|||||||
self.bottomProgressBarHeightConstraint = bottomProgressHeight;
|
self.bottomProgressBarHeightConstraint = bottomProgressHeight;
|
||||||
|
|
||||||
if (topAlertView) {
|
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 {
|
} 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.
|
// Add tabbar if we have it.
|
||||||
@ -924,7 +971,6 @@ CGFloat const PanelAnimationDuration = 0.2;
|
|||||||
|
|
||||||
- (void)viewDidLoad {
|
- (void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
[self.topAlertView pinATopViewController:self];
|
|
||||||
|
|
||||||
// Creates the back button
|
// Creates the back button
|
||||||
self.backButton = [[UIBarButtonItem alloc] initWithImage:[self imageForBackButton] style:UIBarButtonItemStylePlain target:self action:@selector(backButtonPressed:)];
|
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 {
|
- (BOOL)isAPanelShowing {
|
||||||
return fabs(self.mainViewLeading.constant) > 1;
|
return fabs(self.mainViewLeading.constant) > 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -78,7 +78,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
|||||||
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
|
if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) {
|
||||||
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
|
MVMCoreViewManagerViewControllerProtocolHelper.helpSetManager(self, viewController: controller)
|
||||||
}
|
}
|
||||||
hideNavigationBarLine(for: viewController)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
required public init?(coder: NSCoder) {
|
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) {
|
open override func viewWillDisappear(_ animated: Bool) {
|
||||||
super.viewWillDisappear(animated)
|
super.viewWillDisappear(animated)
|
||||||
|
|
||||||
// Notify showing view we will disappear.
|
// Notify showing view we will disappear.
|
||||||
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.managerWillDisappear?(self)
|
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.managerWillDisappear?(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Hides the navigation bar for the page.
|
/// Hides/Shows the navigation bar for the page.
|
||||||
open func hideNavigationBarLine(for viewController: UIViewController) {
|
open func hideNavigationBarLine(_ isHidden: Bool) {
|
||||||
(viewController as? PageProtocol)?.pageModel?.navigationBar?.line?.type = .none
|
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() {
|
open override func updateViews() {
|
||||||
@ -213,7 +223,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
|||||||
index != tabs.selectedIndex else { return }
|
index != tabs.selectedIndex else { return }
|
||||||
viewController = controller
|
viewController = controller
|
||||||
pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType
|
pageType = (viewController as? MVMCoreViewControllerProtocol)?.pageType
|
||||||
hideNavigationBarLine(for: controller)
|
|
||||||
if let viewController = getCurrentViewController() {
|
if let viewController = getCurrentViewController() {
|
||||||
manager?.willDisplay?(viewController)
|
manager?.willDisplay?(viewController)
|
||||||
}
|
}
|
||||||
@ -253,6 +262,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
|||||||
if let viewController = getCurrentViewController() {
|
if let viewController = getCurrentViewController() {
|
||||||
manager?.displayedViewController?(viewController)
|
manager?.displayedViewController?(viewController)
|
||||||
}
|
}
|
||||||
|
hideNavigationBarLine(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - TabsDelegate
|
// MARK: - TabsDelegate
|
||||||
@ -279,6 +289,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
|||||||
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
// MARK: - MVMCoreViewManagerViewControllerProtocol
|
||||||
|
|
||||||
open override func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
open override func viewControllerReady(inManager manager: UIViewController & MVMCoreViewManagerProtocol) {
|
||||||
|
super.viewControllerReady(inManager: manager)
|
||||||
// Pass on down
|
// Pass on down
|
||||||
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.viewControllerReady?(inManager: self)
|
(viewController as? MVMCoreViewManagerViewControllerProtocol)?.viewControllerReady?(inManager: self)
|
||||||
}
|
}
|
||||||
@ -297,19 +308,17 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol,
|
|||||||
}
|
}
|
||||||
|
|
||||||
open func newDataReceived(in viewController: UIViewController) {
|
open func newDataReceived(in viewController: UIViewController) {
|
||||||
if viewController == self.viewController {
|
|
||||||
hideNavigationBarLine(for: viewController)
|
|
||||||
}
|
|
||||||
manager?.newDataReceived?(in: viewController)
|
manager?.newDataReceived?(in: viewController)
|
||||||
|
hideNavigationBarLine(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func willDisplay(_ viewController: UIViewController) {
|
public func willDisplay(_ viewController: UIViewController) {
|
||||||
hideNavigationBarLine(for: viewController)
|
|
||||||
manager?.willDisplay?(viewController)
|
manager?.willDisplay?(viewController)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func displayedViewController(_ viewController: UIViewController) {
|
public func displayedViewController(_ viewController: UIViewController) {
|
||||||
manager?.displayedViewController?(viewController)
|
manager?.displayedViewController?(viewController)
|
||||||
|
hideNavigationBarLine(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - MVMCoreUISwipeNavigationProtocol
|
// MARK: - MVMCoreUISwipeNavigationProtocol
|
||||||
|
|||||||
@ -13,16 +13,19 @@
|
|||||||
|
|
||||||
@optional
|
@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;
|
- (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;
|
- (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;
|
- (void)collapseNotification;
|
||||||
|
|
||||||
/// Updates the existing top alert with the new object
|
/// Updates the existing top alert with the new object
|
||||||
- (void)updateTopAlertWith:(nullable MVMCoreTopAlertObject *)topAlertObject;
|
- (void)updateTopAlertWith:(nullable MVMCoreTopAlertObject *)topAlertObject;
|
||||||
|
|
||||||
|
/// Returns if the top alert is currently utilizing the status bar.
|
||||||
|
- (BOOL)overridingStatusBar;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@ -109,7 +109,7 @@ public extension MVMCoreUITopAlertView {
|
|||||||
// Update status bar.
|
// Update status bar.
|
||||||
guard let statusBarDelegate = molecule as? StatusBarUI else { return }
|
guard let statusBarDelegate = molecule as? StatusBarUI else { return }
|
||||||
let statusBarUI = statusBarDelegate.getStatusBarUI()
|
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>
|
@interface MVMCoreUITopAlertView : UIView <MVMCoreViewProtocol, MVMCoreTopAlertViewProtocol, MVMCoreLoadDelegateProtocol, MVMCoreActionDelegateProtocol, MVMCorePresentationDelegateProtocol, ButtonDelegateProtocol>
|
||||||
|
|
||||||
@property (nonatomic, readonly) UIStatusBarStyle statusBarStyle;
|
|
||||||
|
|
||||||
// Delegate for the top alert view
|
// Delegate for the top alert view
|
||||||
@property (nonatomic, nullable, weak) id <MVMCoreTopAlertAnimationDelegateProtocol> animationDelegate;
|
@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.
|
// Returns a TopAlertView with the mvm styling. Also sets the property in the session.
|
||||||
+ (nullable instancetype)setupTopAlertView;
|
+ (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.
|
// 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;
|
- (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
|
/// Get the content color based on the type
|
||||||
- (nonnull UIColor *)getContentColorForType:(nullable NSString *)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
|
@end
|
||||||
|
|||||||
@ -33,12 +33,6 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
|
|
||||||
@interface MVMCoreUITopAlertView ()
|
@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 (weak, nullable, nonatomic, readwrite) UIView *currentAlert;
|
||||||
@property (strong, nonatomic) NSLayoutConstraint *height;
|
@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.
|
/// Used if we delayed the collapse due to accessibility.
|
||||||
@property (copy, nonatomic) void (^ hideCompletionHandler)(BOOL finished);
|
@property (copy, nonatomic) void (^ hideCompletionHandler)(BOOL finished);
|
||||||
|
|
||||||
|
@property (nonatomic) BOOL currentAlertOverridingStatusBar;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation MVMCoreUITopAlertView
|
@implementation MVMCoreUITopAlertView
|
||||||
@ -88,34 +84,11 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)setupView {
|
- (void)setupView {
|
||||||
if (!self.statusBarView) {
|
if (self.height) { return; }
|
||||||
self.clipsToBounds = YES;
|
self.clipsToBounds = YES;
|
||||||
|
self.height = [self.heightAnchor constraintEqualToConstant:0];
|
||||||
UIView *statusBarView = [MVMCoreUICommonViewsUtility commonView];
|
self.height.active = YES;
|
||||||
UIView *alertView = [MVMCoreUICommonViewsUtility commonView];
|
[self registerWithNotificationCenter];
|
||||||
[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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateView:(CGFloat)size {
|
- (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 {
|
- (void)updateAccessibilityForTopAlert:(nullable UIView *)view {
|
||||||
// Update accessibility with top alert
|
// Update accessibility with top alert
|
||||||
if ([view isKindOfClass:[MVMCoreUITopAlertBaseView class]]) {
|
if ([view isKindOfClass:[MVMCoreUITopAlertBaseView class]]) {
|
||||||
@ -212,7 +153,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
if (weakSelf.currentAlert.superview) {
|
if (weakSelf.currentAlert.superview) {
|
||||||
[weakSelf.currentAlert removeFromSuperview];
|
[weakSelf.currentAlert removeFromSuperview];
|
||||||
}
|
}
|
||||||
[weakSelf.alertView addSubview:view];
|
[weakSelf addSubview:view];
|
||||||
[NSLayoutConstraint constraintPinSubviewToSuperview:view];
|
[NSLayoutConstraint constraintPinSubviewToSuperview:view];
|
||||||
weakSelf.currentAlert = view;
|
weakSelf.currentAlert = view;
|
||||||
|
|
||||||
@ -241,6 +182,40 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
[[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation];
|
[[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 {
|
- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
|
||||||
// If accessible and focused, do not collapse until unfocused.
|
// If accessible and focused, do not collapse until unfocused.
|
||||||
if (!forceful && [MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
|
if (!forceful && [MVMCoreUIUtility viewContainsAccessiblityFocus:self]) {
|
||||||
@ -278,9 +253,12 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
completionHandler(finished);
|
completionHandler(finished);
|
||||||
}
|
}
|
||||||
weakSelf.topAlertObject = nil;
|
weakSelf.topAlertObject = nil;
|
||||||
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
if (weakSelf.currentAlertOverridingStatusBar) {
|
||||||
[weakSelf setStatusBarColor:[UIColor whiteColor] statusBarStyle:UIStatusBarStyleDefault];
|
weakSelf.currentAlertOverridingStatusBar = NO;
|
||||||
}];
|
[MVMCoreDispatchUtility performBlockOnMainThread:^{
|
||||||
|
[[MVMCoreUISplitViewController mainSplitViewController] setStatusBarForCurrentViewController];
|
||||||
|
}];
|
||||||
|
}
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
}];
|
}];
|
||||||
@ -288,6 +266,11 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
|
|||||||
[[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation];
|
[[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
- (void)updateTopAlertWith:(MVMCoreTopAlertObject *)topAlertObject {
|
||||||
|
[self updateMoleculeWith:topAlertObject];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)collapseNotification {
|
- (void)collapseNotification {
|
||||||
if (self.currentAlert) {
|
if (self.currentAlert) {
|
||||||
if ([self.currentAlert isKindOfClass:[MVMCoreUITopAlertExpandableView class]] && ((MVMCoreUITopAlertExpandableView *)self.currentAlert).shortView.label.text.length > 0) {
|
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 {
|
- (BOOL)overridingStatusBar {
|
||||||
__weak typeof(self) weakSelf = self;
|
return self.currentAlertOverridingStatusBar;
|
||||||
[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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user