Merge branch 'feature/heart' into 'develop'
Feature/heart See merge request BPHV_MIPS/mvm_core_ui!582
This commit is contained in:
commit
3db62cbc7f
@ -236,6 +236,8 @@
|
||||
AA997252247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */; };
|
||||
AAA74A172410C04600080241 /* HeadersH2NoButtonsBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */; };
|
||||
AAA74A192410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */; };
|
||||
AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA7CD68250641F90045B959 /* HeartModel.swift */; };
|
||||
AAA7CD6B250642080045B959 /* Heart.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA7CD6A250642080045B959 /* Heart.swift */; };
|
||||
AAA905DF24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA905DE24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift */; };
|
||||
AAA905E124D1759A00D1EFAB /* ListThreeColumnBillHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAA905E024D1759A00D1EFAB /* ListThreeColumnBillHistory.swift */; };
|
||||
AAB7EDEF246ADA1600E54929 /* ListProgressBarThinModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */; };
|
||||
@ -738,6 +740,8 @@
|
||||
AA997251247530B100FC7472 /* ListLeftVariableIconAllTextLinks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListLeftVariableIconAllTextLinks.swift; sourceTree = "<group>"; };
|
||||
AAA74A162410C04600080241 /* HeadersH2NoButtonsBodyText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyText.swift; sourceTree = "<group>"; };
|
||||
AAA74A182410C05800080241 /* HeadersH2NoButtonsBodyTextModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeadersH2NoButtonsBodyTextModel.swift; sourceTree = "<group>"; };
|
||||
AAA7CD68250641F90045B959 /* HeartModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HeartModel.swift; sourceTree = "<group>"; };
|
||||
AAA7CD6A250642080045B959 /* Heart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Heart.swift; sourceTree = "<group>"; };
|
||||
AAA905DE24D1758700D1EFAB /* ListThreeColumnBillHistoryModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnBillHistoryModel.swift; sourceTree = "<group>"; };
|
||||
AAA905E024D1759A00D1EFAB /* ListThreeColumnBillHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListThreeColumnBillHistory.swift; sourceTree = "<group>"; };
|
||||
AAB7EDEE246ADA1600E54929 /* ListProgressBarThinModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListProgressBarThinModel.swift; sourceTree = "<group>"; };
|
||||
@ -1607,6 +1611,8 @@
|
||||
D2092348244A51D40044AD09 /* RadioSwatchModel.swift */,
|
||||
AAB9C109243496DD00151545 /* RadioSwatch.swift */,
|
||||
AA85236B244435A20059CC1E /* RadioSwatchCollectionViewCell.swift */,
|
||||
AAA7CD68250641F90045B959 /* HeartModel.swift */,
|
||||
AAA7CD6A250642080045B959 /* Heart.swift */,
|
||||
);
|
||||
path = Selectors;
|
||||
sourceTree = "<group>";
|
||||
@ -2266,6 +2272,7 @@
|
||||
943784F5236B77BB006A1E82 /* Wheel.swift in Sources */,
|
||||
31BE15CC23D8924D00452370 /* CheckboxModel.swift in Sources */,
|
||||
8D3BA9BF2433789900D341BA /* ListThreeColumnInternationalDataDivider.swift in Sources */,
|
||||
AAA7CD6B250642080045B959 /* Heart.swift in Sources */,
|
||||
94C661DA23CCF4FB00D9FE5B /* UIColor+Extension.swift in Sources */,
|
||||
D28A838123CCB0D800DFE4FC /* AccordionListItemModel.swift in Sources */,
|
||||
D2509ED62472EE2F001BFB9D /* NavigationImageButtonModel.swift in Sources */,
|
||||
@ -2285,6 +2292,7 @@
|
||||
BBC0C4FF24811DCA0087C44F /* TagModel.swift in Sources */,
|
||||
0A7BAD74232A8DC700FB8E22 /* HeadlineBodyButton.swift in Sources */,
|
||||
3265B30424BCA749000D154B /* HeadersH1NoButtonsBodyText.swift in Sources */,
|
||||
AAA7CD69250641F90045B959 /* HeartModel.swift in Sources */,
|
||||
D2FB151D23A40F1500C20E10 /* MoleculeStackItem.swift in Sources */,
|
||||
D28BA7452481652D00B75CB8 /* TabBarProtocol.swift in Sources */,
|
||||
AA11A41F23F15D3100D7962F /* ListRightVariablePayments.swift in Sources */,
|
||||
|
||||
114
MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift
Normal file
114
MVMCoreUI/Atomic/Atoms/Selectors/Heart.swift
Normal file
@ -0,0 +1,114 @@
|
||||
//
|
||||
// Heart.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 07/09/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
@objcMembers open class Heart: Control, MFButtonProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
private var heartLayer: CAShapeLayer?
|
||||
@objc public override var isSelected: Bool {
|
||||
didSet {
|
||||
heartModel?.isActive = isSelected
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
}
|
||||
public var delegateObject: MVMCoreUIDelegateObject?
|
||||
public var heartModel: HeartModel? {
|
||||
return model as? HeartModel
|
||||
}
|
||||
var additionalData: [AnyHashable: Any]?
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Constraints
|
||||
//--------------------------------------------------
|
||||
public var widthConstraint: NSLayoutConstraint?
|
||||
public var heightConstraint: NSLayoutConstraint?
|
||||
|
||||
//------------------------------------------------------
|
||||
// MARK: - State Handling
|
||||
//------------------------------------------------------
|
||||
open override func draw(_ rect: CGRect) {
|
||||
//Draw the heart
|
||||
heartLayer?.removeFromSuperlayer()
|
||||
let heart = drawHeart()
|
||||
layer.addSublayer(heart)
|
||||
heartLayer = heart
|
||||
}
|
||||
|
||||
func drawHeart() -> CAShapeLayer {
|
||||
let heart = CAShapeLayer()
|
||||
let rect = bounds
|
||||
let leftArc = rect.width * 0.4
|
||||
let rightArc = rect.height * 0.3
|
||||
let arcRadius = sqrt(leftArc*leftArc + rightArc*rightArc)/2
|
||||
let heartPath = UIBezierPath()
|
||||
//Left Hand Curve
|
||||
heartPath.addArc(withCenter: CGPoint(x: rect.width * 0.3, y: rect.height * 0.35), radius: arcRadius, startAngle: 135.degreesToRadians, endAngle: 315.degreesToRadians, clockwise: true)
|
||||
//Top Centre Dip
|
||||
heartPath.addLine(to: CGPoint(x: rect.width/2, y: rect.height * 0.2))
|
||||
//Right Hand Curve
|
||||
heartPath.addArc(withCenter: CGPoint(x: rect.width * 0.7, y: rect.height * 0.35), radius: arcRadius, startAngle: 225.degreesToRadians, endAngle: 45.degreesToRadians, clockwise: true)
|
||||
//Right Bottom Line
|
||||
heartPath.addLine(to: CGPoint(x: rect.width * 0.5, y: rect.height * 0.95))
|
||||
//Left Bottom Line
|
||||
heartPath.close()
|
||||
heart.path = heartPath.cgPath
|
||||
heart.fillColor = isSelected ? heartModel?.activeColor.cgColor : heartModel?.inActiveColor.cgColor
|
||||
heart.opacity = 1.0
|
||||
heart.lineWidth = 1
|
||||
heart.strokeColor = isSelected ? UIColor.clear.cgColor : UIColor.mvmBlack.cgColor
|
||||
return heart
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Lifecycle
|
||||
//--------------------------------------------------
|
||||
open override func setupView() {
|
||||
super.setupView()
|
||||
addTarget(self, action: #selector(tapAction), for: .touchUpInside)
|
||||
widthConstraint = widthAnchor.constraint(equalToConstant: 22)
|
||||
widthConstraint?.isActive = true
|
||||
heightConstraint = heightAnchor.constraint(equalTo: widthAnchor, multiplier: 1)
|
||||
heightConstraint?.isActive = true
|
||||
isAccessibilityElement = true
|
||||
accessibilityTraits = .button
|
||||
updateAccessibilityLabel()
|
||||
}
|
||||
|
||||
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||
super.set(with: model, delegateObject, additionalData)
|
||||
self.delegateObject = delegateObject
|
||||
self.additionalData = additionalData
|
||||
guard let model = model as? HeartModel else { return }
|
||||
isSelected = model.isActive
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Methods
|
||||
//--------------------------------------------------
|
||||
/// Adjust accessibility label based on selection of Heart.
|
||||
func updateAccessibilityLabel() {
|
||||
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "heart_unfavorite_action_hint" : "heart_favorite_action_hint")
|
||||
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: isSelected ? "heart_selected_state" : "heart_not_selected_state")
|
||||
}
|
||||
|
||||
func tapAction() {
|
||||
isSelected = !isSelected
|
||||
if let heartModel = heartModel {
|
||||
Button.performButtonAction(with: heartModel.action, button: self, delegateObject: delegateObject, additionalData: additionalData, sourceModel: heartModel)
|
||||
}
|
||||
setNeedsDisplay()
|
||||
}
|
||||
}
|
||||
|
||||
extension Int {
|
||||
var degreesToRadians: CGFloat { return CGFloat(self) * .pi / 180 }
|
||||
}
|
||||
65
MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift
Normal file
65
MVMCoreUI/Atomic/Atoms/Selectors/HeartModel.swift
Normal file
@ -0,0 +1,65 @@
|
||||
//
|
||||
// HeartModel.swift
|
||||
// MVMCoreUI
|
||||
//
|
||||
// Created by Lekshmi S on 07/09/20.
|
||||
// Copyright © 2020 Verizon Wireless. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
open class HeartModel: MoleculeModelProtocol {
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Properties
|
||||
//--------------------------------------------------
|
||||
public static var identifier: String = "heart"
|
||||
public var backgroundColor: Color?
|
||||
public var isActive: Bool = false
|
||||
public var activeColor: Color = Color(uiColor: .mvmRed)
|
||||
public var inActiveColor: Color = Color(uiColor: .clear)
|
||||
public var action: ActionModelProtocol = ActionNoopModel()
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Keys
|
||||
//--------------------------------------------------
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case moleculeName
|
||||
case backgroundColor
|
||||
case isActive
|
||||
case activeColor
|
||||
case inActiveColor
|
||||
case action
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// MARK: - Codec
|
||||
//--------------------------------------------------
|
||||
required public init(from decoder: Decoder) throws {
|
||||
let typeContainer = try decoder.container(keyedBy: CodingKeys.self)
|
||||
|
||||
if let isActive = try typeContainer.decodeIfPresent(Bool.self, forKey: .isActive) {
|
||||
self.isActive = isActive
|
||||
}
|
||||
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||
if let activeColor = try typeContainer.decodeIfPresent(Color.self, forKey: .activeColor) {
|
||||
self.activeColor = activeColor
|
||||
}
|
||||
if let inActiveColor = try typeContainer.decodeIfPresent(Color.self, forKey: .inActiveColor) {
|
||||
self.inActiveColor = inActiveColor
|
||||
}
|
||||
if let action: ActionModelProtocol = try typeContainer.decodeModelIfPresent(codingKey: .action) {
|
||||
self.action = action
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encodeIfPresent(backgroundColor, forKey: .backgroundColor)
|
||||
try container.encode(moleculeName, forKey: .moleculeName)
|
||||
try container.encode(isActive, forKey: .isActive)
|
||||
try container.encode(activeColor, forKey: .activeColor)
|
||||
try container.encode(inActiveColor, forKey: .inActiveColor)
|
||||
try container.encodeModel(action, forKey: .action)
|
||||
}
|
||||
}
|
||||
@ -87,7 +87,7 @@ import Foundation
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: RadioSwatches.self, viewModelClass: RadioSwatchesModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Tags.self, viewModelClass: TagsModel.self)
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Tag.self, viewModelClass: TagModel.self)
|
||||
|
||||
MoleculeObjectMapping.shared()?.register(viewClass: Heart.self, viewModelClass: HeartModel.self)
|
||||
|
||||
|
||||
// MARK:- Other Atoms
|
||||
|
||||
@ -67,6 +67,11 @@
|
||||
"AccOff" = "off";
|
||||
"AccToggleHint" = "double tap to toggle";
|
||||
|
||||
// MARK: Heart
|
||||
"heart_favorite_action_hint" = "Double tap to favorite";
|
||||
"heart_unfavorite_action_hint" = "Double tap to unfavorite";
|
||||
"heart_selected_state" = "Favorited";
|
||||
"heart_not_selected_state" = "Un-favorited";
|
||||
|
||||
// MARK: Carousel
|
||||
"MVMCoreUIPageControl_currentpage_index" = "page %@ of %d";
|
||||
|
||||
@ -49,6 +49,11 @@
|
||||
"AccOn" = "encendido";
|
||||
"AccOff" = "apagado";
|
||||
"AccToggleHint" = "toca dos veces para alternar";
|
||||
// Heart
|
||||
"heart_favorite_action_hint" = "Toca dos veces en favorito";
|
||||
"heart_unfavorite_action_hint" = "Toca dos veces para dejar de marcar como favorito";
|
||||
"heart_selected_state" = "Favoritos";
|
||||
"heart_not_selected_state" = "No favorito";
|
||||
// Carousel
|
||||
"MVMCoreUIPageControl_currentpage_index" = "página %@ de %d";
|
||||
"MVMCoreUIPageControlslides_currentpage_index" = "diapositiva %@ of %d";
|
||||
|
||||
@ -51,6 +51,13 @@
|
||||
"AccOn" = "encendido";
|
||||
"AccOff" = "apagado";
|
||||
"AccToggleHint" = "toca dos veces para alternar";
|
||||
|
||||
// Heart
|
||||
"heart_favorite_action_hint" = "Toca dos veces en favorito";
|
||||
"heart_unfavorite_action_hint" = "Toca dos veces para dejar de marcar como favorito";
|
||||
"heart_selected_state" = "Favoritos";
|
||||
"heart_not_selected_state" = "No favorito";
|
||||
|
||||
// Carousel
|
||||
"MVMCoreUIPageControl_currentpage_index" = "página %@ de %d";
|
||||
"MVMCoreUIPageControlslides_currentpage_index" = "diapositiva %@ of %d";
|
||||
|
||||
Loading…
Reference in New Issue
Block a user