Audio player behavior

This commit is contained in:
Christiano, Kevin 2021-07-20 06:10:17 +00:00 committed by Pfeil, Scott Robert
parent d9e2593de2
commit f56bc4b894
23 changed files with 146 additions and 97 deletions

View File

@ -124,7 +124,7 @@ import MVMCore
didSet { didSet {
if !updateSelectionOnly { if !updateSelectionOnly {
layoutIfNeeded() layoutIfNeeded()
(model as? CheckboxModel)?.checked = isSelected (model as? CheckboxModel)?.selected = isSelected
shapeLayer?.removeAllAnimations() shapeLayer?.removeAllAnimations()
updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated) updateCheckboxUI(isSelected: isSelected, isAnimated: isAnimated)
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
@ -419,8 +419,8 @@ import MVMCore
isAnimated = model.animated isAnimated = model.animated
isRound = model.round isRound = model.round
if model.checked { if model.selected {
checkAndBypassAnimations(selected: model.checked) checkAndBypassAnimations(selected: model.selected)
} }
isEnabled = model.enabled isEnabled = model.enabled

View File

@ -6,10 +6,14 @@
// Copyright © 2020 Verizon Wireless. All rights reserved. // Copyright © 2020 Verizon Wireless. All rights reserved.
// //
import Foundation /// Protocol to apply to any model of a UI Control with a binary on/off nature.
///
/// Example classes: Checkbox or Toggle.
@objc public protocol SelectableMoleculeModelProtocol {
var selected: Bool { get set }
}
@objcMembers public class CheckboxModel: MoleculeModelProtocol, SelectableMoleculeModelProtocol, FormFieldProtocol {
@objcMembers public class CheckboxModel: MoleculeModelProtocol, FormFieldProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -17,7 +21,7 @@ import Foundation
public static var identifier: String = "checkbox" public static var identifier: String = "checkbox"
public var backgroundColor: Color? public var backgroundColor: Color?
public var accessibilityIdentifier: String? public var accessibilityIdentifier: String?
public var checked: Bool = false public var selected: Bool = false
public var enabled: Bool = true public var enabled: Bool = true
public var animated: Bool = true public var animated: Bool = true
public var inverted: Bool = false public var inverted: Bool = false
@ -68,17 +72,17 @@ import Foundation
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Form Validation
//-------------------------------------------------- //--------------------------------------------------
public func formFieldValue() -> AnyHashable? { checked } public func formFieldValue() -> AnyHashable? { selected }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(isChecked: Bool = false) { public init(isChecked: Bool = false) {
self.checked = isChecked self.selected = isChecked
baseValue = isChecked baseValue = isChecked
} }
@ -132,10 +136,10 @@ import Foundation
} }
if let checked = try typeContainer.decodeIfPresent(Bool.self, forKey: .checked) { if let checked = try typeContainer.decodeIfPresent(Bool.self, forKey: .checked) {
self.checked = checked self.selected = checked
} }
baseValue = checked baseValue = selected
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) { if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
self.animated = animated self.animated = animated
@ -169,7 +173,7 @@ import Foundation
try container.encodeIfPresent(fieldKey, forKey: .fieldKey) try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
try container.encodeIfPresent(borderColor, forKey: .borderColor) try container.encodeIfPresent(borderColor, forKey: .borderColor)
try container.encode(borderWidth, forKey: .borderWidth) try container.encode(borderWidth, forKey: .borderWidth)
try container.encode(checked, forKey: .checked) try container.encode(selected, forKey: .checked)
try container.encode(inverted, forKey: .inverted) try container.encode(inverted, forKey: .inverted)
try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier) try container.encodeIfPresent(accessibilityIdentifier, forKey: .accessibilityIdentifier)
try container.encodeIfPresent(checkColor, forKey: .checkColor) try container.encodeIfPresent(checkColor, forKey: .checkColor)

View File

@ -98,7 +98,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
self.constrainKnob() self.constrainKnob()
} }
toggleModel?.state = isOn toggleModel?.selected = isOn
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate) _ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff") accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
setNeedsLayout() setNeedsLayout()
@ -381,7 +381,7 @@ public typealias ActionBlockConfirmation = () -> (Bool)
containerTintColor.off = model.offTintColor.uiColor containerTintColor.off = model.offTintColor.uiColor
knobTintColor.on = model.onKnobTintColor.uiColor knobTintColor.on = model.onKnobTintColor.uiColor
knobTintColor.off = model.offKnobTintColor.uiColor knobTintColor.off = model.offKnobTintColor.uiColor
isOn = model.state isOn = model.selected
changeStateNoAnimation(isOn) changeStateNoAnimation(isOn)
isAnimated = model.animated isAnimated = model.animated
isEnabled = model.enabled isEnabled = model.enabled

