Merge branch 'feature/revert_toggle' into 'release/10_4_0'
Revert "Merge branch 'feature/vds-toggle' ### Summary Back out VDS toggle change. Co-authored-by: Kyle Matthew Hedden <kyle.hedden@verizonwireless.com> See merge request https://gitlab.verizon.com/BPHV_MIPS/mvm_core_ui/-/merge_requests/907
This commit is contained in:
commit
8f4b80021a
@ -593,14 +593,11 @@
|
|||||||
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
|
EA41F4AC2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */; };
|
||||||
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
|
EA5124FD243601600051A3A4 /* BGImageHeadlineBodyButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */; };
|
||||||
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
|
EA5124FF2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */; };
|
||||||
EA797B402909936000DBAFE6 /* VDSTypographyTokens.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = EA797B3F2909936000DBAFE6 /* VDSTypographyTokens.xcframework */; };
|
|
||||||
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; };
|
EA7E67742758310500ABF773 /* EnableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */; };
|
||||||
EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; };
|
EA7E67762758365300ABF773 /* UIUpdatableModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */; };
|
||||||
EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */; };
|
EAA0CFAF275E7D8000D65EB0 /* FormFieldEffectProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */; };
|
||||||
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */; };
|
EAA0CFB1275E823A00D65EB0 /* HideFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */; };
|
||||||
EAA0CFB3275E831E00D65EB0 /* DisableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */; };
|
EAA0CFB3275E831E00D65EB0 /* DisableFormFieldEffectModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */; };
|
||||||
EAA5EEF828F5D079003B3210 /* VDS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EAA5EEF628F5D074003B3210 /* VDS.framework */; };
|
|
||||||
EAA78020290081320057DFDF /* VDSMoleculeViewProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */; };
|
|
||||||
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */; };
|
EAB14BC127D935F00012AB2C /* RuleCompareModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */; };
|
||||||
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; };
|
EAB14BC327D9378D0012AB2C /* RuleAnyModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */; };
|
||||||
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
|
EABFC1412763BB8D00E78B40 /* FormLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EABFC1402763BB8D00E78B40 /* FormLabel.swift */; };
|
||||||
@ -1198,14 +1195,11 @@
|
|||||||
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
EA41F4AB2787927100F5B377 /* DynamicRuleFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DynamicRuleFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||||
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
|
EA5124FC243601600051A3A4 /* BGImageHeadlineBodyButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButton.swift; sourceTree = "<group>"; };
|
||||||
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
|
EA5124FE2436018E0051A3A4 /* BGImageHeadlineBodyButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BGImageHeadlineBodyButtonModel.swift; sourceTree = "<group>"; };
|
||||||
EA797B3F2909936000DBAFE6 /* VDSTypographyTokens.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDSTypographyTokens.xcframework; path = ../SharedFrameworks/VDSTypographyTokens.xcframework; sourceTree = "<group>"; };
|
|
||||||
EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
EA7E67732758310500ABF773 /* EnableFormFieldEffectModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EnableFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||||
EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUpdatableModelProtocol.swift; sourceTree = "<group>"; };
|
EA7E67752758365300ABF773 /* UIUpdatableModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIUpdatableModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldEffectProtocol.swift; sourceTree = "<group>"; };
|
EAA0CFAE275E7D8000D65EB0 /* FormFieldEffectProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormFieldEffectProtocol.swift; sourceTree = "<group>"; };
|
||||||
EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
EAA0CFB0275E823A00D65EB0 /* HideFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HideFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||||
EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
EAA0CFB2275E831E00D65EB0 /* DisableFormFieldEffectModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisableFormFieldEffectModel.swift; sourceTree = "<group>"; };
|
||||||
EAA5EEF628F5D074003B3210 /* VDS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = VDS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
||||||
EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VDSMoleculeViewProtocol.swift; sourceTree = "<group>"; };
|
|
||||||
EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleCompareModelProtocol.swift; sourceTree = "<group>"; };
|
EAB14BC027D935F00012AB2C /* RuleCompareModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleCompareModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; };
|
EAB14BC227D9378D0012AB2C /* RuleAnyModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleAnyModelProtocol.swift; sourceTree = "<group>"; };
|
||||||
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
|
EABFC1402763BB8D00E78B40 /* FormLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormLabel.swift; sourceTree = "<group>"; };
|
||||||
@ -1220,9 +1214,7 @@
|
|||||||
files = (
|
files = (
|
||||||
D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */,
|
D29DF0E621E4F3C7003B2FB9 /* MVMCore.framework in Frameworks */,
|
||||||
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */,
|
AFE4A1D127DFB5EE00C458D0 /* VDSColorTokens.xcframework in Frameworks */,
|
||||||
EAA5EEF828F5D079003B3210 /* VDS.framework in Frameworks */,
|
|
||||||
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */,
|
187FEB2A2844D2A600BF29C2 /* VDSFormControlsTokens.xcframework in Frameworks */,
|
||||||
EA797B402909936000DBAFE6 /* VDSTypographyTokens.xcframework in Frameworks */,
|
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -2066,8 +2058,6 @@
|
|||||||
D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = {
|
D29DF0E421E4F3C7003B2FB9 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
EA797B3F2909936000DBAFE6 /* VDSTypographyTokens.xcframework */,
|
|
||||||
EAA5EEF628F5D074003B3210 /* VDS.framework */,
|
|
||||||
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */,
|
187FEB292844D2A600BF29C2 /* VDSFormControlsTokens.xcframework */,
|
||||||
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */,
|
AFE4A1D027DFB5EE00C458D0 /* VDSColorTokens.xcframework */,
|
||||||
D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */,
|
D29DF0E521E4F3C7003B2FB9 /* MVMCore.framework */,
|
||||||
@ -2462,7 +2452,6 @@
|
|||||||
D2B9D0E3265EEE9D0084735C /* MoleculeListProtocol.swift */,
|
D2B9D0E3265EEE9D0084735C /* MoleculeListProtocol.swift */,
|
||||||
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
011B58EE23A2AA850085F53C /* ModelProtocols */,
|
||||||
27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */,
|
27559EFB27D691D3000836C1 /* ViewMaskingProtocol.swift */,
|
||||||
EAA7801F290081320057DFDF /* VDSMoleculeViewProtocol.swift */,
|
|
||||||
);
|
);
|
||||||
path = Protocols;
|
path = Protocols;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -2789,7 +2778,6 @@
|
|||||||
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */,
|
01EB369423609801006832FA /* HeadlineBodyModel.swift in Sources */,
|
||||||
D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */,
|
D2A92884241ACB25004E01C6 /* ProgrammaticScrollViewController.swift in Sources */,
|
||||||
D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */,
|
D23A90002612347A007E14CE /* PageBehaviorHandlerModelProtocol.swift in Sources */,
|
||||||
EAA78020290081320057DFDF /* VDSMoleculeViewProtocol.swift in Sources */,
|
|
||||||
0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */,
|
0A21DB7F235DECC500C160A2 /* EntryField.swift in Sources */,
|
||||||
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */,
|
D2E2A99F23E07F8A000B42E6 /* PillButton.swift in Sources */,
|
||||||
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
|
D2C5001921F8ECDD001DA659 /* MVMCoreUIViewControllerMappingObject.m in Sources */,
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
import MVMCore
|
import MVMCore
|
||||||
import UIKit
|
import UIKit
|
||||||
import VDS
|
|
||||||
import Combine
|
public typealias ActionBlockConfirmation = () -> (Bool)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A custom implementation of Apple's UISwitch.
|
A custom implementation of Apple's UISwitch.
|
||||||
@ -19,123 +19,402 @@ import Combine
|
|||||||
Container: The background of the toggle control.
|
Container: The background of the toggle control.
|
||||||
Knob: The circular indicator that slides on the container.
|
Knob: The circular indicator that slides on the container.
|
||||||
*/
|
*/
|
||||||
open class Toggle: ToggleBase, VDSMoleculeViewProtocol {
|
@objcMembers open class Toggle: Control, MVMCoreUIViewConstrainingProtocol {
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Properties
|
// MARK: - Properties
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
public var viewModel: ToggleModel!
|
|
||||||
public var delegateObject: MVMCoreUIDelegateObject?
|
/// Holds the on and off colors for the container.
|
||||||
public var additionalData: [AnyHashable: Any]?
|
public var containerTintColor: (on: UIColor, off: UIColor) = (on: .mvmGreen, off: .mvmBlack)
|
||||||
public var valueChangedSubscription: AnyCancellable? {
|
|
||||||
willSet{
|
/// Holds the on and off colors for the knob.
|
||||||
if let current = valueChangedSubscription {
|
public var knobTintColor: (on: UIColor, off: UIColor) = (on: .mvmWhite, off: .mvmWhite)
|
||||||
current.cancel()
|
|
||||||
}
|
/// Holds the on and off colors for the disabled state..
|
||||||
|
public var disabledTintColor: (container: UIColor, knob: UIColor) = (container: .mvmCoolGray3, knob: .mvmWhite)
|
||||||
|
|
||||||
|
/// Set this flag to false if you do not want to animate state changes.
|
||||||
|
public var isAnimated = true
|
||||||
|
|
||||||
|
public var didToggleAction: ActionBlock?
|
||||||
|
|
||||||
|
/// Executes logic before state change. If false, then toggle state will not change and the didToggleAction will not execute.
|
||||||
|
public var shouldToggleAction: ActionBlockConfirmation? = {
|
||||||
|
return { true }
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Sizes are from InVision design specs.
|
||||||
|
static let containerSize = CGSize(width: 51, height: 31)
|
||||||
|
static let knobSize = CGSize(width: 28, height: 28)
|
||||||
|
|
||||||
|
private var knobView: View = {
|
||||||
|
let view = View()
|
||||||
|
view.backgroundColor = .white
|
||||||
|
view.layer.cornerRadius = Toggle.getKnobHeight() / 2.0
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Computed Properties
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override var isEnabled: Bool {
|
||||||
|
didSet {
|
||||||
|
isUserInteractionEnabled = isEnabled
|
||||||
|
changeStateNoAnimation(isEnabled ? isOn : false)
|
||||||
|
setToggleAppearanceFromState()
|
||||||
|
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: isEnabled ? "AccToggleHint" : "AccDisabled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Simple means to prevent user interaction with the toggle.
|
||||||
|
public var isLocked: Bool = false {
|
||||||
|
didSet { isUserInteractionEnabled = !isLocked }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The state on the toggle. Default value: false.
|
||||||
|
open var isOn: Bool = false {
|
||||||
|
didSet {
|
||||||
|
if isAnimated {
|
||||||
|
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
|
||||||
|
if self.isOn {
|
||||||
|
self.knobView.backgroundColor = self.knobTintColor.on
|
||||||
|
self.backgroundColor = self.containerTintColor.on
|
||||||
|
|
||||||
|
} else {
|
||||||
|
self.knobView.backgroundColor = self.knobTintColor.off
|
||||||
|
self.backgroundColor = self.containerTintColor.off
|
||||||
|
}
|
||||||
|
}, completion: nil)
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.33, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0.2, options: [], animations: {
|
||||||
|
self.constrainKnob()
|
||||||
|
self.knobWidthConstraint?.constant = Self.getKnobWidth()
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
}, completion: nil)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setToggleAppearanceFromState()
|
||||||
|
self.constrainKnob()
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleModel?.selected = isOn
|
||||||
|
_ = FormValidator.validate(delegate: delegateObject?.formHolderDelegate)
|
||||||
|
accessibilityValue = isOn ? MVMCoreUIUtility.hardcodedString(withKey: "AccOn") : MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
|
||||||
|
setNeedsLayout()
|
||||||
|
layoutIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var toggleModel: ToggleModel? {
|
||||||
|
model as? ToggleModel
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Delegate
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private var delegateObject: MVMCoreUIDelegateObject?
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Constraints
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
private var knobLeadingConstraint: NSLayoutConstraint?
|
||||||
|
private var knobTrailingConstraint: NSLayoutConstraint?
|
||||||
|
private var knobHeightConstraint: NSLayoutConstraint?
|
||||||
|
private var knobWidthConstraint: NSLayoutConstraint?
|
||||||
|
private var heightConstraint: NSLayoutConstraint?
|
||||||
|
private var widthConstraint: NSLayoutConstraint?
|
||||||
|
|
||||||
|
private func constrainKnob() {
|
||||||
|
|
||||||
|
knobLeadingConstraint?.isActive = false
|
||||||
|
knobTrailingConstraint?.isActive = false
|
||||||
|
|
||||||
|
_ = isOn ? constrainKnobOn() : constrainKnobOff()
|
||||||
|
|
||||||
|
knobTrailingConstraint?.isActive = true
|
||||||
|
knobLeadingConstraint?.isActive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private func constrainKnobOn() {
|
||||||
|
|
||||||
|
knobTrailingConstraint = trailingAnchor.constraint(equalTo: knobView.trailingAnchor, constant: 2)
|
||||||
|
knobLeadingConstraint = knobView.leadingAnchor.constraint(greaterThanOrEqualTo: leadingAnchor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func constrainKnobOff() {
|
||||||
|
|
||||||
|
knobTrailingConstraint = trailingAnchor.constraint(greaterThanOrEqualTo: knobView.trailingAnchor)
|
||||||
|
knobLeadingConstraint = knobView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 2)
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Initializers
|
// MARK: - Initializers
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
}
|
||||||
|
|
||||||
|
public convenience override init() {
|
||||||
|
self.init(frame: .zero)
|
||||||
|
}
|
||||||
|
|
||||||
public convenience init(isOn: Bool) {
|
public convenience init(isOn: Bool) {
|
||||||
self.init(frame: .zero)
|
self.init(frame: .zero)
|
||||||
self.isOn = isOn
|
self.isOn = isOn
|
||||||
}
|
}
|
||||||
|
|
||||||
open override func initialSetup() {
|
/// - parameter isOn: Bool to set the state of the toggle.
|
||||||
super.initialSetup()
|
/// - parameter didToggleAction: A closure which is executed after the toggle changes states.
|
||||||
|
public convenience init(isOn: Bool = false, didToggleAction: ActionBlock?) {
|
||||||
publisher(for: .touchUpInside)
|
self.init(frame: .zero)
|
||||||
.sink {[weak self] toggle in
|
changeStateNoAnimation(isOn)
|
||||||
guard let self = self else { return }
|
self.didToggleAction = didToggleAction
|
||||||
self.toggle()
|
|
||||||
}.store(in: &subscribers)
|
|
||||||
|
|
||||||
//this is logic that will always need to be run
|
|
||||||
//and is added into the array of Set<AnyCancellables>
|
|
||||||
publisher(for: .valueChanged)
|
|
||||||
.sink {[weak self] _ in
|
|
||||||
guard let self = self, let viewModel = self.viewModel else { return }
|
|
||||||
//sync the value on the viewModel
|
|
||||||
viewModel.selected = self.isOn
|
|
||||||
|
|
||||||
//tell the form you changed
|
|
||||||
_ = FormValidator.validate(delegate: self.delegateObject?.formHolderDelegate)
|
|
||||||
|
|
||||||
}.store(in: &subscribers)
|
|
||||||
|
|
||||||
//register the defaultActionExecuter
|
|
||||||
//this can then be overwritten by a subclass
|
|
||||||
valueChangedSubscription = publisher(for: .valueChanged)
|
|
||||||
.sink {[weak self] _ in
|
|
||||||
guard let self = self else { return }
|
|
||||||
self.executeDefaultAction()
|
|
||||||
}
|
|
||||||
|
|
||||||
accessibilityLabelEnabled = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
|
||||||
accessibilityLabelDisabled = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
|
||||||
accessibilityHintEnabled = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint")
|
|
||||||
accessibilityHintDisabled = MVMCoreUIUtility.hardcodedString(withKey: "AccDisabled")
|
|
||||||
accessibilityValueEnabled = MVMCoreUIUtility.hardcodedString(withKey: "AccOn")
|
|
||||||
accessibilityValueDisabled = MVMCoreUIUtility.hardcodedString(withKey: "AccOff")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open func updateView(_ size: CGFloat) {}
|
/// - parameter shouldToggleAction: Takes a closure that returns a boolean.
|
||||||
|
/// - parameter didToggleAction: A closure which is executed after the toggle changes states.
|
||||||
open override func updateView() {
|
public convenience init(shouldToggleAction: ActionBlockConfirmation?, didToggleAction: ActionBlock?) {
|
||||||
super.updateView()
|
self.init(frame: .zero)
|
||||||
//we want to overwrite the VDS color that is set in the ToggleBase
|
self.didToggleAction = didToggleAction
|
||||||
//for surface since the Atomic controls doesn't look at
|
self.shouldToggleAction = shouldToggleAction
|
||||||
//surface today for its views. We just want to show whatever
|
|
||||||
//the current parent's background color.
|
|
||||||
backgroundColor = .clear
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open func viewModelDidUpdate() {
|
public required init?(coder: NSCoder) {
|
||||||
guard let viewModel else { return }
|
super.init(coder: coder)
|
||||||
|
fatalError("Toggle does not support xib.")
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Lifecycle
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public override func updateView(_ size: CGFloat) {
|
||||||
|
super.updateView(size)
|
||||||
|
|
||||||
//set properties from the viewModel change that came in
|
heightConstraint?.constant = Self.getContainerHeight()
|
||||||
if let accessibilityText = viewModel.accessibilityText {
|
widthConstraint?.constant = Self.getContainerWidth()
|
||||||
accessibilityLabelEnabled = accessibilityText
|
|
||||||
accessibilityLabelDisabled = accessibilityText
|
knobHeightConstraint?.constant = Self.getKnobHeight()
|
||||||
}
|
knobWidthConstraint?.constant = Self.getKnobWidth()
|
||||||
isAnimated = viewModel.animated
|
|
||||||
|
layer.cornerRadius = Self.getContainerHeight() / 2.0
|
||||||
|
knobView.layer.cornerRadius = Self.getKnobHeight() / 2.0
|
||||||
|
|
||||||
|
changeStateNoAnimation(isOn)
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func setupView() {
|
||||||
|
super.setupView()
|
||||||
|
|
||||||
|
isAccessibilityElement = true
|
||||||
|
accessibilityHint = MVMCoreUIUtility.hardcodedString(withKey: "AccToggleHint")
|
||||||
|
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
||||||
|
accessibilityTraits = .button
|
||||||
|
|
||||||
//send toggle.model to the Form
|
heightConstraint = heightAnchor.constraint(equalToConstant: Self.containerSize.height)
|
||||||
FormValidator.setupValidation(for: viewModel, delegate: delegateObject?.formHolderDelegate)
|
heightConstraint?.isActive = true
|
||||||
|
|
||||||
|
widthConstraint = widthAnchor.constraint(equalToConstant: Self.containerSize.width)
|
||||||
|
widthConstraint?.isActive = true
|
||||||
|
|
||||||
|
layer.cornerRadius = Self.getContainerHeight() / 2.0
|
||||||
|
backgroundColor = containerTintColor.off
|
||||||
|
|
||||||
|
addSubview(knobView)
|
||||||
|
|
||||||
|
knobHeightConstraint = knobView.heightAnchor.constraint(equalToConstant: Self.knobSize.height)
|
||||||
|
knobHeightConstraint?.isActive = true
|
||||||
|
knobWidthConstraint = knobView.widthAnchor.constraint(equalToConstant: Self.knobSize.width)
|
||||||
|
knobWidthConstraint?.isActive = true
|
||||||
|
knobView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
|
||||||
|
knobView.topAnchor.constraint(greaterThanOrEqualTo: topAnchor).isActive = true
|
||||||
|
bottomAnchor.constraint(greaterThanOrEqualTo: knobView.bottomAnchor).isActive = true
|
||||||
|
|
||||||
|
constrainKnobOff()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func executeDefaultAction() {
|
public override func reset() {
|
||||||
guard let viewModel else { return }
|
super.reset()
|
||||||
if viewModel.action != nil || viewModel.alternateAction != nil {
|
|
||||||
var action: ActionModelProtocol?
|
backgroundColor = containerTintColor.off
|
||||||
if isOn {
|
knobView.backgroundColor = knobTintColor.off
|
||||||
action = viewModel.action
|
accessibilityLabel = MVMCoreUIUtility.hardcodedString(withKey: "Toggle_buttonlabel")
|
||||||
} else {
|
isAnimated = true
|
||||||
action = viewModel.alternateAction ?? viewModel.action
|
didToggleAction = nil
|
||||||
}
|
shouldToggleAction = { return true }
|
||||||
if let action {
|
}
|
||||||
MVMCoreUIActionHandler.performActionUnstructured(with: action,
|
|
||||||
sourceModel: viewModel,
|
class func getContainerWidth() -> CGFloat {
|
||||||
additionalData: additionalData,
|
let containerWidth = Self.containerSize.width
|
||||||
delegateObject: delegateObject)
|
return (MFSizeObject(standardSize: containerWidth, standardiPadPortraitSize: CGFloat(Self.containerSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
class func getContainerHeight() -> CGFloat {
|
||||||
|
let containerHeight = Self.containerSize.height
|
||||||
|
return (MFSizeObject(standardSize: containerHeight, standardiPadPortraitSize: CGFloat(Self.containerSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? containerHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
class func getKnobWidth() -> CGFloat {
|
||||||
|
let knobWidth = Self.knobSize.width
|
||||||
|
return (MFSizeObject(standardSize: knobWidth, standardiPadPortraitSize: CGFloat(Self.knobSize.width * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
class func getKnobHeight() -> CGFloat {
|
||||||
|
let knobHeight = Self.knobSize.width
|
||||||
|
return (MFSizeObject(standardSize: knobHeight, standardiPadPortraitSize: CGFloat(Self.knobSize.height * 1.5)))?.getValueBasedOnApplicationWidth() ?? knobHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Actions
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
|
||||||
|
super.sendAction(action, to: target, for: event)
|
||||||
|
toggleAndAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
open override func sendActions(for controlEvents: UIControl.Event) {
|
||||||
|
super.sendActions(for: controlEvents)
|
||||||
|
toggleAndAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This will toggle the state of the Toggle and execute the actionBlock if provided.
|
||||||
|
public func toggleAndAction() {
|
||||||
|
|
||||||
|
if let result = shouldToggleAction?(), result {
|
||||||
|
isOn.toggle()
|
||||||
|
didToggleAction?()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func changeStateNoAnimation(_ state: Bool) {
|
||||||
|
|
||||||
|
// Hold state in case User wanted isAnimated to remain off.
|
||||||
|
let isAnimatedState = isAnimated
|
||||||
|
|
||||||
|
isAnimated = false
|
||||||
|
isOn = state
|
||||||
|
isAnimated = isAnimatedState
|
||||||
|
}
|
||||||
|
|
||||||
|
override open func accessibilityActivate() -> Bool {
|
||||||
|
// Hold state in case User wanted isAnimated to remain off.
|
||||||
|
guard isUserInteractionEnabled else { return false }
|
||||||
|
let isAnimatedState = isAnimated
|
||||||
|
isAnimated = false
|
||||||
|
sendActions(for: .touchUpInside)
|
||||||
|
isAnimated = isAnimatedState
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - UIResponder
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.1, animations: {
|
||||||
|
self.knobWidthConstraint?.constant += PaddingOne
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
|
||||||
|
|
||||||
|
knobReformAnimation()
|
||||||
|
|
||||||
|
// Action only occurs of the user lifts up from withing acceptable region of the toggle.
|
||||||
|
guard let coordinates = touches.first?.location(in: self),
|
||||||
|
coordinates.x > -20,
|
||||||
|
coordinates.x < bounds.width + 20,
|
||||||
|
coordinates.y > -20,
|
||||||
|
coordinates.y < bounds.height + 20
|
||||||
|
else { return }
|
||||||
|
|
||||||
|
sendActions(for: .touchUpInside)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) {
|
||||||
|
|
||||||
|
knobReformAnimation()
|
||||||
|
sendActions(for: .touchCancel)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
// MARK: - Animations
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
public func setToggleAppearanceFromState() {
|
||||||
|
|
||||||
|
backgroundColor = isEnabled ? isOn ? containerTintColor.on : containerTintColor.off : disabledTintColor.container
|
||||||
|
knobView.backgroundColor = isEnabled ? isOn ? knobTintColor.on : knobTintColor.off : disabledTintColor.knob
|
||||||
|
}
|
||||||
|
|
||||||
|
public func knobReformAnimation() {
|
||||||
|
|
||||||
|
if isAnimated {
|
||||||
|
UIView.animate(withDuration: 0.1, animations: {
|
||||||
|
self.knobWidthConstraint?.constant = Self.getKnobWidth()
|
||||||
|
self.layoutIfNeeded()
|
||||||
|
}, completion: nil)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
knobWidthConstraint?.constant = Self.getKnobWidth()
|
||||||
|
layoutIfNeeded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK:- MoleculeViewProtocol
|
||||||
|
public override func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
||||||
|
super.set(with: model, delegateObject, additionalData)
|
||||||
|
self.delegateObject = delegateObject
|
||||||
|
|
||||||
|
guard let model = model as? ToggleModel else { return }
|
||||||
|
|
||||||
|
FormValidator.setupValidation(for: model, delegate: delegateObject?.formHolderDelegate)
|
||||||
|
|
||||||
|
containerTintColor.on = model.onTintColor.uiColor
|
||||||
|
containerTintColor.off = model.offTintColor.uiColor
|
||||||
|
knobTintColor.on = model.onKnobTintColor.uiColor
|
||||||
|
knobTintColor.off = model.offKnobTintColor.uiColor
|
||||||
|
isOn = model.selected
|
||||||
|
changeStateNoAnimation(isOn)
|
||||||
|
isAnimated = model.animated
|
||||||
|
isEnabled = model.enabled && !model.readOnly
|
||||||
|
|
||||||
|
if let accessibileString = model.accessibilityText {
|
||||||
|
accessibilityLabel = accessibileString
|
||||||
|
}
|
||||||
|
|
||||||
|
if model.action != nil || model.alternateAction != nil {
|
||||||
|
didToggleAction = { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if self.isOn {
|
||||||
|
if let action = model.action {
|
||||||
|
MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: model, additionalData: additionalData, delegateObject: delegateObject)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let action = model.alternateAction ?? model.action {
|
||||||
|
MVMCoreUIActionHandler.performActionUnstructured(with: action, sourceModel: model, additionalData: additionalData, delegateObject: delegateObject)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return the same height as the internal ToggleBase.toggleContainerSize.height
|
public override class func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
||||||
//since this is a class func, we can't reference it directly
|
Self.getContainerHeight()
|
||||||
public static func estimatedHeight(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?) -> CGFloat? {
|
|
||||||
return 44
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - MVMCoreUIViewConstrainingProtocol
|
// MARK: - MVMCoreUIViewConstrainingProtocol
|
||||||
extension Toggle: MVMCoreUIViewConstrainingProtocol {
|
extension Toggle {
|
||||||
|
|
||||||
public func needsToBeConstrained() -> Bool { true }
|
public func needsToBeConstrained() -> Bool { true }
|
||||||
|
|
||||||
public func horizontalAlignment() -> UIStackView.Alignment { .trailing }
|
public func horizontalAlignment() -> UIStackView.Alignment { .trailing }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,15 +13,20 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public static var identifier: String = "toggle"
|
public static var identifier: String = "toggle"
|
||||||
public var backgroundColor: Color? //not used
|
public var accessibilityIdentifier: String?
|
||||||
|
public var backgroundColor: Color?
|
||||||
public var selected: Bool = false
|
public var selected: Bool = false
|
||||||
|
public var animated: Bool = true
|
||||||
public var enabled: Bool = true
|
public var enabled: Bool = true
|
||||||
public var readOnly: Bool = false
|
public var readOnly: Bool = false
|
||||||
public var animated: Bool = true
|
|
||||||
public var action: ActionModelProtocol?
|
public var action: ActionModelProtocol?
|
||||||
public var alternateAction: ActionModelProtocol?
|
public var alternateAction: ActionModelProtocol?
|
||||||
public var accessibilityText: String?
|
public var accessibilityText: String?
|
||||||
|
public var onTintColor: Color = Color(uiColor: .mvmGreen)
|
||||||
|
public var offTintColor: Color = Color(uiColor: .mvmBlack)
|
||||||
|
public var onKnobTintColor: Color = Color(uiColor: .mvmWhite)
|
||||||
|
public var offKnobTintColor: Color = Color(uiColor: .mvmWhite)
|
||||||
|
|
||||||
public var fieldKey: String?
|
public var fieldKey: String?
|
||||||
public var groupName: String = FormValidator.defaultGroupName
|
public var groupName: String = FormValidator.defaultGroupName
|
||||||
public var baseValue: AnyHashable?
|
public var baseValue: AnyHashable?
|
||||||
@ -29,16 +34,22 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// MARK: - Keys
|
// MARK: - Keys
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
private enum CodingKeys: String, CodingKey {
|
private enum CodingKeys: String, CodingKey {
|
||||||
case moleculeName
|
case moleculeName
|
||||||
case state
|
case state
|
||||||
|
case animated
|
||||||
case enabled
|
case enabled
|
||||||
case readOnly
|
case readOnly
|
||||||
case animated
|
|
||||||
case action
|
case action
|
||||||
|
case backgroundColor
|
||||||
|
case accessibilityIdentifier
|
||||||
case alternateAction
|
case alternateAction
|
||||||
case accessibilityText
|
case accessibilityText
|
||||||
|
case onTintColor
|
||||||
|
case offTintColor
|
||||||
|
case onKnobTintColor
|
||||||
|
case offKnobTintColor
|
||||||
case fieldKey
|
case fieldKey
|
||||||
case groupName
|
case groupName
|
||||||
}
|
}
|
||||||
@ -64,7 +75,7 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
|
|
||||||
public init(_ state: Bool) {
|
public init(_ state: Bool) {
|
||||||
selected = state
|
self.selected = state
|
||||||
baseValue = state
|
baseValue = state
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,31 +87,62 @@ public class ToggleModel: MoleculeModelProtocol, FormFieldProtocol {
|
|||||||
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) {
|
||||||
selected = state
|
self.selected = state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) {
|
||||||
|
self.animated = animated
|
||||||
|
}
|
||||||
|
|
||||||
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
action = try typeContainer.decodeModelIfPresent(codingKey: .action)
|
||||||
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
|
alternateAction = try typeContainer.decodeModelIfPresent(codingKey: .alternateAction)
|
||||||
|
backgroundColor = try typeContainer.decodeIfPresent(Color.self, forKey: .backgroundColor)
|
||||||
|
accessibilityIdentifier = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityIdentifier)
|
||||||
|
|
||||||
|
if let onTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onTintColor) {
|
||||||
|
self.onTintColor = onTintColor
|
||||||
|
}
|
||||||
|
|
||||||
|
if let offTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offTintColor) {
|
||||||
|
self.offTintColor = offTintColor
|
||||||
|
}
|
||||||
|
|
||||||
|
if let onKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .onKnobTintColor) {
|
||||||
|
self.onKnobTintColor = onKnobTintColor
|
||||||
|
}
|
||||||
|
|
||||||
|
if let offKnobTintColor = try typeContainer.decodeIfPresent(Color.self, forKey: .offKnobTintColor) {
|
||||||
|
self.offKnobTintColor = offKnobTintColor
|
||||||
|
}
|
||||||
|
|
||||||
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
accessibilityText = try typeContainer.decodeIfPresent(String.self, forKey: .accessibilityText)
|
||||||
|
|
||||||
baseValue = selected
|
baseValue = selected
|
||||||
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
fieldKey = try typeContainer.decodeIfPresent(String.self, forKey: .fieldKey)
|
||||||
groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) ?? FormValidator.defaultGroupName
|
if let groupName = try typeContainer.decodeIfPresent(String.self, forKey: .groupName) {
|
||||||
|
self.groupName = groupName
|
||||||
|
}
|
||||||
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
enabled = try typeContainer.decodeIfPresent(Bool.self, forKey: .enabled) ?? true
|
||||||
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
readOnly = try typeContainer.decodeIfPresent(Bool.self, forKey: .readOnly) ?? false
|
||||||
animated = try typeContainer.decodeIfPresent(Bool.self, forKey: .animated) ?? true
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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(accessibilityIdentifier, forKey: .accessibilityIdentifier)
|
||||||
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.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
|
||||||
try container.encode(moleculeName, forKey: .moleculeName)
|
try container.encode(moleculeName, forKey: .moleculeName)
|
||||||
try container.encode(selected, forKey: .state)
|
try container.encode(selected, forKey: .state)
|
||||||
|
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(onKnobTintColor, forKey: .onKnobTintColor)
|
||||||
|
try container.encode(onKnobTintColor, forKey: .onKnobTintColor)
|
||||||
|
try container.encode(offKnobTintColor, forKey: .offKnobTintColor)
|
||||||
|
try container.encodeIfPresent(accessibilityText, forKey: .accessibilityText)
|
||||||
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
try container.encodeIfPresent(fieldKey, forKey: .fieldKey)
|
||||||
try container.encodeIfPresent(groupName, forKey: .groupName)
|
try container.encodeIfPresent(groupName, forKey: .groupName)
|
||||||
try container.encode(readOnly, forKey: .readOnly)
|
try container.encode(readOnly, forKey: .readOnly)
|
||||||
try container.encode(animated, forKey: .animated)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import MVMCore
|
import MVMCore
|
||||||
import VDS
|
|
||||||
|
|
||||||
public typealias ActionBlock = () -> ()
|
public typealias ActionBlock = () -> ()
|
||||||
|
|
||||||
@ -738,6 +737,36 @@ public typealias ActionBlock = () -> ()
|
|||||||
clauses.append(ActionableClause(range: range, actionBlock: actionBlock, accessibilityID: accessibleAction?.hash ?? -1))
|
clauses.append(ActionableClause(range: range, actionBlock: actionBlock, accessibilityID: accessibleAction?.hash ?? -1))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Provides a text container and layout manager of how the text would appear on screen.
|
||||||
|
They are used in tandem to derive low-level TextKit results of the label.
|
||||||
|
*/
|
||||||
|
public func abstractTextContainer() -> (NSTextContainer, NSLayoutManager, NSTextStorage)? {
|
||||||
|
|
||||||
|
// Must configure the attributed string to translate what would appear on screen to accurately analyze.
|
||||||
|
guard let attributedText = attributedText else { return nil }
|
||||||
|
|
||||||
|
let paragraph = NSMutableParagraphStyle()
|
||||||
|
paragraph.alignment = textAlignment
|
||||||
|
|
||||||
|
let stagedAttributedString = NSMutableAttributedString(attributedString: attributedText)
|
||||||
|
stagedAttributedString.addAttributes([NSAttributedString.Key.paragraphStyle: paragraph], range: NSRange(location: 0, length: attributedText.string.count))
|
||||||
|
|
||||||
|
let textStorage = NSTextStorage(attributedString: stagedAttributedString)
|
||||||
|
let layoutManager = NSLayoutManager()
|
||||||
|
let textContainer = NSTextContainer(size: .zero)
|
||||||
|
|
||||||
|
layoutManager.addTextContainer(textContainer)
|
||||||
|
textStorage.addLayoutManager(layoutManager)
|
||||||
|
|
||||||
|
textContainer.lineFragmentPadding = 0.0
|
||||||
|
textContainer.lineBreakMode = lineBreakMode
|
||||||
|
textContainer.maximumNumberOfLines = numberOfLines
|
||||||
|
textContainer.size = bounds.size
|
||||||
|
|
||||||
|
return (textContainer, layoutManager, textStorage)
|
||||||
|
}
|
||||||
|
|
||||||
public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect {
|
public static func boundingRect(forCharacterRange range: NSRange, in label: Label) -> CGRect {
|
||||||
|
|
||||||
guard let abstractContainer = label.abstractTextContainer() else { return CGRect() }
|
guard let abstractContainer = label.abstractTextContainer() else { return CGRect() }
|
||||||
|
|||||||
@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// VDSMoleculeViewProtocol.swift
|
|
||||||
// MVMCoreUI
|
|
||||||
//
|
|
||||||
// Created by Matt Bruce on 10/19/22.
|
|
||||||
// Copyright © 2022 Verizon Wireless. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import MVMCore
|
|
||||||
|
|
||||||
///-----------------------------------------------------------------------------
|
|
||||||
///MARK: -- VDSMoleculeViewProtocol (Contract between VDS -> Atomic)
|
|
||||||
///-----------------------------------------------------------------------------
|
|
||||||
public protocol VDSMoleculeViewProtocol: MoleculeViewProtocol, MVMCoreViewProtocol {
|
|
||||||
associatedtype ViewModel: MoleculeModelProtocol
|
|
||||||
var viewModel: ViewModel! { get set }
|
|
||||||
var delegateObject: MVMCoreUIDelegateObject? { get set }
|
|
||||||
var additionalData: [AnyHashable: Any]? { get set }
|
|
||||||
func viewModelDidUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
extension VDSMoleculeViewProtocol {
|
|
||||||
public func set(with model: MoleculeModelProtocol, _ delegateObject: MVMCoreUIDelegateObject?, _ additionalData: [AnyHashable: Any]?) {
|
|
||||||
guard let castedModel = model as? ViewModel else { return }
|
|
||||||
self.delegateObject = delegateObject
|
|
||||||
self.additionalData = additionalData
|
|
||||||
viewModel = castedModel
|
|
||||||
viewModelDidUpdate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -15,10 +15,6 @@ UNIVERSAL_OUTPUTFOLDER="${BUILD_DIR}/universal"
|
|||||||
# Update to use .xcframework
|
# Update to use .xcframework
|
||||||
sed -i '' 's|MVMCore.framework \*\/ = {isa.*};|MVMCore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = MVMCore.xcframework; path = ../SharedFrameworks/MVMCore.xcframework; sourceTree = "<group>"; };|g' ./MVMCoreUI.xcodeproj/project.pbxproj
|
sed -i '' 's|MVMCore.framework \*\/ = {isa.*};|MVMCore.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = MVMCore.xcframework; path = ../SharedFrameworks/MVMCore.xcframework; sourceTree = "<group>"; };|g' ./MVMCoreUI.xcodeproj/project.pbxproj
|
||||||
sed -i '' 's/MVMCore.framework/MVMCore.xcframework/g' ./MVMCoreUI.xcodeproj/project.pbxproj
|
sed -i '' 's/MVMCore.framework/MVMCore.xcframework/g' ./MVMCoreUI.xcodeproj/project.pbxproj
|
||||||
|
|
||||||
sed -i '' 's|VDS.framework \*\/ = {isa.*};|VDS.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = VDS.xcframework; path = ../SharedFrameworks/VDS.xcframework; sourceTree = "<group>"; };|g' ./MVMCoreUI.xcodeproj/project.pbxproj
|
|
||||||
sed -i '' 's/VDS.framework/VDS.xcframework/g' ./MVMCoreUI.xcodeproj/project.pbxproj
|
|
||||||
|
|
||||||
sed -i '' "s|path = \.\.\/SharedFrameworks|path = ${FRAMEWORKS_DIR}|g" ./MVMCoreUI.xcodeproj/project.pbxproj
|
sed -i '' "s|path = \.\.\/SharedFrameworks|path = ${FRAMEWORKS_DIR}|g" ./MVMCoreUI.xcodeproj/project.pbxproj
|
||||||
|
|
||||||
# Build device archive
|
# Build device archive
|
||||||
|
|||||||
@ -18,13 +18,8 @@ if [ ! -d $FRAMEWORKS_DIR ]; then
|
|||||||
mkdir -p $FRAMEWORKS_DIR
|
mkdir -p $FRAMEWORKS_DIR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/MVMCore.xcframework" BPHV_MobileFirst_IOS/com/vzw/hss/myverizon/MVMCore/3.1/MVMCore-3.1-Debug-SNAPSHOT.zip
|
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/MVMCore.xcframework" BPHV_MobileFirst_IOS/com/vzw/hss/myverizon/MVMCore/3.0/MVMCore-3.0-Debug-SNAPSHOT.zip
|
||||||
|
|
||||||
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDS.xcframework" BPHV_MobileFirst_IOS/com/vzw/hss/myverizon/VDS/1.0/VDS-1.0-Debug-SNAPSHOT.zip
|
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSColorTokens.xcframework" GVJV_VDS_Maven/%40vds-tokens/ios/VDSColorTokens.1.0.6.xcframework.zip
|
||||||
|
|
||||||
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSColorTokens.xcframework" GVJV_VDS_Maven/@vds-tokens/ios/VDSColorTokens.1.0.6.xcframework.zip
|
|
||||||
|
|
||||||
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSFormControlsTokens.xcframework" GVJV_VDS_Maven/@vds-tokens/ios/VDSFormControlsTokens.1.0.7.xcframework.zip
|
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSFormControlsTokens.xcframework" GVJV_VDS_Maven/@vds-tokens/ios/VDSFormControlsTokens.1.0.7.xcframework.zip
|
||||||
|
|
||||||
./Scripts/download_framework.sh $ARTIFACTORY_URL "$FRAMEWORKS_DIR/VDSTypographyTokens.xcframework" GVJV_VDS_Maven/@vds-tokens/ios/VDSTypographyTokens.2.0.0.xcframework.zip
|
|
||||||
|
|
||||||
|
|||||||
@ -48,7 +48,7 @@ fi
|
|||||||
echo -e "Getting checksums..."
|
echo -e "Getting checksums..."
|
||||||
echo -e "URL: ${URL}/api/storage/${REMOTEPATH}"
|
echo -e "URL: ${URL}/api/storage/${REMOTEPATH}"
|
||||||
JSON=$(curl --header "X-JFrog-Art-Api: ${ARTIFACTORY_APIKEY}" -X GET "${URL}/api/storage/${REMOTEPATH}")
|
JSON=$(curl --header "X-JFrog-Art-Api: ${ARTIFACTORY_APIKEY}" -X GET "${URL}/api/storage/${REMOTEPATH}")
|
||||||
CHECKSUM=$(echo "$JSON" | python3 -c 'import sys, json; print (json.load(sys.stdin)["checksums"]["sha1"])')
|
CHECKSUM=$(echo "$JSON" | python -c 'import sys, json; print json.load(sys.stdin)["checksums"]["sha1"]')
|
||||||
if [[ -z "$CHECKSUM" ]]; then
|
if [[ -z "$CHECKSUM" ]]; then
|
||||||
exit_with_error "No Checksum found in json: ${JSON}"
|
exit_with_error "No Checksum found in json: ${JSON}"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user