From b4af1abe81246d611a34957d7f082d214967dc77 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 7 Mar 2022 01:03:36 -0500 Subject: [PATCH 01/19] subnav and tab bar color changes --- MVMCoreUI.xcodeproj/project.pbxproj | 4 + .../TabBarModel.swift | 53 ++++++++++++-- .../HorizontalCombinationViews/Tabs.swift | 5 +- .../TabsModel.swift | 73 +++++++++++++++++-- .../NavigationBar/NavigationBar.swift | 39 ++++++++++ .../NavigationBar/NavigationItemModel.swift | 71 +++++++++++++----- .../NavigationItemModelProtocol.swift | 1 - .../Containers/NavigationController.swift | 68 ++++++++++------- .../SubNav/SubNavManagerController.swift | 3 +- 9 files changed, 255 insertions(+), 62 deletions(-) create mode 100644 MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index 2b9c6711..a26f56e5 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -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 */; }; + AF97288627D2BF63009DC250 /* NavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF97288527D2BF63009DC250 /* NavigationBar.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; @@ -855,6 +856,7 @@ AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2CaretLink.swift; sourceTree = ""; }; AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocatorModel.swift; sourceTree = ""; }; AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = ""; }; + AF97288527D2BF63009DC250 /* NavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; @@ -1826,6 +1828,7 @@ children = ( D23EA7FC247EBB7500D60C34 /* Buttons */, D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */, + AF97288527D2BF63009DC250 /* NavigationBar.swift */, ); path = NavigationBar; sourceTree = ""; @@ -2740,6 +2743,7 @@ D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, + AF97288627D2BF63009DC250 /* NavigationBar.swift in Sources */, D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift index fc3e9449..dfd28a86 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift @@ -10,10 +10,46 @@ import Foundation public class TabBarModel: MoleculeModelProtocol { public static var identifier: String = "tabBar" - public var backgroundColor: Color? = Color(uiColor: .white) public var tabs: [TabBarItemModel] - public var selectedColor = Color(uiColor: .mvmBlack) - public var unSelectedColor = Color(uiColor: .mvmCoolGray6) + + open var _backgroundColor: Color? + open var backgroundColor: Color? { + get { + if let backgroundColor = _backgroundColor { return backgroundColor } + if let style = style, + style == .dark { return Color(uiColor: .mvmBlack) } + return Color(uiColor: .mvmWhite) + } + set { + _backgroundColor = newValue + } + } + + open var _selectedColor: Color? + open var selectedColor: Color { + get { + if let selectedColor = _selectedColor { return selectedColor } + if let style = style, + style == .dark { return Color(uiColor: .mvmWhite) } + return Color(uiColor: .mvmBlack) + } + set { + _selectedColor = newValue + } + } + + open var _unSelectedColor: Color? + open var unSelectedColor: Color { + get { + if let unselectedColor = _unSelectedColor { return unselectedColor } + return Color(uiColor: .mvmCoolGray6) + } + set { + _unSelectedColor = newValue + } + } + + public var style: NavigationItemStyle? = NavigationItemStyle.dark // Must be capped to 0...(tabs.count - 1) public var selectedTab: Int = 0 @@ -25,6 +61,7 @@ public class TabBarModel: MoleculeModelProtocol { case selectedColor case unSelectedColor case selectedTab + case style } public init(with tabs: [TabBarItemModel]) { @@ -46,16 +83,20 @@ public class TabBarModel: MoleculeModelProtocol { if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedTab) { selectedTab = index } + if let style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) { + self.style = style + } } public func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) - try container.encode(backgroundColor, forKey: .backgroundColor) - try container.encode(selectedColor, forKey: .selectedColor) - try container.encode(unSelectedColor, forKey: .unSelectedColor) + try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(_selectedColor, forKey: .selectedColor) + try container.encodeIfPresent(_unSelectedColor, forKey: .unSelectedColor) try container.encode(selectedTab, forKey: .selectedTab) + try container.encodeIfPresent(style, forKey: .style) } } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift index 5802ddf8..b433d831 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/Tabs.swift @@ -152,8 +152,7 @@ import UIKit self.delegateObject = delegateObject self.additionalData = additionalData selectedIndex = tabsModel?.selectedIndex ?? 0 - // TODO: Commented out until we have model support for bar color. Should also do unselected color. - //selectionLine.backgroundColor = tabsModel?.selectedColor.uiColor + selectionLine.backgroundColor = tabsModel?.selectedBarColor.uiColor reloadData() } } @@ -333,7 +332,7 @@ extension Tabs { if selected { label.textColor = tabsModel?.selectedColor.uiColor ?? .black } else { - label.textColor = .mvmCoolGray6 + label.textColor = tabsModel?.unselectedColor.uiColor ?? .mvmCoolGray6 } updateAccessibility(indexPath: indexPath, selected: selected, tabsModel: tabsModel) } diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index 398d7c59..b05b6b76 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -10,19 +10,72 @@ import UIKit public class TabsModel: MoleculeModelProtocol { public static var identifier: String = "tabs" - public var backgroundColor: Color? public var tabs: [TabItemModel] - public var selectedColor = Color(uiColor: .black) + + open var style: NavigationItemStyle? = .dark + + open var _backgroundColor: Color? + open var backgroundColor: Color? { + get { + if let backgroundColor = _backgroundColor { return backgroundColor } + if let style = style, + style == .dark { return Color(uiColor: .mvmBlack) } + return Color(uiColor: .mvmWhite) + } + set { + _backgroundColor = newValue + } + } + + open var _selectedColor: Color? + open var selectedColor: Color { + get { + if let selectedColor = _selectedColor { return selectedColor } + if let style = style, + style == .dark { return Color(uiColor: .mvmWhite) } + return Color(uiColor: .mvmBlack) + } + set { + _selectedColor = newValue + } + } + + open var _unselectedColor: Color? + open var unselectedColor: Color { + get { + if let unselectedColor = _unselectedColor { return unselectedColor } + return Color(uiColor: .mvmCoolGray6) + } + set { + _unselectedColor = newValue + } + } + + open var _selectedBarColor: Color? + open var selectedBarColor: Color { + get { + if let selectedBarColor = _selectedBarColor { return selectedBarColor } + if let style = style, + style == .dark { return Color(uiColor: .mvmWhite) } + return Color(uiColor: .mvmRed) + } + set { + _selectedBarColor = newValue + } + } // Must be capped to 0...(tabs.count - 1) public var selectedIndex: Int = 0 private enum CodingKeys: String, CodingKey { + case moleculeName case tabs case backgroundColor case selectedColor + case unselectedColor + case selectedBarColor case selectedIndex - case moleculeName + case style } public init(with tabs: [TabItemModel]) { @@ -33,8 +86,11 @@ public class TabsModel: MoleculeModelProtocol { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) tabs = try typeContainer.decode([TabItemModel].self, forKey: .tabs) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) - if let color = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) { - selectedColor = color + _selectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) + _unselectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .unselectedColor) + _selectedBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedBarColor) + if let style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) { + self.style = style } if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) { selectedIndex = index @@ -45,9 +101,12 @@ public class TabsModel: MoleculeModelProtocol { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) - try container.encode(backgroundColor, forKey: .backgroundColor) - try container.encode(selectedColor, forKey: .selectedColor) + try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(_selectedColor, forKey: .selectedColor) + try container.encodeIfPresent(_unselectedColor, forKey: .unselectedColor) + try container.encodeIfPresent(_selectedBarColor, forKey: .selectedBarColor) try container.encode(selectedIndex, forKey: .selectedIndex) + try container.encodeIfPresent(style, forKey: .style) } } diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift new file mode 100644 index 00000000..72fb697e --- /dev/null +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift @@ -0,0 +1,39 @@ +// +// NavigationBar.swift +// MVMCoreUI +// +// Created by Scott Pfeil on 3/4/22. +// Copyright © 2022 Verizon Wireless. All rights reserved. +// + +import UIKit + +open class NavigationBar: UINavigationBar, MoleculeViewProtocol { + + public var line: Line = Line(model: LineModel(type: .standard), nil, nil) + + public required init?(coder: NSCoder) { + super.init(coder: coder) + setupView() + } + + public override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + + open func setupView() { + line.addLine(to: self, edge: .bottom, useMargin: false) + reset() + } + + public func reset() { + set(with: NavigationItemModel(), nil, nil) + } + + open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { + guard let model = model as? NavigationItemModel else { return } + NavigationController.setNavigation(bar: self, model: model) + line.setOptional(with: model.line, delegateObject, additionalData) + } +} diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index d8126508..90a34079 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -6,6 +6,10 @@ // Copyright © 2020 Verizon Wireless. All rights reserved. // +public enum NavigationItemStyle: String, Codable { + case light + case dark +} open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtocol { //-------------------------------------------------- @@ -14,12 +18,39 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc open class var identifier: String { "navigationBar" } + private let defaultHidesSystemBackButton = true + open var title: String? - open var hidden: Bool - open var backgroundColor: Color? - open var tintColor: Color - open var line: LineModel? + open var hidden = false + open var line = LineModel(type: .standard) open var hidesSystemBackButton = true + open var style: NavigationItemStyle? = .dark + + open var _backgroundColor: Color? + open var backgroundColor: Color? { + get { + if let backgroundColor = _backgroundColor { return backgroundColor } + if let style = style, + style == .dark { return Color(uiColor: .mvmBlack) } + return Color(uiColor: .mvmWhite) + } + set { + _backgroundColor = newValue + } + } + + open var _tintColor: Color? + open var tintColor: Color { + get { + if let tintColor = _tintColor { return tintColor } + if let style = style, + style == .dark { return Color(uiColor: .mvmWhite) } + return Color(uiColor: .mvmBlack) + } + set { + _tintColor = newValue + } + } /// If true, we add the button in the backButton property. If false we do not add the button. If nil, we add the button if the controller is not the bottom of the stack open var alwaysShowBackButton: Bool? @@ -33,12 +64,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc // MARK: - Initializer //-------------------------------------------------- - public init() { - hidden = false - backgroundColor = Color(uiColor: .mvmWhite) - tintColor = Color(uiColor: .mvmBlack) - line = LineModel(type: .standard) - } + public init() {} //-------------------------------------------------- // MARK: - Keys @@ -57,6 +83,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc case additionalLeftButtons case additionalRightButtons case titleView + case style } //-------------------------------------------------- @@ -66,16 +93,25 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc required public init(from decoder: Decoder) throws { let typeContainer = try decoder.container(keyedBy: CodingKeys.self) title = try typeContainer.decodeIfPresent(String.self, forKey: .title) - hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) ?? false - backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) ?? Color(uiColor: .mvmWhite) - tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) ?? Color(uiColor: .mvmBlack) - line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) ?? LineModel(type: .standard) - hidesSystemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidesSystemBackButton) ?? true + if let hidden = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidden) { + self.hidden = hidden + } + backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) + _tintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .tintColor) + if let line = try typeContainer.decodeIfPresent(LineModel.self, forKey: .line) { + self.line = line + } + if let hidesSystemBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .hidesSystemBackButton) { + self.hidesSystemBackButton = hidesSystemBackButton + } alwaysShowBackButton = try typeContainer.decodeIfPresent(Bool.self, forKey: .alwaysShowBackButton) backButton = try typeContainer.decodeModelIfPresent(codingKey: .backButton) additionalLeftButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalLeftButtons) additionalRightButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalRightButtons) titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView) + if let style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) { + self.style = style + } } open func encode(to encoder: Encoder) throws { @@ -83,8 +119,8 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc try container.encode(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(title, forKey: .title) try container.encode(hidden, forKey: .hidden) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) - try container.encode(tintColor, forKey: .tintColor) + try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(_tintColor, forKey: .tintColor) try container.encodeIfPresent(line, forKey: .line) try container.encode(hidesSystemBackButton, forKey: .hidesSystemBackButton) try container.encodeIfPresent(alwaysShowBackButton, forKey: .alwaysShowBackButton) @@ -92,6 +128,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc try container.encodeModelsIfPresent(additionalLeftButtons, forKey: .additionalLeftButtons) try container.encodeModelsIfPresent(additionalRightButtons, forKey: .additionalRightButtons) try container.encodeModelIfPresent(titleView, forKey: .titleView) + try container.encodeIfPresent(style, forKey: .style) } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift index 8f82c946..570581e5 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift @@ -13,7 +13,6 @@ public protocol NavigationItemModelProtocol { var hidden: Bool { get set } var backgroundColor: Color? { get set } var tintColor: Color { get set } - var line: LineModel? { get set } var hidesSystemBackButton: Bool { get set } var alwaysShowBackButton: Bool? { get set } var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)? { get set } diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index c2b63a6e..c7d461d5 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -9,28 +9,22 @@ import UIKit @objcMembers open class NavigationController: UINavigationController, MVMCoreViewManagerViewControllerProtocol { - public var separatorView: Line? public weak var manager: (UIViewController & MVMCoreViewManagerProtocol)? + /// TODO: Remove after removing legacy connections. + public var separatorView: Line? { + get { + return (navigationBar as? NavigationBar)?.line + } + } /// 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) + public static func setupNavigationController() -> NavigationController { + let navigationController = NavigationController(navigationBarClass: NavigationBar.self, toolbarClass: nil) MVMCoreUISession.sharedGlobal()?.navigationController = navigationController MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController MVMCoreNavigationHandler.shared()?.navigationController = navigationController @@ -39,8 +33,8 @@ import UIKit } /// Sets up the application with a navigation controller as the main container. - public static func setupNavigationControllerAsMainController() -> Self? { - guard let navigationController = setupNavigationController() else { return nil } + public static func setupNavigationControllerAsMainController() -> NavigationController { + let navigationController = setupNavigationController() MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController) return navigationController } @@ -84,18 +78,38 @@ import UIKit /// Convenience function for setting the navigation bar ui, except for the buttons. public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) { + let navigationBar = navigationController.navigationBar + if let model = navigationItemModel as? NavigationItemModelProtocol & MoleculeModelProtocol, + let navigationBar = navigationBar as? MoleculeViewProtocol { + navigationBar.set(with: model, nil, nil) + } else { + setNavigation(bar: navigationController.navigationBar, model: navigationItemModel) + } 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 settin the navigation bar by the model + public static func setNavigation(bar: UINavigationBar, model: NavigationItemModelProtocol) { + let font = MFStyler.fontBoldBodySmall(false) + let backgroundColor = model.backgroundColor?.uiColor + let tint = model.tintColor.uiColor + bar.tintColor = tint + if #available(iOS 13.0, *) { + let appearance = UINavigationBarAppearance() + appearance.configureWithOpaqueBackground() + appearance.titleTextAttributes = [NSAttributedString.Key.font: font, + NSAttributedString.Key.foregroundColor: tint]; + appearance.backgroundColor = backgroundColor + appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) + bar.standardAppearance = appearance + bar.scrollEdgeAppearance = appearance + } else { + // Fallback on earlier versions + bar.shadowImage = UIImage() + bar.isOpaque = true + bar.titleTextAttributes = [NSAttributedString.Key.font: font, + NSAttributedString.Key.foregroundColor: tint]; + bar.barTintColor = backgroundColor } } diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 19a8c4fd..bab0d7af 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -119,7 +119,8 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, /// Hides the navigation bar for the page. open func hideNavigationBarLine(for viewController: UIViewController) { - (viewController as? PageProtocol)?.pageModel?.navigationBar?.line?.type = .none + guard let navigationBar = navigationController?.navigationBar as? NavigationBar else { return } + navigationBar.isHidden = true } open override func updateViews() { From a03965cafe5cc6c1b4682b7ba6523d6d358bba57 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 9 Mar 2022 00:07:31 -0500 Subject: [PATCH 02/19] nav line hide for subnav --- .../Containers/NavigationController.swift | 2 +- .../SubNav/SubNavManagerController.swift | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index c7d461d5..c5d84d22 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -88,7 +88,7 @@ import UIKit navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) } - /// Convenience function for settin the navigation bar by the model + /// Convenience function for setting the navigation bar by the model public static func setNavigation(bar: UINavigationBar, model: NavigationItemModelProtocol) { let font = MFStyler.fontBoldBodySmall(false) let backgroundColor = model.backgroundColor?.uiColor diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 77ffa97a..2bcd2597 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -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,17 +110,22 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, } } + open override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + hideNavigationBarLine(true) + } + open override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - + hideNavigationBarLine(false) // Notify showing view we will disappear. (viewController as? MVMCoreViewManagerViewControllerProtocol)?.managerWillDisappear?(self) } - /// Hides the navigation bar for the page. - open func hideNavigationBarLine(for viewController: UIViewController) { + /// Hides/Shows the navigation bar for the page. + open func hideNavigationBarLine(_ isHidden: Bool) { guard let navigationBar = navigationController?.navigationBar as? NavigationBar else { return } - navigationBar.isHidden = true + navigationBar.line.isHidden = isHidden } open override func updateViews() { @@ -214,7 +218,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) } @@ -298,14 +301,10 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, } open func newDataReceived(in viewController: UIViewController) { - if viewController == self.viewController { - hideNavigationBarLine(for: viewController) - } manager?.newDataReceived?(in: viewController) } public func willDisplay(_ viewController: UIViewController) { - hideNavigationBarLine(for: viewController) manager?.willDisplay?(viewController) } From 44a57ab96e764c5e1af5c231dcfed6c081b0541d Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 9 Mar 2022 00:10:31 -0500 Subject: [PATCH 03/19] name update --- .../NavigationBar/NavigationBar.swift | 2 +- .../Containers/NavigationController.swift | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift index 72fb697e..af748539 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift @@ -33,7 +33,7 @@ open class NavigationBar: UINavigationBar, MoleculeViewProtocol { open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { guard let model = model as? NavigationItemModel else { return } - NavigationController.setNavigation(bar: self, model: model) + NavigationController.set(navigationBar: self, model: model) line.setOptional(with: model.line, delegateObject, additionalData) } } diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index c5d84d22..630edbca 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -83,17 +83,17 @@ import UIKit let navigationBar = navigationBar as? MoleculeViewProtocol { navigationBar.set(with: model, nil, nil) } else { - setNavigation(bar: navigationController.navigationBar, model: navigationItemModel) + set(navigationBar: navigationController.navigationBar, model: navigationItemModel) } navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) } /// Convenience function for setting the navigation bar by the model - public static func setNavigation(bar: UINavigationBar, model: NavigationItemModelProtocol) { + public static func set(navigationBar: UINavigationBar, model: NavigationItemModelProtocol) { let font = MFStyler.fontBoldBodySmall(false) let backgroundColor = model.backgroundColor?.uiColor let tint = model.tintColor.uiColor - bar.tintColor = tint + navigationBar.tintColor = tint if #available(iOS 13.0, *) { let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() @@ -101,15 +101,15 @@ import UIKit NSAttributedString.Key.foregroundColor: tint]; appearance.backgroundColor = backgroundColor appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) - bar.standardAppearance = appearance - bar.scrollEdgeAppearance = appearance + navigationBar.standardAppearance = appearance + navigationBar.scrollEdgeAppearance = appearance } else { // Fallback on earlier versions - bar.shadowImage = UIImage() - bar.isOpaque = true - bar.titleTextAttributes = [NSAttributedString.Key.font: font, + navigationBar.shadowImage = UIImage() + navigationBar.isOpaque = true + navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: tint]; - bar.barTintColor = backgroundColor + navigationBar.barTintColor = backgroundColor } } From a1f9e4babea9a13e2d019a555cce127ebbb7f6ca Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 9 Mar 2022 12:07:33 -0500 Subject: [PATCH 04/19] remove testing default --- .../Molecules/HorizontalCombinationViews/TabBarModel.swift | 2 +- .../Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift | 2 +- .../Atomic/Molecules/NavigationBar/NavigationItemModel.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift index dfd28a86..31eb28bc 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift @@ -49,7 +49,7 @@ public class TabBarModel: MoleculeModelProtocol { } } - public var style: NavigationItemStyle? = NavigationItemStyle.dark + public var style: NavigationItemStyle? // Must be capped to 0...(tabs.count - 1) public var selectedTab: Int = 0 diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index b2d46ec6..f624c478 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -12,7 +12,7 @@ public class TabsModel: MoleculeModelProtocol { public static var identifier: String = "tabs" public var tabs: [TabItemModel] - open var style: NavigationItemStyle? = .dark + open var style: NavigationItemStyle? open var _backgroundColor: Color? open var backgroundColor: Color? { diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index 90a34079..5bf73caa 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -24,7 +24,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc open var hidden = false open var line = LineModel(type: .standard) open var hidesSystemBackButton = true - open var style: NavigationItemStyle? = .dark + open var style: NavigationItemStyle? open var _backgroundColor: Color? open var backgroundColor: Color? { From 9f574e854b45979487115c9119a08f8a7aefb7d7 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 9 Mar 2022 12:18:49 -0500 Subject: [PATCH 05/19] change access level --- .../TabBarModel.swift | 28 +++++++++---------- .../TabsModel.swift | 28 +++++++++---------- .../NavigationBar/NavigationItemModel.swift | 4 +-- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift index 31eb28bc..ef36e04b 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift @@ -8,11 +8,11 @@ import Foundation -public class TabBarModel: MoleculeModelProtocol { +open class TabBarModel: MoleculeModelProtocol { public static var identifier: String = "tabBar" - public var tabs: [TabBarItemModel] + open var tabs: [TabBarItemModel] - open var _backgroundColor: Color? + private var _backgroundColor: Color? open var backgroundColor: Color? { get { if let backgroundColor = _backgroundColor { return backgroundColor } @@ -25,7 +25,7 @@ public class TabBarModel: MoleculeModelProtocol { } } - open var _selectedColor: Color? + private var _selectedColor: Color? open var selectedColor: Color { get { if let selectedColor = _selectedColor { return selectedColor } @@ -38,7 +38,7 @@ public class TabBarModel: MoleculeModelProtocol { } } - open var _unSelectedColor: Color? + private var _unSelectedColor: Color? open var unSelectedColor: Color { get { if let unselectedColor = _unSelectedColor { return unselectedColor } @@ -49,10 +49,10 @@ public class TabBarModel: MoleculeModelProtocol { } } - public var style: NavigationItemStyle? + open var style: NavigationItemStyle? // Must be capped to 0...(tabs.count - 1) - public var selectedTab: Int = 0 + open var selectedTab: Int = 0 private enum CodingKeys: String, CodingKey { case moleculeName @@ -88,7 +88,7 @@ public class TabBarModel: MoleculeModelProtocol { } } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) @@ -100,11 +100,11 @@ public class TabBarModel: MoleculeModelProtocol { } } -public class TabBarItemModel: Codable { - var title: String? - var image: String - var action: ActionModelProtocol - var accessibilityText: String? +open class TabBarItemModel: Codable { + open var title: String? + open var image: String + open var action: ActionModelProtocol + open var accessibilityText: String? private enum CodingKeys: String, CodingKey { case title @@ -127,7 +127,7 @@ public class TabBarItemModel: Codable { accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(title, forKey: .title) try container.encode(image, forKey: .image) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index f624c478..122c0763 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -8,13 +8,13 @@ import UIKit -public class TabsModel: MoleculeModelProtocol { +open class TabsModel: MoleculeModelProtocol { public static var identifier: String = "tabs" - public var tabs: [TabItemModel] + open var tabs: [TabItemModel] open var style: NavigationItemStyle? - open var _backgroundColor: Color? + private var _backgroundColor: Color? open var backgroundColor: Color? { get { if let backgroundColor = _backgroundColor { return backgroundColor } @@ -27,7 +27,7 @@ public class TabsModel: MoleculeModelProtocol { } } - open var _selectedColor: Color? + private var _selectedColor: Color? open var selectedColor: Color { get { if let selectedColor = _selectedColor { return selectedColor } @@ -40,7 +40,7 @@ public class TabsModel: MoleculeModelProtocol { } } - open var _unselectedColor: Color? + private var _unselectedColor: Color? open var unselectedColor: Color { get { if let unselectedColor = _unselectedColor { return unselectedColor } @@ -51,7 +51,7 @@ public class TabsModel: MoleculeModelProtocol { } } - open var _selectedBarColor: Color? + private var _selectedBarColor: Color? open var selectedBarColor: Color { get { if let selectedBarColor = _selectedBarColor { return selectedBarColor } @@ -65,7 +65,7 @@ public class TabsModel: MoleculeModelProtocol { } // Must be capped to 0...(tabs.count - 1) - public var selectedIndex: Int = 0 + open var selectedIndex: Int = 0 private enum CodingKeys: String, CodingKey { case moleculeName @@ -97,7 +97,7 @@ public class TabsModel: MoleculeModelProtocol { } } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(moleculeName, forKey: .moleculeName) try container.encode(tabs, forKey: .tabs) @@ -112,11 +112,11 @@ public class TabsModel: MoleculeModelProtocol { -public class TabItemModel: Codable { - public var label: LabelModel - public var action: ActionModelProtocol? +open class TabItemModel: Codable { + open var label: LabelModel + open var action: ActionModelProtocol? - init(label: LabelModel) { + public init(label: LabelModel) { self.label = label } @@ -125,7 +125,7 @@ public class TabItemModel: Codable { case action } - func setDefaults() { + open func setDefaults() { if label.textAlignment == nil { label.textAlignment = .center } @@ -144,7 +144,7 @@ public class TabItemModel: Codable { setDefaults() } - public func encode(to encoder: Encoder) throws { + open func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeModel(label, forKey: .label) try container.encodeModelIfPresent(action, forKey: .action) diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index 5bf73caa..ac73ff18 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -26,7 +26,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc open var hidesSystemBackButton = true open var style: NavigationItemStyle? - open var _backgroundColor: Color? + private var _backgroundColor: Color? open var backgroundColor: Color? { get { if let backgroundColor = _backgroundColor { return backgroundColor } @@ -39,7 +39,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc } } - open var _tintColor: Color? + private var _tintColor: Color? open var tintColor: Color { get { if let tintColor = _tintColor { return tintColor } From c4c513250c5adf229adfab6023a2f9df7cf4e9c9 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 9 Mar 2022 12:21:25 -0500 Subject: [PATCH 06/19] style push decode --- .../Molecules/HorizontalCombinationViews/TabBarModel.swift | 4 +--- .../Molecules/HorizontalCombinationViews/TabsModel.swift | 4 +--- .../Atomic/Molecules/NavigationBar/NavigationItemModel.swift | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift index ef36e04b..2a55b31e 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabBarModel.swift @@ -83,9 +83,7 @@ open class TabBarModel: MoleculeModelProtocol { if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedTab) { selectedTab = index } - if let style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) { - self.style = style - } + style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) } open func encode(to encoder: Encoder) throws { diff --git a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift index 122c0763..16897c67 100644 --- a/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift +++ b/MVMCoreUI/Atomic/Molecules/HorizontalCombinationViews/TabsModel.swift @@ -89,9 +89,7 @@ open class TabsModel: MoleculeModelProtocol { _selectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedColor) _unselectedColor = try typeContainer.decodeIfPresent(Color.self, forKey: .unselectedColor) _selectedBarColor = try typeContainer.decodeIfPresent(Color.self, forKey: .selectedBarColor) - if let style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) { - self.style = style - } + style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) if let index = try typeContainer.decodeIfPresent(Int.self, forKey: .selectedIndex) { selectedIndex = index } diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index ac73ff18..dc2800b3 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -109,9 +109,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc additionalLeftButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalLeftButtons) additionalRightButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalRightButtons) titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView) - if let style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) { - self.style = style - } + style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) } open func encode(to encoder: Encoder) throws { From 07226731c08cc58783763791acab121ee988d730 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Wed, 9 Mar 2022 17:15:15 -0500 Subject: [PATCH 07/19] Line model contains style logic. Fix for subnav revert custom navigation bar for now --- MVMCoreUI.xcodeproj/project.pbxproj | 4 -- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 59 ++++++---------- MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 39 ++++++++++- .../NavigationBar/NavigationBar.swift | 39 ----------- .../NavigationBar/NavigationItemModel.swift | 2 +- .../NavigationItemModelProtocol.swift | 1 + .../BaseControllers/ViewController.swift | 1 + .../Containers/NavigationController.swift | 70 ++++++++++++------- .../SubNav/SubNavManagerController.swift | 21 ++++-- 9 files changed, 125 insertions(+), 111 deletions(-) delete mode 100644 MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index a26f56e5..2b9c6711 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -272,7 +272,6 @@ 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 */; }; - AF97288627D2BF63009DC250 /* NavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF97288527D2BF63009DC250 /* NavigationBar.swift */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; @@ -856,7 +855,6 @@ AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2CaretLink.swift; sourceTree = ""; }; AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocatorModel.swift; sourceTree = ""; }; AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = ""; }; - AF97288527D2BF63009DC250 /* NavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationBar.swift; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; @@ -1828,7 +1826,6 @@ children = ( D23EA7FC247EBB7500D60C34 /* Buttons */, D20FB164241A5D75004AFC3A /* NavigationItemModel.swift */, - AF97288527D2BF63009DC250 /* NavigationBar.swift */, ); path = NavigationBar; sourceTree = ""; @@ -2743,7 +2740,6 @@ D260106123D0C02A00764D80 /* StackItemModelProtocol.swift in Sources */, 0AE98BAF23FEF956004C5109 /* ExternalLink.swift in Sources */, 012A88C4238D86E600FE3DA1 /* CarouselItemModelProtocol.swift in Sources */, - AF97288627D2BF63009DC250 /* NavigationBar.swift in Sources */, D2E2A9A123E095AB000B42E6 /* ButtonModelProtocol.swift in Sources */, 94C2D9AB23872EB50006CF46 /* LabelAttributeActionModel.swift in Sources */, D22D8395241FB41200D3DF69 /* UIStackView+Extension.swift in Sources */, diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index 22d33b1f..7985ec56 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -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: CGFloat(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 } } diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index 0f67b3f0..a9a29264 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -54,7 +54,39 @@ import UIKit //TODO: use color insted of backgroundColor. Needs server changes // public var color: Color? - public var backgroundColor: Color? + private var _backgroundColor: Color? + public var backgroundColor: Color? { + get { + if let backgroundColor = _backgroundColor { return backgroundColor } + if inverted { return backgroundColor_inverted } + if type == .standard { return Color(uiColor: .mvmCoolGray3) } + return Color(uiColor: .mvmBlack) + } + set { + _backgroundColor = newValue + } + } + + private var _thickness: CGFloat? + public var thickness: CGFloat { + get { + if let thickness = _thickness { return thickness } + switch type { + case .heavy: + return 4 + case .medium: + return 2 + case .none: + return 0 + default: + return 1 + } + } + set { + _thickness = newValue + } + } + public var backgroundColor_inverted: Color = Color(uiColor: .mvmWhite) public var inverted: Bool = false @@ -90,6 +122,7 @@ import UIKit case frequency case inverted case useVerticalLine + case thickness } //-------------------------------------------------- @@ -117,6 +150,7 @@ import UIKit backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) useVerticalLine = try typeContainer.decodeIfPresent(Bool.self, forKey: .useVerticalLine) + _thickness = try typeContainer.decodeIfPresent(CGFloat.self, forKey: .thickness) } public func encode(to encoder: Encoder) throws { @@ -125,8 +159,9 @@ import UIKit try container.encode(type, forKey: .type) try container.encode(inverted, forKey: .inverted) try container.encodeIfPresent(frequency, forKey: .frequency) - try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) + try container.encodeIfPresent(_backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor_inverted, forKey: .backgroundColor_inverted) try container.encodeIfPresent(useVerticalLine, forKey: .useVerticalLine) + try container.encodeIfPresent(_thickness, forKey: .thickness) } } diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift deleted file mode 100644 index af748539..00000000 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationBar.swift +++ /dev/null @@ -1,39 +0,0 @@ -// -// NavigationBar.swift -// MVMCoreUI -// -// Created by Scott Pfeil on 3/4/22. -// Copyright © 2022 Verizon Wireless. All rights reserved. -// - -import UIKit - -open class NavigationBar: UINavigationBar, MoleculeViewProtocol { - - public var line: Line = Line(model: LineModel(type: .standard), nil, nil) - - public required init?(coder: NSCoder) { - super.init(coder: coder) - setupView() - } - - public override init(frame: CGRect) { - super.init(frame: frame) - setupView() - } - - open func setupView() { - line.addLine(to: self, edge: .bottom, useMargin: false) - reset() - } - - public func reset() { - set(with: NavigationItemModel(), nil, nil) - } - - open func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) { - guard let model = model as? NavigationItemModel else { return } - NavigationController.set(navigationBar: self, model: model) - line.setOptional(with: model.line, delegateObject, additionalData) - } -} diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index dc2800b3..b7eaf2d8 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -22,7 +22,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc open var title: String? open var hidden = false - open var line = LineModel(type: .standard) + open var line: LineModel? = LineModel(type: .standard) open var hidesSystemBackButton = true open var style: NavigationItemStyle? diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift index 570581e5..8f82c946 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift @@ -13,6 +13,7 @@ public protocol NavigationItemModelProtocol { var hidden: Bool { get set } var backgroundColor: Color? { get set } var tintColor: Color { get set } + var line: LineModel? { get set } var hidesSystemBackButton: Bool { get set } var alwaysShowBackButton: Bool? { get set } var backButton: (NavigationButtonModelProtocol & MoleculeModelProtocol)? { get set } diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index d7e947db..4a154d3a 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -349,6 +349,7 @@ import UIKit } open func pageShown() { + guard self as? MVMCoreViewManagerProtocol == nil else { return } // Update split view properties if this is the current detail controller. if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() { MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 630edbca..21bc030b 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -10,12 +10,6 @@ import UIKit @objcMembers open class NavigationController: UINavigationController, MVMCoreViewManagerViewControllerProtocol { public weak var manager: (UIViewController & MVMCoreViewManagerProtocol)? - /// TODO: Remove after removing legacy connections. - public var separatorView: Line? { - get { - return (navigationBar as? NavigationBar)?.line - } - } /// Getter for the main navigation controller public static func navigationController() -> Self? { @@ -23,8 +17,8 @@ import UIKit } /// Sets up the application with a navigation controller - public static func setupNavigationController() -> NavigationController { - let navigationController = NavigationController(navigationBarClass: NavigationBar.self, toolbarClass: nil) + public static func setupNavigationController() -> Self? { + let navigationController = self.init() MVMCoreUISession.sharedGlobal()?.navigationController = navigationController MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController MVMCoreNavigationHandler.shared()?.navigationController = navigationController @@ -33,8 +27,8 @@ import UIKit } /// Sets up the application with a navigation controller as the main container. - public static func setupNavigationControllerAsMainController() -> NavigationController { - let navigationController = setupNavigationController() + public static func setupNavigationControllerAsMainController() -> Self? { + guard let navigationController = setupNavigationController() else { return nil } MVMCoreUISession.sharedGlobal()?.setup(asStandardLoadViewDelegate: navigationController) return navigationController } @@ -76,23 +70,39 @@ import UIKit viewController.navigationItem.rightBarButtonItems = rightItems.count > 0 ? rightItems : nil } + static 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)) + } +// let rect = CGRect(origin: .zero, size: size) +// UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) +// color.setFill() +// UIRectFill(rect) +// let image = UIGraphicsGetImageFromCurrentImageContext() +// UIGraphicsEndImageContext() +// +// guard let cgImage = image?.cgImage else { return nil } +// self.init(cgImage: cgImage) +// +//// let pixelScale = UIScreen.main.scale +//// let pixelSize = thickness / pixelScale +//// let fillSize = CGSize(width: pixelSize, height: pixelSize) +//// let fillRect = CGRect(origin: CGPoint.zero, size: fillSize) +//// UIGraphicsBeginImageContextWithOptions(fillRect.size, false, pixelScale) +//// graphicsContext.setFillColor(backgroundColor.cgColor) +//// graphicsContext.fill(fillRect) +//// let image = UIGraphicsGetImageFromCurrentImageContext() +//// UIGraphicsEndImageContext() +// return image +// } + /// Convenience function for setting the navigation bar ui, except for the buttons. public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) { let navigationBar = navigationController.navigationBar - if let model = navigationItemModel as? NavigationItemModelProtocol & MoleculeModelProtocol, - let navigationBar = navigationBar as? MoleculeViewProtocol { - navigationBar.set(with: model, nil, nil) - } else { - set(navigationBar: navigationController.navigationBar, model: navigationItemModel) - } - navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) - } - - /// Convenience function for setting the navigation bar by the model - public static func set(navigationBar: UINavigationBar, model: NavigationItemModelProtocol) { let font = MFStyler.fontBoldBodySmall(false) - let backgroundColor = model.backgroundColor?.uiColor - let tint = model.tintColor.uiColor + let backgroundColor = navigationItemModel.backgroundColor?.uiColor + let tint = navigationItemModel.tintColor.uiColor navigationBar.tintColor = tint if #available(iOS 13.0, *) { let appearance = UINavigationBarAppearance() @@ -101,16 +111,19 @@ import UIKit NSAttributedString.Key.foregroundColor: tint]; appearance.backgroundColor = backgroundColor appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) + appearance.shadowColor = navigationItemModel.line?.backgroundColor?.uiColor ?? .clear + appearance.shadowImage = getNavigationBarShadowImage(for: navigationItemModel)?.withRenderingMode(.alwaysTemplate) navigationBar.standardAppearance = appearance navigationBar.scrollEdgeAppearance = appearance } else { // Fallback on earlier versions - navigationBar.shadowImage = UIImage() navigationBar.isOpaque = true + navigationBar.shadowImage = getNavigationBarShadowImage(for: navigationItemModel) navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: tint]; navigationBar.barTintColor = backgroundColor } + navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) } /// Convenience function for setting the navigation titleView. @@ -213,3 +226,12 @@ extension NavigationController: MVMCorePresentationDelegateProtocol { } } } + +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)) + } + } +} diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 2bcd2597..37a33ca9 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -110,22 +110,29 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, } } - open override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) + open override func pageShown() { + super.pageShown() hideNavigationBarLine(true) } open override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) - hideNavigationBarLine(false) // Notify showing view we will disappear. (viewController as? MVMCoreViewManagerViewControllerProtocol)?.managerWillDisappear?(self) } /// Hides/Shows the navigation bar for the page. open func hideNavigationBarLine(_ isHidden: Bool) { - guard let navigationBar = navigationController?.navigationBar as? NavigationBar else { return } - navigationBar.line.isHidden = isHidden + guard self == navigationController?.topViewController else { return } + if #available(iOS 13.0, *) { + 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() { @@ -257,6 +264,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, if let viewController = getCurrentViewController() { manager?.displayedViewController?(viewController) } + hideNavigationBarLine(true) } // MARK: - TabsDelegate @@ -283,6 +291,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) } @@ -302,6 +311,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, open func newDataReceived(in viewController: UIViewController) { manager?.newDataReceived?(in: viewController) + hideNavigationBarLine(true) } public func willDisplay(_ viewController: UIViewController) { @@ -310,6 +320,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, public func displayedViewController(_ viewController: UIViewController) { manager?.displayedViewController?(viewController) + hideNavigationBarLine(true) } // MARK: - MVMCoreUISwipeNavigationProtocol From f23e30645ea413303c3948d91ffb703da9ab3c62 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 10 Mar 2022 10:05:33 -0500 Subject: [PATCH 08/19] Fix for base style for legacy controllers. (sign in different user font) --- MVMCoreUI/Containers/NavigationController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 21bc030b..6b1e6100 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -23,6 +23,7 @@ import UIKit MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController MVMCoreNavigationHandler.shared()?.navigationController = navigationController MVMCoreNavigationHandler.shared()?.addDelegate(navigationController) + NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: NavigationItemModel()) return navigationController } @@ -98,7 +99,7 @@ import UIKit // } /// Convenience function for setting the navigation bar ui, except for the buttons. - public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol, viewController: UIViewController) { + public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) { let navigationBar = navigationController.navigationBar let font = MFStyler.fontBoldBodySmall(false) let backgroundColor = navigationItemModel.backgroundColor?.uiColor @@ -174,7 +175,7 @@ extension NavigationController: MVMCoreViewManagerProtocol { let topViewController = topViewController, let model = getNavigationModel(from: viewController) { Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: topViewController) - Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: topViewController) + Self.setNavigationBarUI(navigationController: self, navigationItemModel: model) } manager?.newDataReceived?(in: viewController) } @@ -189,9 +190,8 @@ extension NavigationController: MVMCoreViewManagerProtocol { 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) + Self.setNavigationBarUI(navigationController: self, navigationItemModel: model) } manager?.displayedViewController?(viewController) } @@ -218,7 +218,7 @@ extension NavigationController: MVMCorePresentationDelegateProtocol { guard self == navigationController, let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } if let model = getNavigationModel(from: newViewController) { - Self.setNavigationBarUI(navigationController: self, navigationItemModel: model, viewController: viewController) + Self.setNavigationBarUI(navigationController: self, navigationItemModel: model) } manager?.displayedViewController?(newViewController) if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { From ebf97cdbe783108183c8114fddf31807ae88d59a Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 10 Mar 2022 12:37:38 -0500 Subject: [PATCH 09/19] remove iOS 13 check --- .../Containers/NavigationController.swift | 31 +++++++------------ 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 6b1e6100..3682fd6b 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -105,25 +105,18 @@ import UIKit let backgroundColor = navigationItemModel.backgroundColor?.uiColor let tint = navigationItemModel.tintColor.uiColor navigationBar.tintColor = tint - if #available(iOS 13.0, *) { - 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.shadowColor = navigationItemModel.line?.backgroundColor?.uiColor ?? .clear - appearance.shadowImage = getNavigationBarShadowImage(for: navigationItemModel)?.withRenderingMode(.alwaysTemplate) - navigationBar.standardAppearance = appearance - navigationBar.scrollEdgeAppearance = appearance - } else { - // Fallback on earlier versions - navigationBar.isOpaque = true - navigationBar.shadowImage = getNavigationBarShadowImage(for: navigationItemModel) - navigationBar.titleTextAttributes = [NSAttributedString.Key.font: font, - NSAttributedString.Key.foregroundColor: tint]; - navigationBar.barTintColor = backgroundColor - } + + 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.shadowColor = navigationItemModel.line?.backgroundColor?.uiColor ?? .clear + appearance.shadowImage = getNavigationBarShadowImage(for: navigationItemModel)?.withRenderingMode(.alwaysTemplate) + navigationBar.standardAppearance = appearance + navigationBar.scrollEdgeAppearance = appearance + navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) } From 5790fc6febd327f683e820b90a608c004fa858cd Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 10 Mar 2022 12:57:14 -0500 Subject: [PATCH 10/19] line update --- MVMCoreUI/Atomic/Atoms/Views/Line.swift | 2 +- MVMCoreUI/Atomic/Atoms/Views/LineModel.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MVMCoreUI/Atomic/Atoms/Views/Line.swift b/MVMCoreUI/Atomic/Atoms/Views/Line.swift index 7985ec56..76016292 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/Line.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/Line.swift @@ -72,7 +72,7 @@ import UIKit open func setStyle(_ style: LineModel.Style) { lineModel?.type = style backgroundColor = lineModel?.backgroundColor?.uiColor - updateLineConstraints(constant: CGFloat(lineModel?.thickness ?? 1)) + updateLineConstraints(constant: lineModel?.thickness ?? 1) } open func shouldBeVisible() -> Bool { diff --git a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift index a9a29264..a3073f52 100644 --- a/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift +++ b/MVMCoreUI/Atomic/Atoms/Views/LineModel.swift @@ -57,8 +57,8 @@ import UIKit private var _backgroundColor: Color? public var backgroundColor: Color? { get { - if let backgroundColor = _backgroundColor { return backgroundColor } if inverted { return backgroundColor_inverted } + if let backgroundColor = _backgroundColor { return backgroundColor } if type == .standard { return Color(uiColor: .mvmCoolGray3) } return Color(uiColor: .mvmBlack) } From e875002cb17e877026b9cda41f214d54b8e15739 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 10 Mar 2022 13:40:30 -0500 Subject: [PATCH 11/19] remove test code --- .../Containers/NavigationController.swift | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 3682fd6b..7da6e0f6 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -76,27 +76,6 @@ import UIKit let backgroundColor = navigationItemModel.line?.backgroundColor else { return nil } return backgroundColor.uiColor.image(CGSize(width: thickness, height: thickness)) } -// let rect = CGRect(origin: .zero, size: size) -// UIGraphicsBeginImageContextWithOptions(rect.size, false, 0.0) -// color.setFill() -// UIRectFill(rect) -// let image = UIGraphicsGetImageFromCurrentImageContext() -// UIGraphicsEndImageContext() -// -// guard let cgImage = image?.cgImage else { return nil } -// self.init(cgImage: cgImage) -// -//// let pixelScale = UIScreen.main.scale -//// let pixelSize = thickness / pixelScale -//// let fillSize = CGSize(width: pixelSize, height: pixelSize) -//// let fillRect = CGRect(origin: CGPoint.zero, size: fillSize) -//// UIGraphicsBeginImageContextWithOptions(fillRect.size, false, pixelScale) -//// graphicsContext.setFillColor(backgroundColor.cgColor) -//// graphicsContext.fill(fillRect) -//// let image = UIGraphicsGetImageFromCurrentImageContext() -//// UIGraphicsEndImageContext() -// return image -// } /// Convenience function for setting the navigation bar ui, except for the buttons. public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) { From b4d7392675ffe66a20873c0a5d2b77b2b5d7f1f4 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Thu, 10 Mar 2022 13:44:07 -0500 Subject: [PATCH 12/19] remove iOS 13 check --- .../Managers/SubNav/SubNavManagerController.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 37a33ca9..8fbf8d49 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -124,15 +124,13 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, /// Hides/Shows the navigation bar for the page. open func hideNavigationBarLine(_ isHidden: Bool) { guard self == navigationController?.topViewController else { return } - if #available(iOS 13.0, *) { - 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 + 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() { From 5bbacf4de123e28f9493deba226c897e383f132b Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Fri, 11 Mar 2022 15:28:21 -0500 Subject: [PATCH 13/19] Move status bar to the split view for control. Each page can style status bar now, not just top alerts. --- ...MCoreUISplitViewController+Extension.swift | 24 +++ .../MVMCoreUISplitViewController.h | 18 +- .../MVMCoreUISplitViewController.m | 82 +++++---- .../TopAlert/MVMCoreTopAlertViewProtocol.h | 9 +- .../MVMCoreUITopAlertView+Extension.swift | 2 +- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h | 15 -- MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m | 164 ++++++------------ 7 files changed, 149 insertions(+), 165 deletions(-) diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index a4bbcb08..58bb1497 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -7,6 +7,7 @@ // import Foundation +import UIKit // Navigation bar update functions public extension MVMCoreUISplitViewController { @@ -122,6 +123,29 @@ public extension MVMCoreUISplitViewController { navigationController.isDisplayed(viewController: viewController), let model = navigationController.getNavigationModel(from: viewController) else { return } set(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) } } diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h index 9c07374d..db5e9cd9 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.h @@ -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 diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m index e16daa56..5c337072 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController.m @@ -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 *)viewController) defaultStatusBarStyle]) { - return [((UIViewController *)viewController) defaultStatusBarStyle]; - } - return UIStatusBarStyleDefault; -} - -- (UIColor *)getDefaultStatusBarBackgroundColor { - UIViewController *viewController = [self getCurrentDetailViewController]; - if ([viewController conformsToProtocol:@protocol(MVMCoreUIDetailViewProtocol)] - && [viewController respondsToSelector:@selector(defaultStatusBarBackgroundColor)] - && [((UIViewController *)viewController) defaultStatusBarBackgroundColor]) { - return [((UIViewController *)viewController) defaultStatusBarBackgroundColor]; - } - return nil; -} - - (BOOL)isAPanelShowing { return fabs(self.mainViewLeading.constant) > 1; } diff --git a/MVMCoreUI/TopAlert/MVMCoreTopAlertViewProtocol.h b/MVMCoreUI/TopAlert/MVMCoreTopAlertViewProtocol.h index e10cec10..e799e858 100644 --- a/MVMCoreUI/TopAlert/MVMCoreTopAlertViewProtocol.h +++ b/MVMCoreUI/TopAlert/MVMCoreTopAlertViewProtocol.h @@ -13,16 +13,19 @@ @optional -// Show based on the object +/// Show based on the object - (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id )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 diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift index 0328f03c..46765385 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView+Extension.swift @@ -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) }) } diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h index 5bb033d7..fad65957 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.h @@ -19,8 +19,6 @@ @interface MVMCoreUITopAlertView : UIView -@property (nonatomic, readonly) UIStatusBarStyle statusBarStyle; - // Delegate for the top alert view @property (nonatomic, nullable, weak) id 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 )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 diff --git a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m index eba4cfcc..c0835541 100644 --- a/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m +++ b/MVMCoreUI/TopAlert/MVMCoreUITopAlertView.m @@ -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 )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 *)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 )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 *)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 From 558e1803e548d68d83b9b1d9f9fa6d554bacc564 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 14 Mar 2022 11:31:53 -0400 Subject: [PATCH 14/19] title offset and default for 3 dot O --- .../Atomic/Molecules/NavigationBar/NavigationItemModel.swift | 4 ++++ .../ModelProtocols/NavigationItemModelProtocol.swift | 1 + MVMCoreUI/Containers/NavigationController.swift | 1 + 3 files changed, 6 insertions(+) diff --git a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift index b7eaf2d8..574107d6 100644 --- a/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift +++ b/MVMCoreUI/Atomic/Molecules/NavigationBar/NavigationItemModel.swift @@ -59,6 +59,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc open var additionalLeftButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? open var additionalRightButtons: [(NavigationButtonModelProtocol & MoleculeModelProtocol)]? open var titleView: MoleculeModelProtocol? + open var titleOffset: UIOffset? //-------------------------------------------------- // MARK: - Initializer @@ -84,6 +85,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc case additionalRightButtons case titleView case style + case titleOffset } //-------------------------------------------------- @@ -110,6 +112,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc additionalRightButtons = try typeContainer.decodeModelsIfPresent(codingKey: .additionalRightButtons) titleView = try typeContainer.decodeModelIfPresent(codingKey: .titleView) style = try typeContainer.decodeIfPresent(NavigationItemStyle.self, forKey: .style) + titleOffset = try typeContainer.decodeIfPresent(UIOffset.self, forKey: .titleOffset) ?? UIOffset(horizontal: -CGFloat.greatestFiniteMagnitude, vertical: 0) } open func encode(to encoder: Encoder) throws { @@ -127,6 +130,7 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc try container.encodeModelsIfPresent(additionalRightButtons, forKey: .additionalRightButtons) try container.encodeModelIfPresent(titleView, forKey: .titleView) try container.encodeIfPresent(style, forKey: .style) + try container.encodeIfPresent(titleOffset, forKey: .titleOffset) } } diff --git a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift index 8f82c946..b9fb111a 100644 --- a/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift +++ b/MVMCoreUI/Atomic/Protocols/ModelProtocols/NavigationItemModelProtocol.swift @@ -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 } } diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController.swift index 7da6e0f6..f369d118 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController.swift @@ -91,6 +91,7 @@ import UIKit NSAttributedString.Key.foregroundColor: tint]; appearance.backgroundColor = backgroundColor appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) + appearance.titlePositionAdjustment = navigationItemModel.titleOffset ?? .zero appearance.shadowColor = navigationItemModel.line?.backgroundColor?.uiColor ?? .clear appearance.shadowImage = getNavigationBarShadowImage(for: navigationItemModel)?.withRenderingMode(.alwaysTemplate) navigationBar.standardAppearance = appearance From ea9171c1246ec26d4362052a1277b0fc7b431085 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 14 Mar 2022 13:53:51 -0400 Subject: [PATCH 15/19] remove force manager check --- MVMCoreUI/BaseControllers/ViewController.swift | 1 - MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 1 - 2 files changed, 2 deletions(-) diff --git a/MVMCoreUI/BaseControllers/ViewController.swift b/MVMCoreUI/BaseControllers/ViewController.swift index 4a154d3a..d7e947db 100644 --- a/MVMCoreUI/BaseControllers/ViewController.swift +++ b/MVMCoreUI/BaseControllers/ViewController.swift @@ -349,7 +349,6 @@ import UIKit } open func pageShown() { - guard self as? MVMCoreViewManagerProtocol == nil else { return } // Update split view properties if this is the current detail controller. if self == MVMCoreUISplitViewController.main()?.getCurrentDetailViewController() { MVMCoreUISplitViewController.main()?.setBottomProgressBarProgress(bottomProgress() ?? 0) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 8fbf8d49..57c84e3f 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -111,7 +111,6 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, } open override func pageShown() { - super.pageShown() hideNavigationBarLine(true) } From 09e59d5b31c4ef56ec122f4ca6caf1b5d1db0fa4 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 14 Mar 2022 13:55:39 -0400 Subject: [PATCH 16/19] comment --- MVMCoreUI/Managers/SubNav/SubNavManagerController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift index 57c84e3f..c3be1868 100644 --- a/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift +++ b/MVMCoreUI/Managers/SubNav/SubNavManagerController.swift @@ -111,6 +111,7 @@ open class SubNavManagerController: ViewController, MVMCoreViewManagerProtocol, } open override func pageShown() { + // Currently not calling super until we can decouple page shown logics for managers. hideNavigationBarLine(true) } From b89cc4386734a921d7810140ca77be79e29bb20a Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 14 Mar 2022 14:46:35 -0400 Subject: [PATCH 17/19] Review Comments from static to extension --- MVMCoreUI.xcodeproj/project.pbxproj | 14 ++- .../NavigationController.swift | 87 ++----------------- .../UINavigationController+Extension.swift | 87 +++++++++++++++++++ ...MCoreUISplitViewController+Extension.swift | 15 ++-- 4 files changed, 112 insertions(+), 91 deletions(-) rename MVMCoreUI/Containers/{ => NavigationController}/NavigationController.swift (50%) create mode 100644 MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift diff --git a/MVMCoreUI.xcodeproj/project.pbxproj b/MVMCoreUI.xcodeproj/project.pbxproj index ae49c2b5..dee2e567 100644 --- a/MVMCoreUI.xcodeproj/project.pbxproj +++ b/MVMCoreUI.xcodeproj/project.pbxproj @@ -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 */; }; BB105859248DEFF70069D008 /* UICollectionViewLeftAlignedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */; }; BB1D17E0244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */; }; BB1D17E2244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */; }; @@ -855,6 +856,7 @@ AAE7270D24AC8B9300A3ED0E /* HeadersH2CaretLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2CaretLink.swift; sourceTree = ""; }; AAE96FA125341F6A0037A989 /* ListStoreLocatorModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocatorModel.swift; sourceTree = ""; }; AAE96FA425341F7D0037A989 /* ListStoreLocator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListStoreLocator.swift; sourceTree = ""; }; + AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+Extension.swift"; sourceTree = ""; }; BB105858248DEFF60069D008 /* UICollectionViewLeftAlignedLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UICollectionViewLeftAlignedLayout.swift; sourceTree = ""; }; BB1D17DF244EAA30001D2002 /* ListDeviceComplexButtonMediumModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMediumModel.swift; sourceTree = ""; }; BB1D17E1244EAA46001D2002 /* ListDeviceComplexButtonMedium.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListDeviceComplexButtonMedium.swift; sourceTree = ""; }; @@ -1529,6 +1531,15 @@ path = Miscellaneous; sourceTree = ""; }; + AFE4A1D427DFBB2700C458D0 /* NavigationController */ = { + isa = PBXGroup; + children = ( + D2B18B93236214AD00A9AEDC /* NavigationController.swift */, + AFE4A1D527DFBB6F00C458D0 /* UINavigationController+Extension.swift */, + ); + path = NavigationController; + sourceTree = ""; + }; D202AFE2242A5F1400E5BEDF /* Extensions */ = { isa = PBXGroup; children = ( @@ -2066,9 +2077,9 @@ D29DF11921E68467003B2FB9 /* Containers */ = { isa = PBXGroup; children = ( + AFE4A1D427DFBB2700C458D0 /* NavigationController */, 0ABD1369237B18EE0081388D /* Views */, D29DF2B621E7BE66003B2FB9 /* SplitViewController */, - D2B18B93236214AD00A9AEDC /* NavigationController.swift */, ); path = Containers; sourceTree = ""; @@ -2631,6 +2642,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 */, diff --git a/MVMCoreUI/Containers/NavigationController.swift b/MVMCoreUI/Containers/NavigationController/NavigationController.swift similarity index 50% rename from MVMCoreUI/Containers/NavigationController.swift rename to MVMCoreUI/Containers/NavigationController/NavigationController.swift index 7da6e0f6..03c10595 100644 --- a/MVMCoreUI/Containers/NavigationController.swift +++ b/MVMCoreUI/Containers/NavigationController/NavigationController.swift @@ -23,7 +23,7 @@ import UIKit MVMCoreNavigationHandler.shared()?.viewControllerToPresentOn = navigationController MVMCoreNavigationHandler.shared()?.navigationController = navigationController MVMCoreNavigationHandler.shared()?.addDelegate(navigationController) - NavigationController.setNavigationBarUI(navigationController: navigationController, navigationItemModel: NavigationItemModel()) + navigationController.setNavigationBarUI(with: NavigationItemModel()) return navigationController } @@ -34,79 +34,6 @@ import UIKit 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 - } - - static 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, except for the buttons. - public static func setNavigationBarUI(navigationController: UINavigationController, navigationItemModel: NavigationItemModelProtocol) { - let navigationBar = navigationController.navigationBar - let font = MFStyler.fontBoldBodySmall(false) - let backgroundColor = navigationItemModel.backgroundColor?.uiColor - let tint = navigationItemModel.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.shadowColor = navigationItemModel.line?.backgroundColor?.uiColor ?? .clear - appearance.shadowImage = getNavigationBarShadowImage(for: navigationItemModel)?.withRenderingMode(.alwaysTemplate) - navigationBar.standardAppearance = appearance - navigationBar.scrollEdgeAppearance = appearance - - navigationController.setNavigationBarHidden(navigationItemModel.hidden, animated: true) - } - - /// 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 @@ -146,8 +73,8 @@ extension NavigationController: MVMCoreViewManagerProtocol { 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) + setNavigationItem(with: model, for: topViewController) + setNavigationBarUI(with: model) } manager?.newDataReceived?(in: viewController) } @@ -155,7 +82,7 @@ extension NavigationController: MVMCoreViewManagerProtocol { public func willDisplay(_ viewController: UIViewController) { if let topViewController = topViewController, let model = getNavigationModel(from: viewController) { - Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: topViewController) + setNavigationItem(with: model, for: topViewController) } manager?.willDisplay?(viewController) } @@ -163,7 +90,7 @@ extension NavigationController: MVMCoreViewManagerProtocol { public func displayedViewController(_ viewController: UIViewController) { if isDisplayed(viewController: viewController), let model = getNavigationModel(from: viewController) { - Self.setNavigationBarUI(navigationController: self, navigationItemModel: model) + setNavigationBarUI(with: model) } manager?.displayedViewController?(viewController) } @@ -174,7 +101,7 @@ extension NavigationController: MVMCorePresentationDelegateProtocol { guard self == navigationController, let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController), let model = getNavigationModel(from: newViewController) else { return } - Self.setNavigationItem(navigationController: self, navigationItemModel: model, viewController: viewController) + setNavigationItem(with: model, for: viewController) } public func navigationController(_ navigationController: UINavigationController, willDisplay viewController: UIViewController) { @@ -190,7 +117,7 @@ extension NavigationController: MVMCorePresentationDelegateProtocol { guard self == navigationController, let newViewController = MVMCoreUIUtility.getViewControllerTraversingManagers(viewController) else { return } if let model = getNavigationModel(from: newViewController) { - Self.setNavigationBarUI(navigationController: self, navigationItemModel: model) + setNavigationBarUI(with: model) } manager?.displayedViewController?(newViewController) if let controller = viewController as? (UIViewController & MVMCoreViewManagerViewControllerProtocol) { diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift new file mode 100644 index 00000000..32de0bdf --- /dev/null +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -0,0 +1,87 @@ +// +// 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.shadowColor = model.line?.backgroundColor?.uiColor ?? .clear + appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate) + navigationBar.standardAppearance = appearance + navigationBar.scrollEdgeAppearance = appearance + + setNavigationBarHidden(model.hidden, animated: true) + } +} diff --git a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift index a4bbcb08..c46a6bb6 100644 --- a/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift +++ b/MVMCoreUI/Containers/SplitViewController/MVMCoreUISplitViewController+Extension.swift @@ -12,18 +12,13 @@ import Foundation 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 +116,7 @@ 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) } } From f198add1f6099f7e69f29bec678c705eb8990688 Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 14 Mar 2022 17:06:09 -0400 Subject: [PATCH 18/19] move to extension --- .../NavigationController/UINavigationController+Extension.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index 32de0bdf..e4d5898a 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -77,6 +77,7 @@ public extension UINavigationController { NSAttributedString.Key.foregroundColor: tint]; appearance.backgroundColor = backgroundColor appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) + appearance.titlePositionAdjustment = navigationItemModel.titleOffset ?? .zero appearance.shadowColor = model.line?.backgroundColor?.uiColor ?? .clear appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate) navigationBar.standardAppearance = appearance From 8df6baf6b4fd3c206ede6c2819d45350a93be0cc Mon Sep 17 00:00:00 2001 From: Scott Pfeil Date: Mon, 14 Mar 2022 17:06:33 -0400 Subject: [PATCH 19/19] move to extension --- .../NavigationController/UINavigationController+Extension.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift index e4d5898a..ea5003f4 100644 --- a/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift +++ b/MVMCoreUI/Containers/NavigationController/UINavigationController+Extension.swift @@ -77,7 +77,7 @@ public extension UINavigationController { NSAttributedString.Key.foregroundColor: tint]; appearance.backgroundColor = backgroundColor appearance.titleTextAttributes.updateValue(tint, forKey: .foregroundColor) - appearance.titlePositionAdjustment = navigationItemModel.titleOffset ?? .zero + appearance.titlePositionAdjustment = model.titleOffset ?? .zero appearance.shadowColor = model.line?.backgroundColor?.uiColor ?? .clear appearance.shadowImage = getNavigationBarShadowImage(for: model)?.withRenderingMode(.alwaysTemplate) navigationBar.standardAppearance = appearance