View File

@ -15,7 +15,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
public static var identifier: String = "toggle" public static var identifier: String = "toggle"
public var accessibilityIdentifier: String? public var accessibilityIdentifier: String?
public var backgroundColor: Color? public var backgroundColor: Color?
public var state: Bool = false public var selected: Bool = false
public var animated: Bool = true public var animated: Bool = true
public var enabled: Bool = true public var enabled: Bool = true
public var action: ActionModelProtocol? public var action: ActionModelProtocol?
@ -53,17 +53,17 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
} }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Methods // MARK: - Form Valdiation
//-------------------------------------------------- //--------------------------------------------------
public func formFieldValue() -> AnyHashable? { state } public func formFieldValue() -> AnyHashable? { selected }
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
//-------------------------------------------------- //--------------------------------------------------
public init(_ state: Bool) { public init(_ state: Bool) {
self.state = state self.selected = state
baseValue = state baseValue = state
} }
@ -75,7 +75,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) { if let state = try typeContainer.decodeIfPresent(Bool.self, forKey: .state) {
self.state = state self.selected = state
} }
if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) { if let enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) {
@ -109,7 +109,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText) accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
baseValue = state baseValue = selected
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey) fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) { if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
self.groupName = groupName self.groupName = groupName
@ -123,7 +123,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol, EnableableMo
try container.encodeModelIfPresent(action, forKey: .action) try container.encodeModelIfPresent(action, forKey: .action)
try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction) try container.encodeModelIfPresent(alternateAction, forKey: .alternateAction)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
try container.encode(state, forKey: .state) try container.encode(selected, forKey: .state)
try container.encode(animated, forKey: .animated) try container.encode(animated, forKey: .animated)
try container.encode(enabled, forKey: .enabled) try container.encode(enabled, forKey: .enabled)
try container.encode(onTintColor, forKey: .onTintColor) try container.encode(onTintColor, forKey: .onTintColor)

View File

@ -81,7 +81,7 @@
numberOfLines = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfLines) numberOfLines = try typeContainer.decodeIfPresent(Int.self, forKey: .numberOfLines)
} }
public func encode(to encoder: Encoder) throws { open func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(moleculeName, forKey: .moleculeName) try container.encodeIfPresent(moleculeName, forKey: .moleculeName)
try container.encode(text, forKey: .text) try container.encode(text, forKey: .text)

View File

@ -7,7 +7,7 @@
// //
public class ListLeftVariableIconWithRightCaretBodyTextModel: ListItemModel, MoleculeModelProtocol { public class ListLeftVariableIconWithRightCaretBodyTextModel: ListItemModel, ParentMoleculeModelProtocol {
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Properties // MARK: - Properties
//----------------------------------------------------- //-----------------------------------------------------
@ -17,6 +17,10 @@ public class ListLeftVariableIconWithRightCaretBodyTextModel: ListItemModel, Mol
public var headlineBody: HeadlineBodyModel public var headlineBody: HeadlineBodyModel
public var rightLabel: LabelModel public var rightLabel: LabelModel
public var children: [MoleculeModelProtocol] {
[image, headlineBody, rightLabel]
}
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Methods // MARK: - Methods
//----------------------------------------------------- //-----------------------------------------------------

View File

@ -7,7 +7,7 @@
// //
public class ListRightVariableRightCaretAllTextAndLinksModel: ListItemModel, MoleculeModelProtocol { public class ListRightVariableRightCaretAllTextAndLinksModel: ListItemModel, ParentMoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
@ -16,6 +16,10 @@ public class ListRightVariableRightCaretAllTextAndLinksModel: ListItemModel, Mol
public var rightLabel: LabelModel public var rightLabel: LabelModel
public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel public var eyebrowHeadlineBodyLink: EyebrowHeadlineBodyLinkModel
public var children: [MoleculeModelProtocol] {
[rightLabel, eyebrowHeadlineBodyLink]
}
//----------------------------------------------------- //-----------------------------------------------------
// MARK: - Methods // MARK: - Methods
//----------------------------------------------------- //-----------------------------------------------------

View File

@ -8,7 +8,7 @@
import UIKit import UIKit
public class CornerLabelsModel: MoleculeModelProtocol { public class CornerLabelsModel: ParentMoleculeModelProtocol {
public static var identifier: String = "cornerLabels" public static var identifier: String = "cornerLabels"
public var backgroundColor: Color? public var backgroundColor: Color?
public var topLeftLabel: LabelModel? public var topLeftLabel: LabelModel?
@ -16,6 +16,9 @@ public class CornerLabelsModel: MoleculeModelProtocol {
public var bottomLeftLabel: LabelModel? public var bottomLeftLabel: LabelModel?
public var bottomRightLabel: LabelModel? public var bottomRightLabel: LabelModel?
public var molecule: MoleculeModelProtocol? public var molecule: MoleculeModelProtocol?
public var children: [MoleculeModelProtocol] {
[molecule, topLeftLabel, topRightLabel, bottomLeftLabel, bottomRightLabel].compactMap { $0 }
}
init(with molecule: MoleculeModelProtocol?) { init(with molecule: MoleculeModelProtocol?) {
self.molecule = molecule self.molecule = molecule
@ -35,20 +38,20 @@ public class CornerLabelsModel: MoleculeModelProtocol {
let typeContainer = try decoder.container(keyedBy: CodingKeys.self) let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor) backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
molecule = try typeContainer.decodeModelIfPresent(codingKey: .molecule) molecule = try typeContainer.decodeModelIfPresent(codingKey: .molecule)
topLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topLeftLabel) topLeftLabel = try typeContainer.decodeMoleculeIfPresent(codingKey: .topLeftLabel)
topRightLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .topRightLabel) topRightLabel = try typeContainer.decodeMoleculeIfPresent(codingKey: .topRightLabel)
bottomLeftLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .bottomLeftLabel) bottomLeftLabel = try typeContainer.decodeMoleculeIfPresent(codingKey: .bottomLeftLabel)
bottomRightLabel = try typeContainer.decodeIfPresent(LabelModel.self, forKey: .bottomRightLabel) bottomRightLabel = try typeContainer.decodeMoleculeIfPresent(codingKey: .bottomRightLabel)
} }
public func encode(to encoder: Encoder) throws { public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self) var container = encoder.container(keyedBy: CodingKeys.self)
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor) try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
try container.encodeModelIfPresent(molecule, forKey: .molecule) try container.encodeModelIfPresent(molecule, forKey: .molecule)
try container.encodeIfPresent(topLeftLabel, forKey: .topLeftLabel) try container.encodeModelIfPresent(topLeftLabel, forKey: .topLeftLabel)
try container.encodeIfPresent(topRightLabel, forKey: .topRightLabel) try container.encodeModelIfPresent(topRightLabel, forKey: .topRightLabel)
try container.encodeIfPresent(bottomLeftLabel, forKey: .bottomLeftLabel) try container.encodeModelIfPresent(bottomLeftLabel, forKey: .bottomLeftLabel)
try container.encodeIfPresent(bottomRightLabel, forKey: .bottomRightLabel) try container.encodeModelIfPresent(bottomRightLabel, forKey: .bottomRightLabel)
try container.encode(moleculeName, forKey: .moleculeName) try container.encode(moleculeName, forKey: .moleculeName)
} }
} }

View File

@ -20,16 +20,9 @@
} }
/// Creates the item with the passed in action. /// Creates the item with the passed in action.
public static func create(with image: UIImage?, actionModel: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self { public static func create(with image: UIImage?, model: MoleculeModelProtocol & NavigationButtonModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self {
let button = create(with: image) let button = create(with: image)
button.set(with: actionModel, delegateObject: delegateObject, additionalData: additionalData) button.set(with: model, delegateObject: delegateObject, additionalData: additionalData)
return button
}
/// Creates the item with the passed in action map.
public static func create(with image: UIImage?, actionMap: [AnyHashable: Any], delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self {
let button = create(with: image)
button.set(with: actionMap, delegateObject: delegateObject, additionalData: additionalData)
return button return button
} }

View File

@ -21,16 +21,9 @@
} }
/// Creates the item with the passed in action. /// Creates the item with the passed in action.
public static func create(with title: String?, actionModel: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self { public static func create(with title: String?, model: NavigationLabelButtonModel, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self {
let button = create(with: title) let button = create(with: title)
button.set(with: actionModel, delegateObject: delegateObject, additionalData: additionalData) button.set(with: model, delegateObject: delegateObject, additionalData: additionalData)
return button
}
/// Creates the item with the passed in action map.
public static func create(with title: String?, actionMap: [AnyHashable : Any], delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) -> Self {
let button = create(with: title)
button.set(with: actionMap, delegateObject: delegateObject, additionalData: additionalData)
return button return button
} }

View File

@ -67,7 +67,7 @@ public class NavigationImageButtonModel: NavigationButtonModelProtocol, Molecule
/// Convenience function that creates a BarButtonItem for the model. /// Convenience function that creates a BarButtonItem for the model.
public func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem { public func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem {
let uiImage = MVMCoreCache.shared()?.getImageFromRegisteredBundles(image) let uiImage = MVMCoreCache.shared()?.getImageFromRegisteredBundles(image)
let buttonItem = ImageBarButtonItem.create(with: uiImage, actionModel: action, delegateObject: delegateObject, additionalData: additionalData) let buttonItem = ImageBarButtonItem.create(with: uiImage, model: self, delegateObject: delegateObject, additionalData: additionalData)
buttonItem.accessibilityIdentifier = accessibilityIdentifier ?? image buttonItem.accessibilityIdentifier = accessibilityIdentifier ?? image
if let accessibilityString = accessibilityText { if let accessibilityString = accessibilityText {
buttonItem.accessibilityLabel = accessibilityString buttonItem.accessibilityLabel = accessibilityString

View File

@ -7,16 +7,16 @@
// //
public class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeModelProtocol { open class NavigationLabelButtonModel: NavigationButtonModelProtocol, MoleculeModelProtocol {
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Properties // MARK: - Properties
//-------------------------------------------------- //--------------------------------------------------
public var backgroundColor: Color? open var backgroundColor: Color?
public static var identifier: String = "navigationLabelButton" open class var identifier: String { "navigationLabelButton" }
public var accessibilityIdentifier: String? open var accessibilityIdentifier: String?
public var title: String open var title: String
public var action: ActionModelProtocol open var action: ActionModelProtocol
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Initializer // MARK: - Initializer
@ -62,7 +62,7 @@ public class NavigationLabelButtonModel: NavigationButtonModelProtocol, Molecule
//-------------------------------------------------- //--------------------------------------------------
/// Convenience function that creates a BarButtonItem for the model. /// Convenience function that creates a BarButtonItem for the model.
public func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem { open func createNavigationItemButton(delegateObject: MVMCoreUIDelegateObject? = nil, additionalData: [AnyHashable: Any]? = nil) -> UIBarButtonItem {
return LabelBarButtonItem.create(with: title, actionModel: action, delegateObject: delegateObject, additionalData: additionalData) return LabelBarButtonItem.create(with: title, model: self, delegateObject: delegateObject, additionalData: additionalData)
} }
} }

View File

@ -91,3 +91,16 @@ open class NavigationItemModel: NavigationItemModelProtocol, MoleculeModelProtoc
try container.encodeModelIfPresent(titleView, forKey: .titleView) try container.encodeModelIfPresent(titleView, forKey: .titleView)
} }
} }
extension NavigationItemModel: ParentMoleculeModelProtocol {
public var children: [MoleculeModelProtocol] {
var children: [MoleculeModelProtocol] = [line, titleView, backButton].compactMap { $0 }
if let leftButtons = additionalLeftButtons {
children.append(contentsOf: leftButtons)
}
if let rightButtons = additionalRightButtons {
children.append(contentsOf: rightButtons)
}
return children
}
}

View File

@ -6,14 +6,14 @@
// Copyright © 2019 Verizon Wireless. All rights reserved. // Copyright © 2019 Verizon Wireless. All rights reserved.
// //
import Foundation
public protocol MoleculeDelegateProtocol: AnyObject { public protocol MoleculeDelegateProtocol: AnyObject {
func getRootMolecules() -> [MoleculeModelProtocol] func getRootMolecules() -> [MoleculeModelProtocol]
/// returns a module for the corresponding module name. /// returns a module for the corresponding module name.
func getModuleWithName(_ name: String?) -> [AnyHashable : Any]? func getModuleWithName(_ name: String?) -> [AnyHashable: Any]?
func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol? func getModuleWithName(_ moleculeName: String) -> MoleculeModelProtocol?
/// Notifies the delegate that the molecule layout update. Should be called when the layout may change due to an async method. Mainly used for list or collections. /// Notifies the delegate that the molecule layout update. Should be called when the layout may change due to an async method. Mainly used for list or collections.
@ -21,15 +21,19 @@ public protocol MoleculeDelegateProtocol: AnyObject {
/// Asks the delegate to add or remove molecules. Mainly used for list or collections. /// Asks the delegate to add or remove molecules. Mainly used for list or collections.
func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath?
func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation)
func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation)
} }
extension MoleculeDelegateProtocol { extension MoleculeDelegateProtocol {
public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {} public func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { }
public func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { return nil } public func getIndexPath(for molecule: ListItemModelProtocol & MoleculeModelProtocol) -> IndexPath? { nil }
public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) {}
public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {} public func addMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], indexPath: IndexPath, animation: UITableView.RowAnimation) { }
public func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) { }
} }

View File

@ -50,5 +50,4 @@ extension MoleculeTreeTraversalProtocol {
return accumulator return accumulator
} }
} }
} }

View File

@ -184,9 +184,7 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) { open override func moleculeLayoutUpdated(_ molecule: MoleculeViewProtocol) {
guard let tableView = tableView else { return } guard let tableView = tableView else { return }
if let indexPath = tableView.indexPathForRow(at: molecule.center), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
let point = molecule.convert(molecule.bounds.origin, to: tableView)
if let indexPath = tableView.indexPathForRow(at: point), tableView.indexPathsForVisibleRows?.contains(indexPath) ?? false {
performTableViewUpdates() performTableViewUpdates()
} }
} }
@ -222,6 +220,36 @@ open class MoleculeListTemplate: ThreeLayerTableViewController, TemplateProtocol
} }
} }
open func newData(for molecule: MoleculeModelProtocol) {
//TODO: expand for header, navigation, etc
let json = molecule.toJSON()
guard let index = moleculesInfo?.firstIndex(where: { (moleculeInfo) -> Bool in
//TODO: check for molecule protocol eqaulity
if json == moleculeInfo.molecule.toJSON() {
return true
} else if let parent = moleculeInfo.molecule as? ParentMoleculeModelProtocol {
// Get all molecules of the same type for faster check.
let molecules: [MoleculeModelProtocol] = parent.reduceDepthFirstTraverse(options: .childFirst, depth: 0, initialResult: []) { (accumulator, currentMolecule, depth) in
if currentMolecule.moleculeName == molecule.moleculeName {
return accumulator + [currentMolecule]
}
return accumulator
}
for molecule in molecules {
if json == molecule.toJSON() {
return true
}
}
}
return false
}) else { return }
// Refresh the cell.
let indexPath = IndexPath(row: index, section: 0)
_ = tableView(tableView, cellForRowAt: indexPath)
performTableViewUpdates()
}
open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) { open override func removeMolecules(_ molecules: [ListItemModelProtocol & MoleculeModelProtocol], animation: UITableView.RowAnimation) {
var indexPaths: [IndexPath] = [] var indexPaths: [IndexPath] = []
//TODO: check for molecule protocol equality //TODO: check for molecule protocol equality

View File

@ -16,7 +16,7 @@
public var moleculeStack: StackModel public var moleculeStack: StackModel
public override var rootMolecules: [MoleculeModelProtocol] { public override var rootMolecules: [MoleculeModelProtocol] {
return [header, moleculeStack, footer].compactMap { $0 } [navigationBar, header, moleculeStack, footer].compactMap { $0 }
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -18,7 +18,7 @@
public var footer: MoleculeModelProtocol? public var footer: MoleculeModelProtocol?
public override var rootMolecules: [MoleculeModelProtocol] { public override var rootMolecules: [MoleculeModelProtocol] {
return [header, footer].compactMap { $0 } [navigationBar, header, footer].compactMap { $0 }
} }
//-------------------------------------------------- //--------------------------------------------------

View File

@ -20,7 +20,7 @@ public typealias BarButtonAction = (BarButtonItem) -> ()
//-------------------------------------------------- //--------------------------------------------------
// MARK: - Delegate // MARK: - Delegate
//-------------------------------------------------- //--------------------------------------------------
open var model: (MoleculeModelProtocol & NavigationButtonModelProtocol)?
open weak var buttonDelegate: ButtonDelegateProtocol? open weak var buttonDelegate: ButtonDelegateProtocol?
var actionDelegate: ActionDelegate? var actionDelegate: ActionDelegate?
@ -28,18 +28,12 @@ public typealias BarButtonAction = (BarButtonItem) -> ()
// MARK: - Methods // MARK: - Methods
//-------------------------------------------------- //--------------------------------------------------
open func set(with actionModel: ActionModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) { open func set(with model: MoleculeModelProtocol & NavigationButtonModelProtocol, delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
self.model = model
buttonDelegate = delegateObject?.buttonDelegate buttonDelegate = delegateObject?.buttonDelegate
actionDelegate?.buttonAction = { sender in actionDelegate?.buttonAction = { sender in
Button.performButtonAction(with: actionModel, button: sender, delegateObject: delegateObject, additionalData: additionalData) let additionalDataWithSource = additionalData.dictionaryAdding(key: KeySourceModel, value: model)
} Button.performButtonAction(with: model.action, button: sender, delegateObject: delegateObject, additionalData: additionalDataWithSource)
}
open func set(with actionMap: [AnyHashable : Any], delegateObject: MVMCoreUIDelegateObject?, additionalData: [AnyHashable: Any]?) {
buttonDelegate = delegateObject?.buttonDelegate
actionDelegate?.buttonAction = { sender in
guard delegateObject?.buttonDelegate?.button?(sender, shouldPerformActionWithMap: actionMap, additionalData: additionalData) ?? true else { return }
MVMCoreActionHandler.shared()?.handleAction(with: actionMap, additionalData: additionalData, delegateObject: delegateObject)
} }
} }
} }

View File

@ -450,10 +450,12 @@ import UIKit
addFormParams(requestParameters: requestParameters, actionInformation: actionInformation, additionalData: additionalData) addFormParams(requestParameters: requestParameters, actionInformation: actionInformation, additionalData: additionalData)
requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType") requestParameters.parentPageType = loadObject?.pageJSON?.optionalStringForKey("parentPageType")
var pageForwardedData = additionalData ?? [:] var pageForwardedData = additionalData ?? [:]
executeBehaviors { (behavior: PageLocalDataShareBehavior) in executeBehaviors { (behavior: PageLocalDataShareBehavior) in
let dataMap = behavior.compileLocalPageDataForTransfer(delegateObjectIVar) let dataMap = behavior.compileLocalPageDataForTransfer(delegateObjectIVar)
pageForwardedData.merge(dataMap) { (current, _) in current } pageForwardedData.merge(dataMap) { current, _ in current }
} }
MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, actionInformation: actionInformation, additionalData: pageForwardedData, delegateObject: delegateObject()) MVMCoreActionHandler.defaultHandleOpenPage(for: requestParameters, actionInformation: actionInformation, additionalData: pageForwardedData, delegateObject: delegateObject())
} }
@ -461,14 +463,16 @@ import UIKit
MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: self, actionInformation: actionInformation, additionalData: additionalData) MVMCoreUILoggingHandler.shared()?.defaultLogAction(forController: self, actionInformation: actionInformation, additionalData: additionalData)
} }
open func handleUnknownActionType(_ actionType: String?, actionInformation: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) { open func handleUnknownActionType(_ actionType: String?, actionInformation: [AnyHashable: Any]?, additionalData: [AnyHashable: Any]?) {
var handled = false var handled = false
executeBehaviors { (behavior: PageCustomActionHandlerBehavior) in executeBehaviors { (behavior: PageCustomActionHandlerBehavior) in
if (!handled) { if !handled {
handled = behavior.handleAction(type: actionType, information: actionInformation, additionalData: additionalData) handled = behavior.handleAction(type: actionType, information: actionInformation, additionalData: additionalData)
} }
} }
if (!handled) {
if !handled {
MVMCoreUIActionHandler.defaultHandleUnknownActionType(actionType, actionInformation: actionInformation, additionalData: additionalData, delegateObject: delegateObjectIVar) MVMCoreUIActionHandler.defaultHandleUnknownActionType(actionType, actionInformation: actionInformation, additionalData: additionalData, delegateObject: delegateObjectIVar)
} }
} }
@ -478,7 +482,7 @@ import UIKit
//-------------------------------------------------- //--------------------------------------------------
open func getRootMolecules() -> [MoleculeModelProtocol] { open func getRootMolecules() -> [MoleculeModelProtocol] {
return model?.rootMolecules ?? [] model?.rootMolecules ?? []
} }
open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? { open func getModuleWithName(_ name: String?) -> [AnyHashable: Any]? {

View File

@ -9,6 +9,7 @@
import Foundation import Foundation
import Contacts import Contacts
public protocol PageGetContactBehaviorConsumerProtocol { public protocol PageGetContactBehaviorConsumerProtocol {
func getMatchParameters() -> (NSPredicate, [CNKeyDescriptor])? func getMatchParameters() -> (NSPredicate, [CNKeyDescriptor])?
func consume(contacts: [CNContact]) func consume(contacts: [CNContact])
@ -18,7 +19,7 @@ public class PageGetContactBehaviorModel: PageBehaviorModelProtocol {
public class var identifier: String { "pageGetContactBehavior" } public class var identifier: String { "pageGetContactBehavior" }
public var shouldAllowMultipleInstances: Bool { false } public var shouldAllowMultipleInstances: Bool { false }
public init() {} public init() { }
} }
public class PageGetContactBehavior: PageVisibilityBehavior { public class PageGetContactBehavior: PageVisibilityBehavior {

View File

@ -41,6 +41,11 @@ public protocol PageLocalDataShareBehavior: PageBehaviorProtocol {
public protocol PageCustomActionHandlerBehavior: PageBehaviorProtocol { public protocol PageCustomActionHandlerBehavior: PageBehaviorProtocol {
/// - Parameters:
/// - actionType: The action type of the passed action model.
/// - information: information of the passed action model.
/// - additionalData: Additional information of the
/// - Returns: Boolean determines if the action has been handled.
func handleAction(type actionType: String?, information: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) -> Bool func handleAction(type actionType: String?, information: [AnyHashable : Any]?, additionalData: [AnyHashable : Any]?) -> Bool
} }