From a3ddaae1545d5e5757b07302d095b7eeb0eb2090 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 26 Apr 2022 21:17:59 +0100 Subject: [PATCH 01/55] PI-1738: Billing form component: standard --- Source/CheckoutColor.swift | 23 +++ Source/Extensions/StringExtensions.swift | 19 ++ Source/Resources/warning/warning.pdf | Bin 0 -> 2501 bytes .../UI/Controllers/CardViewController.swift | 22 ++- .../Factory/BillingFormFactory.swift | 22 +++ .../Cell/BillingFormHeaderCellStyle.swift | 8 + .../Cell/BillingFormTextFieldCellStyle.swift | 10 + .../DefaultFormStyleAddressLine1Cell.swift | 23 +++ .../DefaultFormStyleAddressLine2Cell.swift | 22 +++ .../City/DefaultFormStyleCityCell.swift | 22 +++ .../Country/DefaultFormStyleCountryCell.swift | 22 +++ .../DefaultFormStyleFullNameCell.swift | 22 +++ .../DefaultFormStylePhoneNumberCell.swift | 23 +++ .../DefaultFormStylePostcodedCell.swift | 22 +++ .../State/DefaultFormStyleStateCell.swift | 22 +++ .../Cancel/DefaultCancelButtonFormStyle.swift | 36 ++++ .../Done/DefaultDoneFormButtonStyle.swift | 36 ++++ .../DefaultBillingFormHeaderCellStyle.swift | 15 ++ .../Title/DefaultHeaderLabelFormStyle.swift | 8 + .../Main/DefaultBillingFormStyle.swift | 15 ++ .../Error/DefaultErrorInputLabelStyle.swift | 30 +++ .../Hint/DefaultHintInputLabelStyle.swift | 19 ++ .../Elements/TextField/DefaultTextField.swift | 48 +++++ .../Title/DefaultTitleLabelStyle.swift | 18 ++ .../Style/Protocols/BillingFormStyle.swift | 7 + .../Protocols/ErrorInputLabelStyle.swift | 13 ++ .../Style/Protocols/FormButtonStyle.swift | 15 ++ .../Style/Protocols/FormTextFieldStyle.swift | 19 ++ .../Style/Protocols/InputLabelStyle.swift | 9 + .../Error/BillingFormTextFieldErrorView.swift | 68 +++++++ .../View/Field/BillFormTextField.swift | 13 ++ .../Field/BillingFormPhoneNumberText.swift | 86 +++++++++ .../View/Field/BillingFormTextFieldView.swift | 171 ++++++++++++++++++ .../Fields/BillingFormTextFieldCell.swift | 74 ++++++++ .../Header/BillingFormHeaderCell.swift | 138 ++++++++++++++ .../BillingFormViewController.swift | 171 ++++++++++++++++++ .../ViewModel/BillingFormCellType.swift | 25 +++ .../ViewModel/BillingFormViewModel.swift | 19 ++ .../DefaultBillingFormViewModel.swift | 119 ++++++++++++ Source/UI/UITableView.swift | 10 + Source/Validator/AddressLine1Validator.swift | 13 ++ Source/Validator/AddressLine2Validator.swift | 13 ++ Source/Validator/CityValidator.swift | 13 ++ Source/Validator/CountryValidator.swift | 13 ++ Source/Validator/FullNameValidator.swift | 13 ++ Source/Validator/PhoneNumberValidator.swift | 13 ++ Source/Validator/PostCodeValidator.swift | 13 ++ Source/Validator/StateValidator.swift | 13 ++ Source/Validator/Validator.swift | 5 + .../AddressViewControllerMockDelegate.swift | 2 +- ...BillingFormTextFieldCellMockDelegate.swift | 37 ++++ ...illingFormViewControllerMockDelegate.swift | 69 +++++++ ...lingFormViewModelEditingMockDelegate.swift | 12 ++ .../BillingFormViewModelMockDelegate.swift | 14 ++ .../AddressLine1ValidatorTests.swift | 19 ++ .../AddressLine2ValidatorTests.swift | 19 ++ .../Validator/CityValidatorTests.swift | 19 ++ .../Validator/CountryValidatorTests.swift | 19 ++ .../Validator/FullNameValidatorTests.swift | 19 ++ .../Validator/PhoneNumberValidatorTests.swift | 19 ++ .../Validator/PostCodeValidatorTests.swift | 19 ++ .../Validator/StateValidatorTests.swift | 19 ++ ...illingFormFullNameTextFieldCellTests.swift | 55 ++++++ .../BillingFormTextFieldErrorViewTests.swift | 44 +++++ .../View/BillingFormTextFieldViewTests.swift | 38 ++++ .../BillingFormViewControllerTests.swift | 110 +++++++++++ .../ViewModel/BillingFormCellTypeTests.swift | 39 ++++ .../ViewModel/BillingFormViewModelTests.swift | 115 ++++++++++++ .../AppIcon.appiconset/100.png | Bin 0 -> 3730 bytes .../AppIcon.appiconset/1024.png | Bin 0 -> 122426 bytes .../AppIcon.appiconset/114.png | Bin 0 -> 4426 bytes .../AppIcon.appiconset/120.png | Bin 0 -> 4706 bytes .../AppIcon.appiconset/144.png | Bin 0 -> 5964 bytes .../AppIcon.appiconset/152.png | Bin 0 -> 6668 bytes .../AppIcon.appiconset/167.png | Bin 0 -> 7022 bytes .../AppIcon.appiconset/180.png | Bin 0 -> 7758 bytes .../Assets.xcassets/AppIcon.appiconset/20.png | Bin 0 -> 840 bytes .../Assets.xcassets/AppIcon.appiconset/29.png | Bin 0 -> 946 bytes .../Assets.xcassets/AppIcon.appiconset/40.png | Bin 0 -> 1134 bytes .../Assets.xcassets/AppIcon.appiconset/50.png | Bin 0 -> 1302 bytes .../Assets.xcassets/AppIcon.appiconset/57.png | Bin 0 -> 1460 bytes .../Assets.xcassets/AppIcon.appiconset/58.png | Bin 0 -> 1512 bytes .../Assets.xcassets/AppIcon.appiconset/60.png | Bin 0 -> 1492 bytes .../Assets.xcassets/AppIcon.appiconset/72.png | Bin 0 -> 2500 bytes .../Assets.xcassets/AppIcon.appiconset/76.png | Bin 0 -> 2662 bytes .../Assets.xcassets/AppIcon.appiconset/80.png | Bin 0 -> 2852 bytes .../Assets.xcassets/AppIcon.appiconset/87.png | Bin 0 -> 3174 bytes .../AppIcon.appiconset/Contents.json | 99 +--------- .../Assets.xcassets/Contents.json | 6 +- .../logo.imageset/Contents.json | 21 +++ .../logo.imageset/playstore.png | Bin 0 -> 33636 bytes .../Base.lproj/LaunchScreen.storyboard | 31 +++- .../Base.lproj/Main.storyboard | 99 +++++++--- .../MainViewController.swift | 37 ++-- 94 files changed, 2402 insertions(+), 151 deletions(-) create mode 100644 Source/CheckoutColor.swift create mode 100644 Source/Resources/warning/warning.pdf create mode 100644 Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Fullname/DefaultFormStyleFullNameCell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodedCell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Main/DefaultBillingFormStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Error/DefaultErrorInputLabelStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Hint/DefaultHintInputLabelStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/TextField/DefaultTextField.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Title/DefaultTitleLabelStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Protocols/BillingFormStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift create mode 100644 Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift create mode 100644 Source/UI/NewUI/BillingForm/View/Field/BillFormTextField.swift create mode 100644 Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift create mode 100644 Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift create mode 100644 Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift create mode 100644 Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift create mode 100644 Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift create mode 100644 Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift create mode 100644 Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift create mode 100644 Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift create mode 100644 Source/UI/UITableView.swift create mode 100644 Source/Validator/AddressLine1Validator.swift create mode 100644 Source/Validator/AddressLine2Validator.swift create mode 100644 Source/Validator/CityValidator.swift create mode 100644 Source/Validator/CountryValidator.swift create mode 100644 Source/Validator/FullNameValidator.swift create mode 100644 Source/Validator/PhoneNumberValidator.swift create mode 100644 Source/Validator/PostCodeValidator.swift create mode 100644 Source/Validator/StateValidator.swift create mode 100644 Source/Validator/Validator.swift create mode 100644 Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift create mode 100644 Tests/Mocks/BillingFormViewControllerMockDelegate.swift create mode 100644 Tests/Mocks/BillingFormViewModelEditingMockDelegate.swift create mode 100644 Tests/Mocks/BillingFormViewModelMockDelegate.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift create mode 100644 Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift create mode 100644 Tests/UI/New UI/BillingForm/View/BillingFormTextFieldErrorViewTests.swift create mode 100644 Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift create mode 100644 Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift create mode 100644 Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift create mode 100644 Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/144.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/180.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/20.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/50.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/57.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/76.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/80.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json create mode 100644 iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png diff --git a/Source/CheckoutColor.swift b/Source/CheckoutColor.swift new file mode 100644 index 00000000..625fa5ed --- /dev/null +++ b/Source/CheckoutColor.swift @@ -0,0 +1,23 @@ +import UIKit + +extension UIColor { +// Blue + //#0B5FF0 + public static var brandeisBlue = UIColor(red: 11/255, green: 95/255, blue: 240/255, alpha: 1) + +// Gray + //#636363 + public static var doveGray = UIColor(red: 99/255, green: 99/255, blue: 99/255, alpha: 1) + + //#141414 + public static var codGray = UIColor(red: 20/255, green: 20/255, blue: 20/255, alpha: 1) + + //#8A8A8A + public static var mediumGray = UIColor(red: 138/255, green: 138/255, blue: 138/255, alpha: 1) + +// Red + //#AD283E + public static var tallPoppy = UIColor(red: 173/255, green: 40/255, blue: 62/255, alpha: 1) + +} + diff --git a/Source/Extensions/StringExtensions.swift b/Source/Extensions/StringExtensions.swift index 8ef50012..b102999d 100644 --- a/Source/Extensions/StringExtensions.swift +++ b/Source/Extensions/StringExtensions.swift @@ -22,4 +22,23 @@ extension String { let bundle = getBundle(forClass: forClass) return UIImage(named: self, in: bundle, compatibleWith: nil) ?? UIImage() } + + //https://www.hackingwithswift.com/example-code/core-graphics/how-to-render-a-pdf-to-an-image + func vectorPDFImage(forClass: AnyClass) -> UIImage? { + let bundle = getBundle(forClass: forClass) + guard let urlPath = bundle.url(forResource: self, withExtension: "pdf") else { return nil } + guard let document = CGPDFDocument(urlPath as CFURL) else { return nil } + guard let page = document.page(at: 1) else { return nil } + + let pageRect = page.getBoxRect(.mediaBox) + let renderer = UIGraphicsImageRenderer(size: pageRect.size) + + return renderer.image { + UIColor.white.set() + $0.fill(pageRect) + $0.cgContext.translateBy(x: 0.0, y: pageRect.size.height) + $0.cgContext.scaleBy(x: 1.0, y: -1.0) + $0.cgContext.drawPDFPage(page) + } + } } diff --git a/Source/Resources/warning/warning.pdf b/Source/Resources/warning/warning.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3f1e62ca96c4a5492ec6f3dce7c6cc95a0cfbde6 GIT binary patch literal 2501 zcmZveO^+Kz5QgvbEBX>CIi%gyAJyGb6p3sILVySxZV?CLog|BPZLl2_`1L$Bo}JhU zKCEWn>8g6`t&g5ZuV21;D!vYbxZrlb|1miC?3sK1d>FSk_U{nS@zsyx_WkjLOMusQ z>TukT>-%B#a{T*tGhTo9!d<;N|8H{`{u;!G>F2`3!_(#If8R+K4bg4xhv2ogoFM0= zXj20F$p5Lj!)7~FpCp!$oMc~B&FFq8zNyAo&%o?+!7Lb*Qms5C{PfnNlmp$CCCA-hO|V+tBdcF{c5R(OalrDk@?<2x4;@KK=}ageoU znFwl*njKQK(nB%TT9nYSL$i=m7vpDT$py-_W(6{SxhfQRlF+JIYHu-FL=@m{FnP#Z zz)h#p;98AhLr!#pb&nd0(eILbG1Kg&tKcU4(sPL2O2HvSGciJKkxUi{#Yz_I0W;Mo zv8n6kI2CG=e9K+yR1|y&MS)4KFyU>)070xOP$rFHl#}mWqITS1Qp?;Q5rrtwSA8@I z^<{J24Ic*e6wYX)QH$M3-d}*7Twtrd1#}<`9HJzoQCcHcD;WYtB?l;0S|LQL0GJX= zH|U6_L?I2Ln+Wll;R2ayR$7iSEMTRHs9?PCRv}rC;38_1LbDh+v#XwZ&xy@BoI`W2 z7Ii*Hh9`1&=UB~=UWM=+Kq+`T^$xwl-fgUG=H8#1t$!ft=J`QeP0Wn-yBH zMaIR`qV`$5r6>!lrJOvRn4ckYew&N>&O%r(EY#Q`GOr(~F_lyM&lp4+%f<$Ry}?vj zZ{%d^C$FW|Zhb)5z(%TIwMb!}jU!EBr_d%&b_G#dV2T3vtV6T2(Uk_q)==69gssG| zv+R_~v3S`A#&!&EI^$w?MQVw*HfSMbC0e}Nnt-&_dNl^Dz}D}c;28hf9bva`8aDi@1JsALDG%QzgUSO{3)i>Mi?s#x-f8*-rxBB&;KS#HEy?#H=z)$1N?fS*; zlY7fDpDyC?`Qc&ZPFLf!kAr*gbUhw+ANQN_;OyhzdUkiU+aAX)5$((10erpQgE_8? z2|D|JFlhO%Sp9H&165}kTrY91b|0~oulOH8&OGUbCrj|K1pJ)%)%v);+r7Uu{j?w7 z4Z+pnl)n9SN~;zJJpTk$?B})%#1(%DNiScX5}Sa_Q&DK{FCbcefsXt2?cKN^ta{(S zM2^RY-TnB)J-)qpauQ{Az1tm~B|HhddUN~l2>a=SYrQ{C>F|ZqhewaT{rS~@IUNFc literal 0 HcmV?d00001 diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index f586bb4f..d171c1be 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -43,7 +43,7 @@ public class CardViewController: UIViewController, var topConstraint: NSLayoutConstraint? private var loggedForCurrentCorrelationID = false - + public var isNewUI: Bool = false // MARK: - Initialization /// Returns a newly initialized view controller with the cardholder's name and billing details @@ -160,7 +160,12 @@ public class CardViewController: UIViewController, } @objc func onTapAddressView() { - navigationController?.pushViewController(addressViewController, animated: true) + guard isNewUI else { + navigationController?.pushViewController(addressViewController, animated: true) + return + } + let viewController = BillingFormFactory.getBillingFormViewController(delegate: self) + navigationController?.present(viewController, animated: true) checkoutApiClient?.logger.log(.billingFormPresented) loggedForCurrentCorrelationID = true } @@ -339,3 +344,16 @@ public class CardViewController: UIViewController, } } } + + +extension CardViewController: BillingFormViewModelDelegate { + func onTapDoneButton(address: CkoAddress, phone: CkoPhoneNumber) { + billingDetailsAddress = address + billingDetailsPhone = phone + let value = "\(address.addressLine1 ?? ""), \(address.city ?? "")" + cardView.billingDetailsInputView.value.text = value + validateFieldsValues() + // return to CardViewController + self.topConstraint?.isActive = false + } +} diff --git a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift new file mode 100644 index 00000000..9a219dc3 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift @@ -0,0 +1,22 @@ +import UIKit + +struct BillingFormFactory { + // in order + static let styles: [BillingFormTextFieldCellStyle] = [ + DefaultFormStyleFullNameCell(), + DefaultFormStyleAddressLine1Cell(), + DefaultFormStyleAddressLine2Cell(), + DefaultFormStyleCityCell(), + DefaultFormStyleStateCell(), + DefaultFormStylePostcodedCell(), + DefaultFormStyleCountryCell(), + DefaultFormStylePhoneNumberCell() + ] + + static func getBillingFormViewController(delegate: BillingFormViewModelDelegate) -> UIViewController { + let style = DefaultBillingFormStyle() + let viewModel = DefaultBillingFormViewModel(style: style, initialCountry: "", delegate: delegate) + return BillingFormViewController(viewModel: viewModel) + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift new file mode 100644 index 00000000..2118ea37 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift @@ -0,0 +1,8 @@ +import Foundation + +// Header Cell +public protocol BillingFormHeaderCellStyle { + var headerLabel: InputLabelStyle { get } + var cancelButton: FormButtonStyle { get } + var doneButton: FormButtonStyle { get set} +} diff --git a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift new file mode 100644 index 00000000..ba3e3616 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift @@ -0,0 +1,10 @@ +import UIKit + +// Field Cell +public protocol BillingFormTextFieldCellStyle { + var backgroundColor: UIColor { get } + var title: InputLabelStyle? { get } + var hint: InputLabelStyle? { get } + var textfield: TextFieldStyle { get set } + var error: ErrorInputLabelStyle { get set } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift new file mode 100644 index 00000000..54c93ab3 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift @@ -0,0 +1,23 @@ +import UIKit + +//Address line 1 +struct DefaultFormStyleAddressLine1Cell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "Address line 1"), + hint: InputLabelStyle? = nil, + textfield: TextFieldStyle = DefaultTextField(), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Address line 1")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift new file mode 100644 index 00000000..3a2b61ba --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift @@ -0,0 +1,22 @@ +import UIKit + +struct DefaultFormStyleAddressLine2Cell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "Address line 2"), + hint: InputLabelStyle? = nil, + textfield: TextFieldStyle = DefaultTextField(), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Address line 2")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift new file mode 100644 index 00000000..ef38ba4f --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift @@ -0,0 +1,22 @@ +import UIKit + +struct DefaultFormStyleCityCell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "City"), + hint: InputLabelStyle? = nil, + textfield: TextFieldStyle = DefaultTextField(), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing City")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift new file mode 100644 index 00000000..6b81af4a --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift @@ -0,0 +1,22 @@ +import UIKit + +struct DefaultFormStyleCountryCell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "Country"), + hint: InputLabelStyle? = nil, + textfield: TextFieldStyle = DefaultTextField(), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Country")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Fullname/DefaultFormStyleFullNameCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Fullname/DefaultFormStyleFullNameCell.swift new file mode 100644 index 00000000..95b2e44a --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Fullname/DefaultFormStyleFullNameCell.swift @@ -0,0 +1,22 @@ +import UIKit + +struct DefaultFormStyleFullNameCell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "Full name"), + hint: InputLabelStyle? = nil, + textfield: TextFieldStyle = DefaultTextField(), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Full name")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift new file mode 100644 index 00000000..0a579f7a --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift @@ -0,0 +1,23 @@ +import UIKit + +struct DefaultFormStylePhoneNumberCell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "Phone number"), + hint: InputLabelStyle? = DefaultHintInputLabelStyle(isHidden: false, + text: "We will only use this to confirm identity if neccessary"), + textfield: TextFieldStyle = DefaultTextField(isSupprtingNumbericKeyboard: true), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Phone number")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodedCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodedCell.swift new file mode 100644 index 00000000..bbf25b98 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodedCell.swift @@ -0,0 +1,22 @@ +import UIKit + +struct DefaultFormStylePostcodedCell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "Postcode/Zip"), + hint: InputLabelStyle? = nil, + textfield: TextFieldStyle = DefaultTextField(), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Postcode/Zip")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift new file mode 100644 index 00000000..08f26287 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift @@ -0,0 +1,22 @@ +import UIKit + +struct DefaultFormStyleStateCell : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor + var title: InputLabelStyle? + var hint: InputLabelStyle? + var textfield: TextFieldStyle + var error: ErrorInputLabelStyle + + init(backgroundColor: UIColor = .white, + header: InputLabelStyle = DefaultTitleLabelStyle(text: "State"), + hint: InputLabelStyle? = nil, + textfield: TextFieldStyle = DefaultTextField(), + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing State")) { + self.backgroundColor = backgroundColor + self.title = header + self.hint = hint + self.textfield = textfield + self.error = error + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift new file mode 100644 index 00000000..b321fe08 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift @@ -0,0 +1,36 @@ +import UIKit + +struct DefaultCancelButtonFormStyle: FormButtonStyle { + var isEnabled: Bool + var text: String + var font: UIFont + var activeTitleColor: UIColor + var inActiveTitleColor: UIColor + var inActiveTintColor: UIColor + var activeTintColor: UIColor + var backgroundColor: UIColor + var hight: Double + var width: Double + + init( isEnabled: Bool = true, + text: String = "Cancel", + font: UIFont = UIFont.systemFont(ofSize: 17), + activeTitleColor: UIColor = .brandeisBlue, + inActiveTitleColor: UIColor = .doveGray, + inActiveTintColor: UIColor = .doveGray, + activeTintColor: UIColor = .brandeisBlue, + backgroundColor: UIColor = .white, + hight: Double = 44, + width: Double = 53) { + self.isEnabled = isEnabled + self.text = text + self.font = font + self.activeTitleColor = activeTitleColor + self.inActiveTitleColor = inActiveTitleColor + self.inActiveTintColor = inActiveTintColor + self.activeTintColor = activeTintColor + self.backgroundColor = backgroundColor + self.hight = hight + self.width = width + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift new file mode 100644 index 00000000..c3c0c8c0 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift @@ -0,0 +1,36 @@ +import UIKit + +struct DefaultDoneFormButtonStyle: FormButtonStyle { + var isEnabled: Bool + var text: String + var font: UIFont + var activeTitleColor: UIColor + var inActiveTitleColor: UIColor + var inActiveTintColor: UIColor + var activeTintColor: UIColor + var backgroundColor: UIColor + var hight: Double + var width: Double + + init( isEnabled: Bool = true, + text: String = "Done", + font: UIFont = UIFont.systemFont(ofSize: 17), + activeTitleColor: UIColor = .brandeisBlue, + inActiveTitleColor: UIColor = .doveGray, + inActiveTintColor: UIColor = .doveGray, + activeTintColor: UIColor = .brandeisBlue, + backgroundColor: UIColor = .white, + hight: Double = 44, + width: Double = 53) { + self.isEnabled = isEnabled + self.text = text + self.font = font + self.activeTitleColor = activeTitleColor + self.inActiveTitleColor = inActiveTitleColor + self.inActiveTintColor = inActiveTintColor + self.activeTintColor = activeTintColor + self.backgroundColor = backgroundColor + self.hight = hight + self.width = width + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift new file mode 100644 index 00000000..fef1fc0f --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift @@ -0,0 +1,15 @@ +import Foundation + +// Header Cell +struct DefaultBillingFormHeaderCellStyle: BillingFormHeaderCellStyle { + var headerLabel: InputLabelStyle + var cancelButton: FormButtonStyle + var doneButton: FormButtonStyle + init(headerLabel: InputLabelStyle = DefaultHeaderLabelFormStyle(), + cancelButton: FormButtonStyle = DefaultCancelButtonFormStyle(), + doneButton: FormButtonStyle = DefaultDoneFormButtonStyle()) { + self.headerLabel = headerLabel + self.doneButton = doneButton + self.cancelButton = cancelButton + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift new file mode 100644 index 00000000..629846be --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift @@ -0,0 +1,8 @@ +import UIKit + +struct DefaultHeaderLabelFormStyle: InputLabelStyle { + var isHidden: Bool { false } + var text: String { "Billing address" } + var font: UIFont { UIFont.systemFont(ofSize: 24) } + var textColor: UIColor { .codGray } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Main/DefaultBillingFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Main/DefaultBillingFormStyle.swift new file mode 100644 index 00000000..7be26350 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Main/DefaultBillingFormStyle.swift @@ -0,0 +1,15 @@ +import UIKit + +struct DefaultBillingFormStyle: BillingFormStyle { + var mainBackground: UIColor + var header: BillingFormHeaderCellStyle + var fields: [BillingFormTextFieldCellStyle] + + init(mainBackground: UIColor = .white, + header: BillingFormHeaderCellStyle = DefaultBillingFormHeaderCellStyle(), + fields: [BillingFormTextFieldCellStyle] = BillingFormFactory.styles) { + self.mainBackground = mainBackground + self.header = header + self.fields = fields + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Error/DefaultErrorInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Error/DefaultErrorInputLabelStyle.swift new file mode 100644 index 00000000..cf605bcb --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Error/DefaultErrorInputLabelStyle.swift @@ -0,0 +1,30 @@ +import UIKit + +struct DefaultErrorInputLabelStyle: ErrorInputLabelStyle { + var isHidden: Bool + var backgroundColor: UIColor + var tintColor: UIColor + var text: String + var font: UIFont + var textColor: UIColor + var isWarningSympoleOnLeft: Bool + var height: Double + + init(isHidden: Bool = true, + backgroundColor: UIColor = .white, + tintColor: UIColor = .tallPoppy, + text: String = "", + font: UIFont = UIFont.systemFont(ofSize: 15), + textColor: UIColor = .tallPoppy, + isWarningSympoleOnLeft: Bool = true, + height: Double = 18.0) { + self.isHidden = isHidden + self.backgroundColor = backgroundColor + self.tintColor = tintColor + self.text = text + self.font = font + self.textColor = textColor + self.isWarningSympoleOnLeft = isWarningSympoleOnLeft + self.height = height + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Hint/DefaultHintInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Hint/DefaultHintInputLabelStyle.swift new file mode 100644 index 00000000..8ad35116 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Hint/DefaultHintInputLabelStyle.swift @@ -0,0 +1,19 @@ +import UIKit + +// hint element +struct DefaultHintInputLabelStyle: InputLabelStyle { + var isHidden: Bool + var text: String + var font: UIFont + var textColor: UIColor + + init(isHidden: Bool = false, + text: String = "", + font: UIFont = UIFont.systemFont(ofSize: 13), + textColor: UIColor = .doveGray) { + self.isHidden = isHidden + self.text = text + self.font = font + self.textColor = textColor + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/TextField/DefaultTextField.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/TextField/DefaultTextField.swift new file mode 100644 index 00000000..2e2b420f --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/TextField/DefaultTextField.swift @@ -0,0 +1,48 @@ +import UIKit + +struct DefaultTextField: TextFieldStyle { + var text: String + var placeHolder: String + var isPlaceHolderHidden: Bool + var font: UIFont + var textColor: UIColor + var normalBorderColor: UIColor + var focusBorderColor: UIColor + var errorBorderColor: UIColor + var backgroundColor: UIColor + var tintColor: UIColor + var width: Double + var height: Double + var isSecured: Bool + var isSupprtingNumbericKeyboard: Bool + + init(text: String = "", + placeHolder: String = "", + isPlaceHolderHidden: Bool = false, + font: UIFont = UIFont.systemFont(ofSize: 16), + textColor: UIColor = .codGray, + normalBorderColor: UIColor = .mediumGray, + focusBorderColor: UIColor = .brandeisBlue, + errorBorderColor: UIColor = .tallPoppy, + backgroundColor: UIColor = .white, + tintColor: UIColor = .codGray, + width: Double = 335.0, + height: Double = 56.0, + isSecured: Bool = false, + isSupprtingNumbericKeyboard: Bool = false) { + self.text = text + self.placeHolder = placeHolder + self.isPlaceHolderHidden = isPlaceHolderHidden + self.font = font + self.textColor = textColor + self.normalBorderColor = normalBorderColor + self.focusBorderColor = focusBorderColor + self.errorBorderColor = errorBorderColor + self.backgroundColor = backgroundColor + self.tintColor = tintColor + self.width = width + self.height = height + self.isSecured = isSecured + self.isSupprtingNumbericKeyboard = isSupprtingNumbericKeyboard + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Title/DefaultTitleLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Title/DefaultTitleLabelStyle.swift new file mode 100644 index 00000000..fb660602 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Title/DefaultTitleLabelStyle.swift @@ -0,0 +1,18 @@ +import UIKit + +struct DefaultTitleLabelStyle: InputLabelStyle { + var isHidden: Bool + var text: String + var font: UIFont + var textColor: UIColor + + init(isHidden: Bool = false, + text: String = "", + font: UIFont = UIFont.systemFont(ofSize: 15), + textColor: UIColor = .codGray) { + self.isHidden = isHidden + self.text = text + self.font = font + self.textColor = textColor + } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/BillingFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/BillingFormStyle.swift new file mode 100644 index 00000000..6cd4706a --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/BillingFormStyle.swift @@ -0,0 +1,7 @@ +import UIKit + +protocol BillingFormStyle { + var mainBackground: UIColor { get } + var header: BillingFormHeaderCellStyle { get set } + var fields: [BillingFormTextFieldCellStyle] { get } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift new file mode 100644 index 00000000..3239a3a6 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift @@ -0,0 +1,13 @@ +import UIKit + +// Error element +public protocol ErrorInputLabelStyle { + var isHidden: Bool { get set } + var text: String { get } + var font: UIFont { get } + var textColor: UIColor { get } + var backgroundColor: UIColor { get } + var tintColor: UIColor { get } + var isWarningSympoleOnLeft: Bool { get } + var height: Double { get } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift new file mode 100644 index 00000000..82560292 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift @@ -0,0 +1,15 @@ +import UIKit + +//Button element +public protocol FormButtonStyle { + var text: String { get } + var font: UIFont { get } + var isEnabled: Bool { get set} + var activeTitleColor: UIColor { get } + var inActiveTitleColor: UIColor { get } + var inActiveTintColor: UIColor { get } + var activeTintColor: UIColor { get } + var backgroundColor: UIColor { get } + var hight: Double { get } + var width: Double { get } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift new file mode 100644 index 00000000..9cb8c793 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift @@ -0,0 +1,19 @@ +import UIKit + +// TextField element +public protocol TextFieldStyle { + var text: String { get set } + var placeHolder: String { get } + var isPlaceHolderHidden: Bool { get } + var font: UIFont { get } + var textColor: UIColor { get } + var normalBorderColor: UIColor { get } + var focusBorderColor: UIColor { get } + var errorBorderColor: UIColor { get } + var backgroundColor: UIColor { get } + var tintColor: UIColor { get } + var width: Double { get } + var height: Double { get } + var isSecured: Bool { get } + var isSupprtingNumbericKeyboard: Bool { get } +} diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift new file mode 100644 index 00000000..3eccf956 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift @@ -0,0 +1,9 @@ +import UIKit + +// Label element +public protocol InputLabelStyle { + var isHidden: Bool { get } + var text: String { get } + var font: UIFont { get } + var textColor: UIColor { get } +} diff --git a/Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift b/Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift new file mode 100644 index 00000000..5d17d8b8 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift @@ -0,0 +1,68 @@ +import UIKit + +final class BillingFormTextFieldErrorView: UIView { + private var style: ErrorInputLabelStyle = DefaultErrorInputLabelStyle() + + lazy var headerLabel: UILabel = { + let view = UILabel() + view.text = style.text + view.font = style.font + view.textColor = style.textColor + view.textAlignment = .justified + view.numberOfLines = 0 + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .white + return view + }() + + lazy var image: UIImageView = { + let view = UIImageView() + view.image = "warning".vectorPDFImage(forClass: BillingFormTextFieldErrorView.self) + view.tintColor = style.tintColor + view.contentMode = .scaleAspectFit + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .white + return view + }() + + init(style: ErrorInputLabelStyle) { + super.init(frame: .zero) + self.style = style + setupViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension BillingFormTextFieldErrorView { + + private func setupViews(){ + backgroundColor = style.backgroundColor + setupHeaderLabel() + setupImageView() + } + + private func setupHeaderLabel() { + addSubview(headerLabel) + NSLayoutConstraint.activate([ + headerLabel.topAnchor.constraint(equalTo: topAnchor), + headerLabel.bottomAnchor.constraint(equalTo: bottomAnchor), + headerLabel.trailingAnchor.constraint(equalTo: trailingAnchor) + ]) + } + + private func setupImageView() { + addSubview(image) + NSLayoutConstraint.activate([ + image.topAnchor.constraint(equalTo: topAnchor), + image.bottomAnchor.constraint(equalTo: bottomAnchor), + image.leadingAnchor.constraint(equalTo: leadingAnchor), + image.trailingAnchor.constraint(equalTo: headerLabel.leadingAnchor, constant: -10), + image.widthAnchor.constraint(equalToConstant: 15) + + ]) + } + +} diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillFormTextField.swift b/Source/UI/NewUI/BillingForm/View/Field/BillFormTextField.swift new file mode 100644 index 00000000..d00c5c36 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/View/Field/BillFormTextField.swift @@ -0,0 +1,13 @@ +import UIKit + +final class BillFormTextField: UITextField { + var type: BillingFormCellType + init(type: BillingFormCellType) { + self.type = type + super.init(frame: .zero) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift new file mode 100644 index 00000000..bae99c90 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -0,0 +1,86 @@ +import UIKit +import PhoneNumberKit + +final class BillingFormPhoneNumberText: UITextField { + var type: BillingFormCellType + /// Phone Number Kit + let phoneNumberKit = PhoneNumberKit() + var partialFormatter: PartialFormatter { + return PartialFormatter.init(phoneNumberKit: phoneNumberKit, defaultRegion: "GB", withPrefix: true) + } + + /// National Number (e.g. ) + public var nationalNumber: String { + let rawNumber = self.text ?? "" + return partialFormatter.nationalNumber(from: rawNumber) + } + + /// True if the phone number is valid, false otherwise + public var isValidNumber: Bool { + let rawNumber = self.text ?? "" + do { + phoneNumber = try phoneNumberKit.parse(rawNumber.replacingOccurrences(of: " ", with: "")) + return true + } catch { + return false + } + } + + /// Phone Number + public var phoneNumber: PhoneNumber? + + private var previousTextCount = 0 + private var previousFormat = "" + + init(type: BillingFormCellType) { + self.type = type + super.init(frame: .zero) + setup() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + setup() + } + + private func setup() { + addTarget(self, action: #selector(textFieldDidChange), for: UIControl.Event.editingChanged) + } + + /// Called when the text changed. + @objc public func textFieldDidChange(textField: UITextField) { + var targetCursorPosition = 0 + if let startPosition = textField.selectedTextRange?.start { + targetCursorPosition = textField.offset(from: textField.beginningOfDocument, to: startPosition) + } + + let phoneNumber = textField.text! + let formatted = partialFormatter.formatPartial(phoneNumber) + textField.text = formatted + + if var targetPosition = textField.position(from: textField.beginningOfDocument, offset: targetCursorPosition) { + if targetCursorPosition != 0 { + let lastChar = formatted[formatted.index(formatted.startIndex, + offsetBy: targetCursorPosition - 1)] + if lastChar == " " && previousTextCount < formatted.count && phoneNumber != formatted { + guard let aTargetPosition = textField.position(from: textField.beginningOfDocument, + offset: targetCursorPosition + 1) else { + return + } + targetPosition = aTargetPosition + } + } + if (previousFormat.filter {$0 == " "}.count != formatted.filter {$0 == " "}.count) && + phoneNumber != formatted { + guard let aTargetPosition = textField.position(from: textField.beginningOfDocument, + offset: targetCursorPosition + 1) else { + return + } + targetPosition = aTargetPosition + } + textField.selectedTextRange = textField.textRange(from: targetPosition, to: targetPosition) + } + previousTextCount = formatted.count + previousFormat = formatted + } +} diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift new file mode 100644 index 00000000..30f38565 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -0,0 +1,171 @@ +import UIKit + +protocol BillingFormTextFieldViewDelegate: AnyObject { + func textFieldShouldBeginEditing(textField: UITextField) + func textFieldShouldReturn() + func textFieldDidEndEditing(textField: UITextField) + func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) +} + +final class BillingFormTextFieldView: UIView { + + private var style: BillingFormTextFieldCellStyle + private var type: BillingFormCellType + private weak var delegate: BillingFormTextFieldViewDelegate? + + private(set) lazy var headerLabel: UILabel = { + let view = UILabel() + view.text = style.title?.text + view.font = style.title?.font + view.textColor = style.title?.textColor + view.numberOfLines = 0 + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .white + return view + }() + + private(set) lazy var hintLabel: UILabel = { + let view = UILabel() + view.text = style.hint?.text + view.font = style.hint?.font + view.textColor = style.hint?.textColor + view.numberOfLines = 0 + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .white + return view + }() + + private(set) lazy var textFieldContainer: UIView = { + let view = UIView() + view.layer.cornerRadius = 10.0 + view.layer.borderWidth = 1.0 + textField.autocorrectionType = .no + view.translatesAutoresizingMaskIntoConstraints = false + view.layer.borderColor = style.textfield.normalBorderColor.cgColor + view.backgroundColor = style.textfield.backgroundColor + textField.keyboardType = style.textfield.isSupprtingNumbericKeyboard ? .phonePad : .default + textField.textContentType = style.textfield.isSupprtingNumbericKeyboard ? .telephoneNumber : .name + return view + }() + + private(set) lazy var textField: UITextField = { + let view: UITextField = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type) : BillFormTextField(type: self.type) + view.text = style.textfield.text + view.font = style.textfield.font + view.placeholder = style.textfield.placeHolder + view.textColor = style.textfield.textColor + view.tintColor = style.textfield.tintColor + view.delegate = self + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .clear + return view + }() + + private(set) lazy var errorView: BillingFormTextFieldErrorView = { + let view = BillingFormTextFieldErrorView(style: style.error) + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + init(type: BillingFormCellType, style: BillingFormTextFieldCellStyle, delegate: BillingFormTextFieldViewDelegate? = nil) { + self.style = style + self.type = type + super.init(frame: .zero) + self.delegate = delegate + self.setupViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension BillingFormTextFieldView { + + private func setupViews(){ + backgroundColor = style.backgroundColor + setupHeaderLabel() + setupHintLabel() + setupTextFieldContainer() + setupTextField() + setupErrorView() + } + + private func setupHeaderLabel() { + addSubview(headerLabel) + NSLayoutConstraint.activate([ + headerLabel.topAnchor.constraint(equalTo: topAnchor), + headerLabel.leadingAnchor.constraint(equalTo: leadingAnchor), + headerLabel.trailingAnchor.constraint(equalTo: trailingAnchor) + ]) + } + + private func setupHintLabel() { + addSubview(hintLabel) + NSLayoutConstraint.activate([ + hintLabel.topAnchor.constraint(equalTo: headerLabel.safeBottomAnchor, constant: 2), + hintLabel.leadingAnchor.constraint(equalTo: leadingAnchor), + hintLabel.trailingAnchor.constraint(equalTo: trailingAnchor) + ]) + } + + private func setupTextField() { + textFieldContainer.addSubview(textField) + NSLayoutConstraint.activate([ + textField.topAnchor.constraint(equalTo: textFieldContainer.topAnchor), + textField.leadingAnchor.constraint(equalTo: textFieldContainer.leadingAnchor, constant: 20), + textField.trailingAnchor.constraint(equalTo: textFieldContainer.trailingAnchor, constant: -20), + textField.bottomAnchor.constraint(equalTo: textFieldContainer.bottomAnchor) + ]) + } + + private func setupTextFieldContainer() { + addSubview(textFieldContainer) + + let width = textFieldContainer.widthAnchor.constraint(equalToConstant: style.textfield.width) + width.priority = UILayoutPriority(rawValue: 750) + + NSLayoutConstraint.activate([ + textFieldContainer.topAnchor.constraint(equalTo: hintLabel.bottomAnchor, constant: 6), + textFieldContainer.leadingAnchor.constraint(equalTo: leadingAnchor), + textFieldContainer.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor), + width, + textFieldContainer.heightAnchor.constraint(equalToConstant: style.textfield.height) + ]) + } + + private func setupErrorView() { + addSubview(errorView) + NSLayoutConstraint.activate([ + errorView.topAnchor.constraint(equalTo: textFieldContainer.bottomAnchor, constant: 10), + errorView.leadingAnchor.constraint(equalTo: leadingAnchor), + errorView.trailingAnchor.constraint(equalTo: trailingAnchor), + errorView.bottomAnchor.constraint(equalTo: bottomAnchor), + errorView.heightAnchor.constraint(equalToConstant: style.error.isHidden ? 0 : style.error.height) + ]) + } +} + +extension BillingFormTextFieldView: UITextFieldDelegate { + + func textFieldDidBeginEditing(_ textField: UITextField) { + textFieldContainer.layer.borderColor = style.textfield.focusBorderColor.cgColor + self.delegate?.textFieldShouldBeginEditing(textField: textField) + } + + func textFieldDidEndEditing(_ textField: UITextField) { + textFieldContainer.layer.borderColor = style.textfield.normalBorderColor.cgColor + delegate?.textFieldDidEndEditing(textField: textField) + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + delegate?.textFieldShouldReturn() + return false + } + + func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + delegate?.textFieldDidChangeCharacters(textField: textField, replacementString: string) + return true + } +} diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift new file mode 100644 index 00000000..df38e23a --- /dev/null +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift @@ -0,0 +1,74 @@ +import UIKit +import PhoneNumberKit + +protocol BillingFormTextFieldCellDelegate: AnyObject { + func textFieldShouldBeginEditing(textField: UITextField) + func textFieldShouldReturn() + func textFieldDidEndEditing(textField: UITextField) + func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) +} + +final class BillingFormTextFieldCell: UITableViewCell { + weak var delegate: BillingFormTextFieldCellDelegate? + private var style: BillingFormTextFieldCellStyle + private var type: BillingFormCellType + + init(type: BillingFormCellType, style: BillingFormTextFieldCellStyle, delegate: BillingFormTextFieldCellDelegate?) { + self.style = style + self.type = type + super.init(style: .default, reuseIdentifier: nil) + self.delegate = delegate + setupViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private lazy var paymentInputView: BillingFormTextFieldView = { + let view = BillingFormTextFieldView(type: type, style: style,delegate: self) + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + +} + +// setup views +extension BillingFormTextFieldCell { + + private func setupViews() { + contentView.addSubview(paymentInputView) + NSLayoutConstraint.activate([ + paymentInputView.topAnchor.constraint( + equalTo: contentView.safeTopAnchor, + constant: 0), + paymentInputView.leadingAnchor.constraint( + equalTo: contentView.safeLeadingAnchor, + constant: 20), + paymentInputView.trailingAnchor.constraint( + equalTo: contentView.safeTrailingAnchor, + constant: -20), + paymentInputView.bottomAnchor.constraint( + equalTo: contentView.safeBottomAnchor, + constant: -24) + ]) + } +} + +extension BillingFormTextFieldCell: BillingFormTextFieldViewDelegate { + func textFieldDidEndEditing(textField: UITextField) { + delegate?.textFieldDidEndEditing(textField: textField) + } + + func textFieldShouldBeginEditing(textField: UITextField) { + delegate?.textFieldShouldBeginEditing(textField: textField) + } + func textFieldShouldReturn() { + delegate?.textFieldShouldReturn() + } + + func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) { + delegate?.textFieldDidChangeCharacters(textField: textField, replacementString: replacementString) + } + +} diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift new file mode 100644 index 00000000..0d70ecbf --- /dev/null +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -0,0 +1,138 @@ +import UIKit + +protocol BillingFormHeaderCellDelegate: AnyObject { + func doneButtonIsPressed() + func cancelButtonIsPressed() +} + +final class BillingFormHeaderCell: UITableViewCell { + private var style: BillingFormHeaderCellStyle + private weak var deleagte: BillingFormHeaderCellDelegate? + + private lazy var cancel: UIButton = { + let view = UIButton() + view.setTitle(style.cancelButton.text, for: .normal) + view.titleLabel?.font = style.cancelButton.font + view.setTitleColor(style.cancelButton.activeTitleColor, for: .normal) + view.setTitleColor(style.cancelButton.inActiveTitleColor, for: .disabled) + view.tintColor = view.isEnabled ? style.cancelButton.activeTintColor : style.cancelButton.inActiveTintColor + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = style.cancelButton.backgroundColor + view.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) + return view + }() + + private lazy var done: UIButton = { + let view = UIButton() + view.isEnabled = style.doneButton.isEnabled + view.setTitle(style.doneButton.text, for: .normal) + view.titleLabel?.font = style.doneButton.font + view.setTitleColor(style.doneButton.activeTitleColor, for: .normal) + view.setTitleColor(style.doneButton.inActiveTitleColor, for: .disabled) + view.tintColor = view.isEnabled ? style.doneButton.activeTintColor : style.doneButton.inActiveTintColor + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = style.doneButton.backgroundColor + view.addTarget(self, action: #selector(doneAction), for: .touchUpInside) + return view + }() + + private lazy var headerLabel: UILabel = { + let view = UILabel() + view.text = style.headerLabel.text + view.font = style.headerLabel.font + view.textColor = style.headerLabel.textColor + view.numberOfLines = 0 + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .white + return view + }() + + init(style: BillingFormHeaderCellStyle , delegate: BillingFormHeaderCellDelegate?) { + self.style = style + super.init(style: .default, reuseIdentifier: nil) + self.deleagte = delegate + setupViews() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func doneAction(){ + deleagte?.doneButtonIsPressed() + } + + @objc private func cancelAction(){ + deleagte?.cancelButtonIsPressed() + } + + private func shouldEnableDoneButton(flag: Bool) { + done.isEnabled = flag + } +} + +// setup views +extension BillingFormHeaderCell { + + private func setupViews() { + setupCancelButton() + setupDoneButton() + setupHeaderLabel() + } + + private func setupCancelButton() { + contentView.addSubview(cancel) + NSLayoutConstraint.activate([ + cancel.topAnchor.constraint( + equalTo: safeTopAnchor, + constant: 0), + cancel.leadingAnchor.constraint( + equalTo: contentView.safeLeadingAnchor, + constant: 20), + cancel.heightAnchor.constraint( + equalToConstant: style.cancelButton.hight), + cancel.widthAnchor.constraint( + equalToConstant: style.cancelButton.width) + ]) + } + + private func setupDoneButton() { + contentView.addSubview(done) + NSLayoutConstraint.activate([ + done.topAnchor.constraint( + equalTo: safeTopAnchor, + constant: 0), + done.trailingAnchor.constraint( + equalTo: contentView.safeTrailingAnchor, + constant: -20), + done.heightAnchor.constraint( + equalToConstant: style.doneButton.hight), + done.widthAnchor.constraint( + equalToConstant: style.doneButton.width) + ]) + } + + private func setupHeaderLabel() { + contentView.addSubview(headerLabel) + NSLayoutConstraint.activate([ + headerLabel.topAnchor.constraint( + equalTo: contentView.safeTopAnchor, + constant: 58), + headerLabel.leadingAnchor.constraint( + equalTo: contentView.safeLeadingAnchor, + constant: 20), + headerLabel.trailingAnchor.constraint( + equalTo: contentView.safeTrailingAnchor, + constant: -20), + headerLabel.bottomAnchor.constraint( + equalTo: contentView.safeBottomAnchor, + constant: -40) + ]) + } +} + +extension BillingFormHeaderCell: BillingFormViewModelEditingDelegate { + func didFinishEditingBillingForm(successfully: Bool) { + shouldEnableDoneButton(flag: successfully) + } +} diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift new file mode 100644 index 00000000..928c56f5 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -0,0 +1,171 @@ +import UIKit + +protocol BillingFormViewControllerDeleagte: AnyObject { + func doneButtonIsPressed(sender: UIViewController) + func cancelButtonIsPressed(sender: UIViewController) + func tableView(numberOfRowsInSection section: Int) -> Int + func tableView(cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell + func tableView(estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat + func validate(textField: BillFormTextField) + func textFieldIsChanged(textField: BillFormTextField, replacementString: String) +} + +final class BillingFormViewController: UIViewController { + weak var delegate: BillingFormViewControllerDeleagte? + + fileprivate var focusedTextField: UITextField? + private var viewModel: BillingFormViewModel + private var notificationCenter = NotificationCenter.default + + private lazy var tableView: UITableView = { + let view = UITableView() + view.dataSource = self + view.rowHeight = UITableView.automaticDimension + view.estimatedRowHeight = 300 + view.separatorStyle = .none + view.showsVerticalScrollIndicator = false + view.showsHorizontalScrollIndicator = false + view.allowsSelection = false + view.translatesAutoresizingMaskIntoConstraints = false + return view + }() + + override func viewDidLoad() { + super.viewDidLoad() + view.backgroundColor = viewModel.style.mainBackground + setupTableView() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + navigationController?.setNavigationBarHidden(true, animated: false) + setUpKeyboard() + } + + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + deregisterKeyboardHandlers(notificationCenter: notificationCenter) + } + + init(viewModel: BillingFormViewModel) { + self.viewModel = viewModel + self.delegate = viewModel as? BillingFormViewControllerDeleagte + super.init(nibName: nil, bundle: nil) + self.setupViewModel() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func dismissKeyboard (_ sender: UITapGestureRecognizer) { + view.endEditing(true) + } + + @objc func keyboardWillShow(notification: NSNotification) { + scrollViewOnKeyboardWillShow(notification: notification, + scrollView: tableView as UIScrollView, + activeField: nil) + } + + @objc func keyboardWillHide(notification: Notification) { + tableView.setBottomInset(to: 0.0) + self.focusedTextField = nil + } +} + +// setup views +extension BillingFormViewController { + private func setupTableView() { + view.addSubview(tableView) + NSLayoutConstraint.activate([ + tableView.topAnchor.constraint( + equalTo: view.safeTopAnchor, + constant: 20), + tableView.leadingAnchor.constraint( + equalTo: view.safeLeadingAnchor, + constant: 20), + tableView.trailingAnchor.constraint( + equalTo: view.safeTrailingAnchor, + constant: -20), + tableView.bottomAnchor.constraint( + equalTo: view.safeBottomAnchor, + constant: 20) + ]) + } + + private func setUpKeyboard() { + title = "addressViewControllerTitle".localized(forClass: AddressViewController.self) + registerKeyboardHandlers(notificationCenter: notificationCenter, + keyboardWillShow: #selector(keyboardWillShow), + keyboardWillHide: #selector(keyboardWillHide)) + +// let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:))) +// view.addGestureRecognizer(tapGesture) +// NotificationCenter.default.addObserver(self, selector: #selector(BillingFormViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) +// NotificationCenter.default.addObserver(self, selector: #selector(BillingFormViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) + } +} + +// UITableViewDataSource +extension BillingFormViewController: UITableViewDataSource { + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + delegate?.tableView(numberOfRowsInSection: section) ?? 0 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + delegate?.tableView(cellForRowAt: indexPath, sender: self) ?? UITableViewCell() + } + + func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + delegate?.tableView(estimatedHeightForRowAt: indexPath) ?? 0.0 + } +} + +//FormCellDelegate +extension BillingFormViewController: BillingFormTextFieldCellDelegate { + func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) { + guard let textField = textField as? BillFormTextField else { return } + delegate?.textFieldIsChanged(textField: textField, replacementString: replacementString) + } + + func textFieldDidEndEditing(textField: UITextField) { + guard let textField = textField as? BillFormTextField else { return } + delegate?.validate(textField: textField) + } + + + func textFieldShouldBeginEditing(textField: UITextField) { + self.focusedTextField = textField + } + + func textFieldShouldReturn() { + view.endEditing(true) + } +} + +//FormHeaderCellDelegate +extension BillingFormViewController: BillingFormHeaderCellDelegate { + + func doneButtonIsPressed() { + delegate?.doneButtonIsPressed(sender: self) + } + + func cancelButtonIsPressed() { + delegate?.cancelButtonIsPressed(sender: self) + } +} + +// ViewModel +extension BillingFormViewController { + private func setupViewModel() { + viewModel.updateRow = { + DispatchQueue.main.async { [weak self] in + guard let self = self, let row = self.viewModel.updatedRow else { return } + let indexPath = IndexPath(row: row, section: 0) + self.tableView.reloadRows(at: [indexPath], with: .automatic) + } + + } + } +} diff --git a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift new file mode 100644 index 00000000..5e7f4062 --- /dev/null +++ b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift @@ -0,0 +1,25 @@ +import Foundation + +@frozen enum BillingFormCellType: Int, CaseIterable { + case fullName = 1 + case addressLine1 = 2 + case addressLine2 = 3 + case city = 4 + case state = 5 + case postcode = 6 + case country = 7 + case phoneNumber = 8 + + var validator: Validator { + switch self { + case .fullName: return FullNameValidator() + case .addressLine1: return AddressLine1Validator() + case .addressLine2: return AddressLine2Validator() + case .city: return CityValidator() + case .state: return StateValidator() + case .postcode: return PostCodeValidator() + case .country: return CountryValidator() + case .phoneNumber: return PhoneNumberValidator() + } + } +} diff --git a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift new file mode 100644 index 00000000..74ae130f --- /dev/null +++ b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift @@ -0,0 +1,19 @@ +import Foundation + +protocol BillingFormViewModelDelegate { + /// Executed when an user tap on the done button. + /// + /// - parameter controller: `AddressViewController` + /// - parameter address: Address entered by the user + func onTapDoneButton(address: CkoAddress, phone: CkoPhoneNumber) +} + +protocol BillingFormViewModelEditingDelegate { + func didFinishEditingBillingForm(successfully: Bool) +} + +protocol BillingFormViewModel { + var style: BillingFormStyle { get } + var updatedRow: Int? { get } + var updateRow: (() -> Void)? { get set } +} diff --git a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift new file mode 100644 index 00000000..0920070d --- /dev/null +++ b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift @@ -0,0 +1,119 @@ +import UIKit + +final class DefaultBillingFormViewModel: BillingFormViewModel { + var style: BillingFormStyle + var updateRow: (() -> Void)? + var updatedRow: Int? { + didSet { + updateRow?() + } + } + + lazy var errorFlagOfCellType = [BillingFormCellType: Bool]() + lazy var textValueOfCellType = [BillingFormCellType: String]() + + private var initialCountry: String + private var initialRegionCode: String? + var editDelegate: BillingFormViewModelEditingDelegate? + var delegate: BillingFormViewModelDelegate? + + init(style: BillingFormStyle, initialCountry: String = "", initialRegionCode: String? = nil, delegate: BillingFormViewModelDelegate? = nil) { + self.style = style + self.initialCountry = initialCountry + self.initialRegionCode = initialRegionCode + self.delegate = delegate + } + + func getCell(for row: Int, delegate: UIViewController? = nil) -> UITableViewCell { + if row == 0 { + return getHeaderCell(delegate: delegate as? BillingFormHeaderCellDelegate) + } + return getFieldCell(for: row, delegate: delegate as? BillingFormTextFieldCellDelegate) + } + + private func getHeaderCell(delegate: BillingFormHeaderCellDelegate?) -> UITableViewCell { + var style = style.header + updateHeaderView(with: &style) + let cell = BillingFormHeaderCell(style: style, delegate: delegate) + self.editDelegate = cell + return cell + } + + private func getFieldCell(for row: Int, delegate: BillingFormTextFieldCellDelegate?) -> UITableViewCell { + guard let type = BillingFormCellType(rawValue: row) else { return UITableViewCell()} + var style = style.fields[row - 1] + updateErrorView(with: &style, type: type) + updateTextField(with: &style, type: type) + return BillingFormTextFieldCell(type: type, style: style, delegate: delegate) + } + + private func updateHeaderView(with style: inout BillingFormHeaderCellStyle) { + style.doneButton.isEnabled = textValueOfCellType.values.count == self.style.fields.count + } + + private func updateErrorView(with style: inout BillingFormTextFieldCellStyle, type: BillingFormCellType) { + guard let hasError = errorFlagOfCellType[type] else { return } + style.error.isHidden = !hasError + } + + private func updateTextField(with style: inout BillingFormTextFieldCellStyle, type: BillingFormCellType) { + guard let text = textValueOfCellType[type] else { return } + style.textfield.text = text + } +} + +extension DefaultBillingFormViewModel: BillingFormViewControllerDeleagte { + func textFieldIsChanged(textField: BillFormTextField, replacementString: String) { + if !replacementString.isEmpty { + textValueOfCellType[textField.type] = replacementString + } + + if textValueOfCellType.values.count == style.fields.count { + editDelegate?.didFinishEditingBillingForm(successfully: !errorFlagOfCellType.values.allSatisfy({$0})) + } + } + + func tableView(estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + UITableView.automaticDimension + } + + func tableView(numberOfRowsInSection section: Int) -> Int { + style.fields.count + 1 + } + + func tableView(cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell { + getCell(for: indexPath.row, delegate: sender) + } + + func doneButtonIsPressed(sender: UIViewController) { + let countryCode = "44" //"\(addressView.phoneInputView.phoneNumber?.countryCode ?? 44)" + let phone = CkoPhoneNumber(countryCode: countryCode, + number: textValueOfCellType[.phoneNumber]) + let address = CkoAddress(addressLine1: textValueOfCellType[.addressLine1], + addressLine2: textValueOfCellType[.addressLine2], + city: textValueOfCellType[.city], + state: textValueOfCellType[.state], + zip: textValueOfCellType[.postcode], + country: textValueOfCellType[.country]) + delegate?.onTapDoneButton(address: address, phone: phone) + sender.dismiss(animated: true) + } + + func cancelButtonIsPressed(sender: UIViewController) { + sender.dismiss(animated: true) + } + + func validate(textField: BillFormTextField) { + let type = textField.type + let text = textField.text + textValueOfCellType[type] = text + + guard !type.validator.validate(text: textField.text) else { + errorFlagOfCellType[type] = true + updatedRow = type.rawValue + return + } + errorFlagOfCellType[type] = false + updatedRow = type.rawValue + } +} diff --git a/Source/UI/UITableView.swift b/Source/UI/UITableView.swift new file mode 100644 index 00000000..b3418db9 --- /dev/null +++ b/Source/UI/UITableView.swift @@ -0,0 +1,10 @@ +import UIKit +extension UITableView { + + func setBottomInset(to value: CGFloat) { + let edgeInset = UIEdgeInsets(top: 0, left: 0, bottom: value, right: 0) + self.contentInset = edgeInset + self.scrollIndicatorInsets = edgeInset + + } +} diff --git a/Source/Validator/AddressLine1Validator.swift b/Source/Validator/AddressLine1Validator.swift new file mode 100644 index 00000000..237d4d78 --- /dev/null +++ b/Source/Validator/AddressLine1Validator.swift @@ -0,0 +1,13 @@ +import Foundation + +class AddressLine1Validator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/AddressLine2Validator.swift b/Source/Validator/AddressLine2Validator.swift new file mode 100644 index 00000000..8a1c271c --- /dev/null +++ b/Source/Validator/AddressLine2Validator.swift @@ -0,0 +1,13 @@ +import Foundation + +class AddressLine2Validator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/CityValidator.swift b/Source/Validator/CityValidator.swift new file mode 100644 index 00000000..35fdc35c --- /dev/null +++ b/Source/Validator/CityValidator.swift @@ -0,0 +1,13 @@ +import Foundation + +class CityValidator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/CountryValidator.swift b/Source/Validator/CountryValidator.swift new file mode 100644 index 00000000..45094ed2 --- /dev/null +++ b/Source/Validator/CountryValidator.swift @@ -0,0 +1,13 @@ +import Foundation + +class CountryValidator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/FullNameValidator.swift b/Source/Validator/FullNameValidator.swift new file mode 100644 index 00000000..86884bbf --- /dev/null +++ b/Source/Validator/FullNameValidator.swift @@ -0,0 +1,13 @@ +import Foundation + +class FullNameValidator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/PhoneNumberValidator.swift b/Source/Validator/PhoneNumberValidator.swift new file mode 100644 index 00000000..fb2439c3 --- /dev/null +++ b/Source/Validator/PhoneNumberValidator.swift @@ -0,0 +1,13 @@ +import Foundation + +class PhoneNumberValidator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/PostCodeValidator.swift b/Source/Validator/PostCodeValidator.swift new file mode 100644 index 00000000..0073c932 --- /dev/null +++ b/Source/Validator/PostCodeValidator.swift @@ -0,0 +1,13 @@ +import Foundation + +class PostCodeValidator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/StateValidator.swift b/Source/Validator/StateValidator.swift new file mode 100644 index 00000000..da7f5213 --- /dev/null +++ b/Source/Validator/StateValidator.swift @@ -0,0 +1,13 @@ +import Foundation + +class StateValidator: Validator { + func validate(text: String?) -> Bool { + return isEmpty(text: text) + } + + private func isEmpty(text: String?) -> Bool { + guard let text = text, !text.isEmpty else { return true } + return false + } + +} diff --git a/Source/Validator/Validator.swift b/Source/Validator/Validator.swift new file mode 100644 index 00000000..4e8dd5dc --- /dev/null +++ b/Source/Validator/Validator.swift @@ -0,0 +1,5 @@ +import Foundation + +protocol Validator { + func validate(text: String?) -> Bool +} diff --git a/Tests/Mocks/AddressViewControllerMockDelegate.swift b/Tests/Mocks/AddressViewControllerMockDelegate.swift index fe8e64f6..af7fd0fc 100644 --- a/Tests/Mocks/AddressViewControllerMockDelegate.swift +++ b/Tests/Mocks/AddressViewControllerMockDelegate.swift @@ -1,4 +1,4 @@ -import Foundation +import UIKit @testable import Frames class AddressViewControllerMockDelegate: AddressViewControllerDelegate { diff --git a/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift b/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift new file mode 100644 index 00000000..34f29ef7 --- /dev/null +++ b/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift @@ -0,0 +1,37 @@ +import UIKit +@testable import Frames + +class BillingFormTextFieldCellMockDelegate: BillingFormTextFieldCellDelegate { + + var textFieldShouldBeginEditingCalledTimes = 0 + var textFieldShouldBeginEditingLastCalledWithTextField: UITextField? + + var textFieldShouldReturnCalledTimes = 0 + + var textFieldDidEndEditingCalledTimes = 0 + var textFieldDidEndEditingLastCalledWithTextField: UITextField? + + var textFieldDidChangeCharactersCalledTimes = 0 + var textFieldDidChangeCharactersLastCalledWithTextField: UITextField? + var textFieldDidChangeCharactersLastCalledWithReplacementString: String? + + func textFieldShouldBeginEditing(textField: UITextField) { + textFieldShouldBeginEditingCalledTimes += 1 + textFieldShouldBeginEditingLastCalledWithTextField = textField + } + + func textFieldShouldReturn() { + textFieldShouldReturnCalledTimes += 1 + } + + func textFieldDidEndEditing(textField: UITextField) { + textFieldDidEndEditingCalledTimes += 1 + textFieldDidEndEditingLastCalledWithTextField = textField + } + + func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) { + textFieldDidChangeCharactersCalledTimes += 1 + textFieldDidChangeCharactersLastCalledWithTextField = textField + textFieldDidChangeCharactersLastCalledWithReplacementString = replacementString + } +} diff --git a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift new file mode 100644 index 00000000..7ff7e379 --- /dev/null +++ b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift @@ -0,0 +1,69 @@ +import UIKit +@testable import Frames + +class BillingFormViewControllerMockDelegate: BillingFormViewControllerDeleagte { + + var doneButtonIsPressedCalledTimes = 0 + var doneButtonIsPressedLastCalledWithSender: UIViewController? + + var cancelButtonIsPressedCalledTimes = 0 + var cancelButtonIsPressedLastCalledWithSender: UIViewController? + + var numberOfRowsInSectionCalledTimes = 0 + var numberOfRowsInSectionLastCalledWithSection: Int? + + var cellForRowAtCalledTimes = 0 + var cellForRowAtLastCalledWithIndexPath: IndexPath? + var cellForRowAtLastCalledWithSender: UIViewController? + + var estimatedHeightForRowCalledTimes = 0 + var estimatedHeightForRowLastCalledWithIndexPath: IndexPath? + + var validateCalledTimes = 0 + var validateLastCalledWithBillFormTextField: BillFormTextField? + + var textFieldIsChangedCalledTimes = 0 + var textFieldIsChangedLastCalledWithBillFormTextField: BillFormTextField? + var textFieldIsChangedLastCalledWithReplacementString: String? + + func doneButtonIsPressed(sender: UIViewController) { + doneButtonIsPressedCalledTimes += 1 + doneButtonIsPressedLastCalledWithSender = sender + } + + func cancelButtonIsPressed(sender: UIViewController) { + cancelButtonIsPressedCalledTimes += 1 + cancelButtonIsPressedLastCalledWithSender = sender + } + + func tableView(numberOfRowsInSection section: Int) -> Int { + numberOfRowsInSectionCalledTimes += 1 + numberOfRowsInSectionLastCalledWithSection = section + return 5 + } + + func tableView(cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell { + cellForRowAtCalledTimes += 1 + cellForRowAtLastCalledWithIndexPath = indexPath + cellForRowAtLastCalledWithSender = sender + return UITableViewCell() + } + + func tableView(estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + estimatedHeightForRowCalledTimes += 1 + estimatedHeightForRowLastCalledWithIndexPath = indexPath + return 100 + } + + func validate(textField: BillFormTextField) { + validateCalledTimes += 1 + validateLastCalledWithBillFormTextField = textField + } + + func textFieldIsChanged(textField: BillFormTextField, replacementString: String) { + textFieldIsChangedCalledTimes += 1 + textFieldIsChangedLastCalledWithBillFormTextField = textField + textFieldIsChangedLastCalledWithReplacementString = replacementString + } + +} diff --git a/Tests/Mocks/BillingFormViewModelEditingMockDelegate.swift b/Tests/Mocks/BillingFormViewModelEditingMockDelegate.swift new file mode 100644 index 00000000..e6ede444 --- /dev/null +++ b/Tests/Mocks/BillingFormViewModelEditingMockDelegate.swift @@ -0,0 +1,12 @@ +import UIKit +@testable import Frames + +class BillingFormViewModelEditingMockDelegate: BillingFormViewModelEditingDelegate { + var didFinishEditingBillingFormCalledTimes = 0 + var didFinishEditingBillingFormLastCalledWithSuccessfully: Bool? + + func didFinishEditingBillingForm(successfully: Bool) { + didFinishEditingBillingFormCalledTimes += 1 + didFinishEditingBillingFormLastCalledWithSuccessfully = successfully + } +} diff --git a/Tests/Mocks/BillingFormViewModelMockDelegate.swift b/Tests/Mocks/BillingFormViewModelMockDelegate.swift new file mode 100644 index 00000000..780a81cd --- /dev/null +++ b/Tests/Mocks/BillingFormViewModelMockDelegate.swift @@ -0,0 +1,14 @@ +import UIKit +@testable import Frames + +class BillingFormViewModelMockDelegate: BillingFormViewModelDelegate { + var onTapDoneButtonCalledTimes = 0 + var onTapDoneButtonLastCalledWithAddress: CkoAddress? + var onTapDoneButtonLastCalledWithNumber: CkoPhoneNumber? + + func onTapDoneButton(address: CkoAddress, phone: CkoPhoneNumber) { + onTapDoneButtonCalledTimes += 1 + onTapDoneButtonLastCalledWithAddress = address + onTapDoneButtonLastCalledWithNumber = phone + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift new file mode 100644 index 00000000..b59e62c6 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class AddressLine1ValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.addressLine1 + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.addressLine1 + let text = "addressLine1" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift new file mode 100644 index 00000000..5f408a89 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class AddressLine2ValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.addressLine2 + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.addressLine2 + let text = "addressLine2" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift new file mode 100644 index 00000000..9be38cb9 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class CityValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.city + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.city + let text = "City" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift new file mode 100644 index 00000000..5f0fa413 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class CountryValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.country + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.country + let text = "Country" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift new file mode 100644 index 00000000..1cb0340c --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class FullNameValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.fullName + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.fullName + let text = "fullName" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift new file mode 100644 index 00000000..83c3f575 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class PhoneNumberValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.phoneNumber + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.phoneNumber + let text = "phoneNumber" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift new file mode 100644 index 00000000..c627ed10 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class PostCodeValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.postcode + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.postcode + let text = "postcode" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift new file mode 100644 index 00000000..9bb8cd37 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift @@ -0,0 +1,19 @@ +import XCTest +@testable import Frames + +class StateValidatorTests: XCTestCase { + + func testValidationWhenTextIsEmptyThenShouldBeTrue() { + let expectedType = BillingFormCellType.state + let text = "" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, true) + } + + func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { + let expectedType = BillingFormCellType.state + let text = "postcode" + let isValid = expectedType.validator.validate(text: text) + XCTAssertEqual(isValid, false) + } +} diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift new file mode 100644 index 00000000..d2a0710d --- /dev/null +++ b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift @@ -0,0 +1,55 @@ +import XCTest +@testable import Frames + +class BillingFormTextFieldCellTests: XCTestCase { + var view: BillingFormTextFieldCell! + + override func setUp() { + super.setUp() + view = BillingFormTextFieldCell(type: .fullName, style: DefaultFormStyleFullNameCell(), delegate: nil) + } + + func testCallDelegateMethodTextFieldShouldBeginEditing() { + let delegate = BillingFormTextFieldCellMockDelegate() + let textField = BillFormTextField(type: .fullName) + view.delegate = delegate + + view.textFieldShouldBeginEditing(textField: textField) + + XCTAssertEqual(delegate.textFieldShouldBeginEditingCalledTimes, 1) + XCTAssertEqual(delegate.textFieldShouldBeginEditingLastCalledWithTextField, textField) + } + + func testCallDelegateMethodTextFieldShouldReturn() { + let delegate = BillingFormTextFieldCellMockDelegate() + view.delegate = delegate + + view.textFieldShouldReturn() + XCTAssertEqual(delegate.textFieldShouldReturnCalledTimes, 1) + } + + func testCallDelegateMethodTextFieldDidEndEditing() { + let delegate = BillingFormTextFieldCellMockDelegate() + let textField = BillFormTextField(type: .fullName) + view.delegate = delegate + + view.textFieldDidEndEditing(textField: textField) + + XCTAssertEqual(delegate.textFieldDidEndEditingCalledTimes, 1) + XCTAssertEqual(delegate.textFieldDidEndEditingLastCalledWithTextField, textField) + } + + func testCallDelegateMethodTextFieldDidChangeCharacters() { + let delegate = BillingFormTextFieldCellMockDelegate() + let textField = BillFormTextField(type: .fullName) + let text = "test" + view.delegate = delegate + + view.textFieldDidChangeCharacters(textField: textField, replacementString: text) + + XCTAssertEqual(delegate.textFieldDidChangeCharactersCalledTimes, 1) + XCTAssertEqual(delegate.textFieldDidChangeCharactersLastCalledWithTextField, textField) + XCTAssertEqual(delegate.textFieldDidChangeCharactersLastCalledWithReplacementString, text) + } + +} diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldErrorViewTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldErrorViewTests.swift new file mode 100644 index 00000000..a4e18135 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldErrorViewTests.swift @@ -0,0 +1,44 @@ +import XCTest +@testable import Frames + +struct ErrorInputLabelStyleImp: ErrorInputLabelStyle { + var isHidden: Bool + var text: String { "Error" } + var font: UIFont { UIFont.systemFont(ofSize: 17) } + var textColor: UIColor { .red } + var backgroundColor: UIColor { .white } + var tintColor: UIColor { .red } + var isWarningSympoleOnLeft: Bool { true } + var height: Double { 120 } +} + +class BillingFormTextFieldErrorViewTests: XCTestCase { + var errorView: BillingFormTextFieldErrorView! + let style = ErrorInputLabelStyleImp(isHidden: false) + + override func setUp() { + super.setUp() + errorView = BillingFormTextFieldErrorView(style: style) + } + + func testStyleIsHidden(){ + XCTAssertEqual(errorView.isHidden, style.isHidden) + } + + func testStyleFont(){ + XCTAssertEqual(errorView.headerLabel.font, style.font) + } + + func testStyleTextColor(){ + XCTAssertEqual(errorView.headerLabel.textColor, style.textColor) + } + + func testStyleBackgroundColor(){ + XCTAssertEqual(errorView.backgroundColor, style.backgroundColor) + } + + func testStyleTintColor(){ + XCTAssertEqual(errorView.image.tintColor, style.tintColor) + } + +} diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift new file mode 100644 index 00000000..b8120be5 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift @@ -0,0 +1,38 @@ +import XCTest +@testable import Frames + +class BillingFormTextFieldViewTests: XCTestCase { + var view: BillingFormTextFieldView! + let style = DefaultFormStyleFullNameCell() + + override func setUp() { + super.setUp() + view = BillingFormTextFieldView(type: .fullName, style: style, delegate: nil) + } + + func testHeaderLabelStyle(){ + XCTAssertEqual(view.headerLabel.text, style.title?.text) + XCTAssertEqual(view.headerLabel.font, style.title?.font) + XCTAssertEqual(view.headerLabel.textColor, style.title?.textColor) + } + + func testHintLabelStyle(){ + XCTAssertEqual(view.hintLabel.text, style.hint?.text) + } + + func testTextFieldContainerStyle(){ + XCTAssertEqual(view.textFieldContainer.layer.borderColor, style.textfield.normalBorderColor.cgColor) + XCTAssertEqual(view.textFieldContainer.backgroundColor, style.textfield.backgroundColor) + XCTAssertEqual(view.textField.keyboardType, .default) + XCTAssertEqual(view.textField.textContentType, .name) + } + + func testTextFieldtyle(){ + XCTAssertEqual(view.textField.text, style.textfield.text) + XCTAssertEqual(view.textField.font, style.textfield.font) + XCTAssertNil(view.textField.placeholder) + XCTAssertEqual(view.textField.textColor, style.textfield.textColor) + XCTAssertEqual(view.textField.tintColor, style.textfield.tintColor) + } + +} diff --git a/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift b/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift new file mode 100644 index 00000000..a5df0b72 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift @@ -0,0 +1,110 @@ +import XCTest +@testable import Frames + +class BillingFormViewControllerTests: XCTestCase { + var billingFormViewController: BillingFormViewController! + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + let style = DefaultBillingFormStyle() + let viewModel = DefaultBillingFormViewModel(style: style) + billingFormViewController = BillingFormViewController(viewModel: viewModel) + let navigation = UINavigationController() + navigation.viewControllers = [billingFormViewController] + } + + func testInitialization() { + billingFormViewController.viewDidLoad() + billingFormViewController.viewDidLayoutSubviews() + XCTAssertEqual(billingFormViewController.view.subviews.count, 1) + XCTAssertTrue(billingFormViewController.view.subviews.first is UITableView) + } + + func testCallDelegateMethodOnTapDoneButton() { + let delegate = BillingFormViewControllerMockDelegate() + billingFormViewController.viewDidLoad() + billingFormViewController.delegate = delegate + + billingFormViewController.doneButtonIsPressed() + XCTAssertEqual(delegate.doneButtonIsPressedCalledTimes, 1) + XCTAssertEqual(delegate.doneButtonIsPressedLastCalledWithSender, billingFormViewController) + } + + func testCallDelegateMethodOnTapCancelButton() { + let delegate = BillingFormViewControllerMockDelegate() + billingFormViewController.viewDidLoad() + billingFormViewController.delegate = delegate + + billingFormViewController.cancelButtonIsPressed() + XCTAssertEqual(delegate.cancelButtonIsPressedCalledTimes, 1) + XCTAssertEqual(delegate.cancelButtonIsPressedLastCalledWithSender, billingFormViewController) + } + + func testCallDelegateMethodTableViewCellForRow() { + let delegate = BillingFormViewControllerMockDelegate() + billingFormViewController.viewDidLoad() + billingFormViewController.delegate = delegate + + let indexthPath = IndexPath(row: 2, section: 2) + let cell = billingFormViewController.tableView(UITableView(), cellForRowAt: indexthPath) + + XCTAssertNotNil(cell) + XCTAssertEqual(delegate.cellForRowAtCalledTimes, 1) + XCTAssertEqual(delegate.cellForRowAtLastCalledWithSender, billingFormViewController) + XCTAssertEqual(delegate.cellForRowAtLastCalledWithIndexPath, indexthPath) + } + + func testCallDelegateMethodTableViewNumberOfRowsInSection() { + let delegate = BillingFormViewControllerMockDelegate() + billingFormViewController.viewDidLoad() + billingFormViewController.delegate = delegate + + let section = 0 + let cell = billingFormViewController.tableView(UITableView(), numberOfRowsInSection: section) + + XCTAssertNotNil(cell) + XCTAssertEqual(delegate.numberOfRowsInSectionCalledTimes, 1) + XCTAssertEqual(delegate.numberOfRowsInSectionLastCalledWithSection, section) + } + + func testCallDelegateMethodTableViewEstimatedHeightForRow() { + let delegate = BillingFormViewControllerMockDelegate() + billingFormViewController.viewDidLoad() + billingFormViewController.delegate = delegate + + let indexthPath = IndexPath(row: 2, section: 2) + let cell = billingFormViewController.tableView(UITableView(), estimatedHeightForRowAt: indexthPath) + + XCTAssertNotNil(cell) + XCTAssertEqual(delegate.estimatedHeightForRowCalledTimes, 1) + XCTAssertEqual(delegate.estimatedHeightForRowLastCalledWithIndexPath, indexthPath) + } + + func testCallDelegateMethodValidate() { + let delegate = BillingFormViewControllerMockDelegate() + billingFormViewController.viewDidLoad() + billingFormViewController.delegate = delegate + + let textfield = BillFormTextField(type: .fullName) + + billingFormViewController.textFieldDidEndEditing(textField: textfield) + + XCTAssertEqual(delegate.validateCalledTimes, 1) + XCTAssertEqual(delegate.validateLastCalledWithBillFormTextField, textfield) + } + + func testCallDelegateMethodTextFieldIsChanged() { + let delegate = BillingFormViewControllerMockDelegate() + billingFormViewController.viewDidLoad() + billingFormViewController.delegate = delegate + + let textfield = BillFormTextField(type: .fullName) + let text = "Test" + billingFormViewController.textFieldDidChangeCharacters(textField: textfield, replacementString: text) + + XCTAssertEqual(delegate.textFieldIsChangedCalledTimes, 1) + XCTAssertEqual(delegate.textFieldIsChangedLastCalledWithReplacementString, text) + XCTAssertEqual(delegate.textFieldIsChangedLastCalledWithBillFormTextField, textfield) + } +} diff --git a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift new file mode 100644 index 00000000..b6e3effe --- /dev/null +++ b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift @@ -0,0 +1,39 @@ +import XCTest +@testable import Frames + +class BillingFormCellTypeTests: XCTestCase { + + + + func testFullNameValidatorType(){ + XCTAssertTrue(BillingFormCellType.fullName.validator is FullNameValidator) + } + + func testaddressLine1ValidatorType(){ + XCTAssertTrue(BillingFormCellType.addressLine1.validator is AddressLine1Validator) + } + + func testaddressLine2ValidatorType(){ + XCTAssertTrue(BillingFormCellType.addressLine2.validator is AddressLine2Validator) + } + + func testCityValidatorType(){ + XCTAssertTrue(BillingFormCellType.city.validator is CityValidator) + } + + func testStateValidatorType(){ + XCTAssertTrue(BillingFormCellType.state.validator is StateValidator) + } + + func testCountryValidatorType(){ + XCTAssertTrue(BillingFormCellType.country.validator is CountryValidator) + } + + func testPostcodeValidatorType(){ + XCTAssertTrue(BillingFormCellType.postcode.validator is PostCodeValidator) + } + + func testPhoneNumberValidatorType(){ + XCTAssertTrue(BillingFormCellType.phoneNumber.validator is PhoneNumberValidator) + } +} diff --git a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift new file mode 100644 index 00000000..bbb635d0 --- /dev/null +++ b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift @@ -0,0 +1,115 @@ +import XCTest +@testable import Frames + +class BillingFormViewModelTests: XCTestCase { + + func testIntialization() { + let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) + XCTAssertNotNil(viewModel) + } + + // TableView Cells + func testGetHeaderCell() { + let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) + let cell = viewModel.getCell(for: 0) + XCTAssertNotNil(cell) + XCTAssertTrue(cell is BillingFormHeaderCell) + } + + func testGetFieldCell() { + let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) + let cell = viewModel.getCell(for: 1) + XCTAssertNotNil(cell) + XCTAssertTrue(cell is BillingFormTextFieldCell) + } + + func testValidationWhenTextFieldIsEmptyThenShowError() { + let expectation = expectation(description: #function) + let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) + let expectedType = BillingFormCellType.fullName + let text = "" + let textField = BillFormTextField(type: expectedType) + textField.text = text + + viewModel.updateRow = { + XCTAssertEqual(viewModel.updatedRow, expectedType.rawValue) + XCTAssertEqual(viewModel.errorFlagOfCellType[expectedType], true) + XCTAssertEqual(viewModel.textValueOfCellType[expectedType], text) + expectation.fulfill() + } + + viewModel.validate(textField: textField) + waitForExpectations(timeout: 1) + } + + func testValidationWhenTextFieldIsNotEmptyThenShowSuccess() { + let expectation = expectation(description: #function) + let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) + let expectedType = BillingFormCellType.fullName + let text = "fullName" + let textField = BillFormTextField(type: expectedType) + textField.text = text + + viewModel.updateRow = { + XCTAssertEqual(viewModel.updatedRow, expectedType.rawValue) + XCTAssertEqual(viewModel.errorFlagOfCellType[expectedType], false) + XCTAssertEqual(viewModel.textValueOfCellType[expectedType], text) + expectation.fulfill() + } + + viewModel.validate(textField: textField) + waitForExpectations(timeout: 1) + } + + func testCallDelegateMethodTextFieldIsChanged() { + let delegate = BillingFormViewModelMockDelegate() + let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) + let textValueOfCellType = [BillingFormCellType.fullName: "fullName" , + BillingFormCellType.postcode: "postcode" , + BillingFormCellType.phoneNumber: "phoneNumber" , + BillingFormCellType.country: "country" , + BillingFormCellType.city: "city" , + BillingFormCellType.addressLine1: "addressLine1" , + BillingFormCellType.addressLine2: "addressLine2" , + BillingFormCellType.state: "state" ] + + let countryCode = "44" //"\(addressView.phoneInputView.phoneNumber?.countryCode ?? 44)" + let phone = CkoPhoneNumber(countryCode: countryCode, number: textValueOfCellType[.phoneNumber]) + let address = CkoAddress(addressLine1: textValueOfCellType[.addressLine1], + addressLine2: textValueOfCellType[.addressLine2], + city: textValueOfCellType[.city], + state: textValueOfCellType[.state], + zip: textValueOfCellType[.postcode], + country: textValueOfCellType[.country]) + + viewModel.textValueOfCellType = textValueOfCellType + viewModel.delegate = delegate + + viewModel.doneButtonIsPressed(sender: UIViewController()) + + XCTAssertEqual(delegate.onTapDoneButtonCalledTimes, 1) + XCTAssertEqual(delegate.onTapDoneButtonLastCalledWithNumber, phone) + XCTAssertEqual(delegate.onTapDoneButtonLastCalledWithAddress, address) + } + + func testCallDelegateMethodDidFinishEditingBillingForm() { + let delegate = BillingFormViewModelEditingMockDelegate() + let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) + let textValueOfCellType = [BillingFormCellType.fullName: "fullName" , + BillingFormCellType.postcode: "postcode" , + BillingFormCellType.phoneNumber: "phoneNumber" , + BillingFormCellType.country: "country" , + BillingFormCellType.city: "city" , + BillingFormCellType.addressLine1: "addressLine1" , + BillingFormCellType.addressLine2: "addressLine2" , + BillingFormCellType.state: "state" ] + viewModel.textValueOfCellType = textValueOfCellType + viewModel.editDelegate = delegate + + viewModel.textFieldIsChanged(textField: BillFormTextField(type: .fullName), replacementString: "text") + + XCTAssertEqual(delegate.didFinishEditingBillingFormCalledTimes, 1) + XCTAssertEqual(delegate.didFinishEditingBillingFormLastCalledWithSuccessfully, false) + } + +} diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000000000000000000000000000000000000..7a799cd64629cc072c0f07b919a7864c944ed585 GIT binary patch literal 3730 zcmeH`dpMNq7Qo-^o^~#qkV0-7MPxQ3*GVcOQtpOLoLok(qj8JLWmj@bE;~sEh1{7f z%wWdM>68>PZjC)L%?`N?Gn4DcV9wb4>1qG5&vX7c|DCtQq(x_WcvbMnyyk*1XzT?-zmE;c)?<2n&tgIcrCDA{Gk>cXbw6cY!K^ zNZRcdU%mO7CQR`UxqP8+`D>oA{ zbrY7jc5x_OdKy(V9;gn@!C59!%e#?MK5SNHFONgqx|S691ART~kfQGBQQ`J#gT6jMdfU`_4mNjl4ComVHY}Fm}tNthnEknttGdgCn+T&E%5Hu z#ZYPwL?&HqN_u(r0%KLHR+JG_e!}25wWpDHAdJ&DbDPUpxIsh6SU)kCY>D^DZN6Fp z=|3XfBzDVP)dbf7fg`dmEMI$zL8#`M93-+z7!;osw2vN+70`_RbOdX>v9N@s=XI>Q zWX|Mdq@B_&i_IiQhvbEMw?44YnmE@bCEmbb-r)=aLjK8 ziZL;tXAqjJ+p~+xQTdYRUqB~ky%cZ^25Axh(c9^E}kVRbM zLs>oq$B`3${rKJlD}{h}eZQK-9^|AFOp}@>jZ95djB3vLUsRtz+nsPp!wrZ0?3R+@ za3!&JI*Z$Jv7Xi5=aM2VgJ`)vPv1_uGs0f)Y#i3K@mI~2c)!pqesyrH5m6x3<0@qm zanL+wpEGPeVA)CXx?YVtefe;65FSZ_UjMCfhJtfcN7ctrw4HD(*9JqOk|N)BFJagA zj7y=Xrbl8+9OFuT3nLdp4f}>E@n(&(PdYILX^Dh&YkZ{#&n**ntL#kI;9O5rkj}e~ z=XJJE)3_oqRi~yaOpS09HBr7|EF@Ej!zg`6o|$%xF{8LBdMv`g!TVQdz`jKoLG^x@i^`y3-FI@^WpJaqNr zvHNPR@Rm}JoNc})(I1CSFef3&qcY|1yuasR(wHNg#m_p8JpJbbh<3xWEAuNIWiy*F z#$((4kcojcSB<1n{@`5VS<78-?;8(9_r4B-P&Xbkl=1H;KG-S$O0yqjgeuL1#Oh~q zfAK2bNJy;JkQiU66BqQ5B=7Cg&v4`>GwTZG-m)T!@0$AULiTHUBd$S4`m^IWo+~=h zT%#p!l5{ae^P$$Bu0A<=qi_#w6ROmc6#X)$o$SkC#4N*+E2!?&X{}_o$P#^EIE5C) zoae@Gt`uW*4>l`XcfCv;>mzfLi3?$Fy^W{KtuDdpin-i094sl|Qu+S&y%l=lI#;`3 zbQW(l)f=yKBnZ+7c_hrU);m+hfh@ncuLOB>MB0F9SC2_3^`x>1NHI1k?wAEFq1>{^ zNqm&T+~ln^pXPhwN^6rVwK`Z!=5+POr1`VXRjR7@3yqODUV=F}h>R>y8}ruVIXrz_ z@zgl3KYN|j85G6qPYO!<`NRPVv3^41W;Zfp%S+j;KrY?VvcHUp! z&wrRvZ?As*yiRXtmN7afp%|K* z`j6ukzPxcCJZFPG(FKdE(MbIWl}UeNsp`X=eS0^}8HEdD7fos8T3V*U71t9=tK*hQ zR0hr!i?v2U`-|X(hVKGU5k++vZEH3xpdxOE#InJ6DzX=C|jf$SA9a zqBzK2$i9v@FK9>tgFC5j{Y~s*DO*0qB6@?Pn%%b)wFaYD=HL6hf0qqM7sjx#HgsSC zWo|RI2iBS#YR*?~X56kEj_W17_esFZK4c3ujM=qTTjZ9yjIk*_2vG@!oLF1eD;)d{ zDcNBb#b`GRG^dx&X&bRoAN7sGH@h6saU))pGKW#MAN@o%e29yJ|1&2XtBuf)*40?U zE%Vt7?9reY8Z-#P?QB8UrK#7FjyB{PUvKPRKWT=D=U*T*BM9TE76l;zqpRNd#rPCD zWyrlEwb9dGwMs7ge4pgI%vD{pzHm4-Q+|5c{;kV=UOm1om6O<+vhC+?YEPQ9jnv9c zZ#l48Kn*dHuP2mL2?-V6=yFQBX3b+=@-m)9@3VEWKW^z=Elrq?i6&rZQse literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000000000000000000000000000000000000..a68fe1ec047a3b50c559f180ef90c4fd9c7e99b1 GIT binary patch literal 122426 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000000000000000000000000000000000000..d5b97e0936158d6205dc0846d0a3121c07649951 GIT binary patch literal 4426 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 LqP1FUcM0I%9TA&= literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000000000000000000000000000000000000..55bfd61ee09644aceb4c7ffde2f37d95af5c574e GIT binary patch literal 4706 zcmeH{XH-+!7RRq;ET|}mBN#v?6h$ctXb=dDNQ5AWgd$xDA!r~$DMo^jXC=~`ND)*J z5Tqzzg0!eufDj@C2oNA5O-hIZk{BT2g_-4YKFnM1%lq&?xbNNj{La4ntaHx)+;tG} z-RTC{*Cb=7eXX8O)K?27lKx}U&1EXfY6n>R%~U(n|*Ok4wBYI z;)*~pfB-B3a|!=X?T4O$xd31|4*+Wtf8>xE06@730P=l5a%v9%VCxM4ATus_2YLUw zn6;9)8jS{k*+Kx=;tBxUKLCJ~`}c+Z82jTa{=;5XBx4jM`wWyken0@=3#b5a00;O0 zIug&CBxLA>x5y4-iZex>W)Y>za#hV&zr`yS;ez(cksVS3#|8h-oJR*--ri`~i z+Dk}o7nJuaR>wWEDg+Jj4H{o>()+%hpY2Ztek$-&fu9Qe|0_^TxK?4Ic3n9ioR&+l zB&q3vUt<-XwKlnI%#=09$?Wmq)m;LyA6Z$@i>+GLHl=IodxfVJk$fN5CWHh|N8(P8 zqK@wayJqi2$_nYkUa>nEb6jRD-Nt_*-kEguuqQYf{>X{$By&Vqy6++1U*zZ9w4usw zWEA@1t-XJibW+}foWsL$oM1oIv^(%(hcV8VXycP_c=cOpipSHnKQYPZ>Bj{b9l2F8 zR)gJ*M7PpR);t)f5G8Hc}&^v|jp>49uHq+_Ya!7RihUC$l*I#80qO1)?ERwt}y zvbLJXkGVYoF;|1<+8793{M-4NZnMSkzy*Jvdiw9GBbr<&ru+q+fsSa+La&xVos1_k zu>vqFs8MO4KaW1^=%`+?8BW7}vF?l0CQ^2p&LI#R-e z7Dt~uC?5`I6j`Boiiy!ffek}=ksE$+n*WK*2wS$B2yLez7vf2E3m^MSvVHAutjJqm zZyA^QF1097aYyeS0qQF&_TGe8Q2ByB0VR^T)G=-KbwySqVR-%*?jd#R-T5Y}0$AZ( zpQwr759-?g%X}(CY->tz4`3knUAn)hO{LX_pOUM@Z%|2jQ;4N=jvlLcuxl0; z!X!^!<5GLMMnXo(Ee1H>SWUnMYt%J&b6~BZ(3*#q?qfw(#nvOAKy|o6FYy58@|c3f zg98a?#$%@r@8AEX8iMUgecoeHP;zJVfhe*&)PJNku(Pb#K~{*w+XYf!nvWAA=OQy@ zqgA}s4scCFNsiN>y|YXlpZ3`7pe5;hF4uaM5!Ax{Jn>ChdT8#`(oii(>s(v#{pj@H zk9F<92c6iO)rY!mzg%gprEc94ID2sFmIL3xAq&RVeXLBar)3-LQ`pW?+v5OMK#%ry zW8TGKQtKAJK$fGNcJD~5MfYfRFMCqc2JqN~0bO1EX>hsG*_rNEy&F~TzS)WX0$2fG|S;&VC3j19?3>9L#$N@>?^<`&dJjRxr7TgQ_Llp4q@s5UTpc%q!TSN}d$TmbSdG&Rc!vc{Di5 z5>0N#-=u|Kf!X0(BCL1pB9YQ5jpdzd`V2G$Vx^oHevN~+F1INjsD05y-$MkdR)bf) z9uFkvXlp(3x&;?OS2`2?Ues3=lRj4N+B3AC9EnmoDRgVMPsr&daJr(%Ii0STu3yyG zgjXU5m}Qy4jV_U@mzo>H$-5^87YE#)Ho|z+hyC{)hjcl#g;rxw1t;s!d!BG=Kp1Lj ztyzdLJTg_2@SIs!3nUEkZJ3PM_=fL+8Y^=^}9JB3zkwJOh@ zoFFrJu1{=DOE2o<;F<`zC!?WnB8(^6KxG+WdD2eVvR*RmT4byIT!DWCakf->THMQ0 zGKrD3QjklJ$df)AkXfiSesIS|O$AFvKt0FFOH|!fgf~Twsc-haCim8E2^xe}<(&x5 zddm*yI8*Y{;Bl-O`@D{#U1rRCHb-sjmtMaoQRKt#XSt?twHaY^Pqn@PyK26QKFs544=;7i^4qA>pqeE?)&^Yo(H% z6;u4`=De!Twc!K}Gv(R7@XY#?@R43tL;?5sXp}fU(&3H<;pUyRRDa%Oim2<}n8!dN zTNv*A>RNy)V{s4t z3R~%s~IpB zjnPHmrdN)HYqCyC)hS^|nF#o1fSueRNKeGJ{m>6*IaRayCUK_){5X5U(E?>wlkowS zJ#5GIbS`n$O%@X-P&SHjnp?2Ja~ilpNUVyvHWc}e+MLGmeRl}jFd2`(7o}gm7-AgP zl2B?%my_9nq1{S-GILoV>cRwzvrQk)={`AI>ojLXFw<>_EcK`sMFsMzxm`5#N!7un zyFxZh3t^vAp!3XD8Ny)NLZdNlkh&33o^j$@si4j*?6+D%p|P$%4{v71ocu)fTJLvN zamRVK zf-E%>0&y1vDG4G?fe;Z%D3UA$2oOSUxcAv-?}vMz`{jQ0J!j_qo%g)+%*=o0%yG51 zv9Ue^0A81@oIRb-U)>J?fU2mZ|MRxLc+pvIr|1#bDYsqkItKs{Xmq5jt(EFk?`x{t zvA^tQK-8VT_&@j^0I)g?h-v^B(E1PW|5s>VU{F+mDCtj8iH;O?4gfm>MSM8qUmUy5 zxBkVc+Z^fcdQp_~tB6m9{2Sl;H-<;wi5BI&-OdlV6S>XfA~uJF!?yd{w(Sug41#*N ziTqVjQ3Rp@SHKpq67m1l{?;=B2LR_+0N}f)f5&cN0D$-i0OUshj;a3&01^)Ypt0}H z&B&Yo9Lz3Jy)!r%0G7%CK+GEeq~8I+exJVv`ghyE*W$m-RaMkRQ8dp8(G>!O13`c) zU=Kin06<$rdcZkA7cdg-m@9i^06-`G^>IK9b_^%{{ncW6dNH&?V>mMI-7YPiXmh8qhpOZ zV}QPotlUo*!CWCKME9zK-Y(3Ge*Vm)b7Rgc`y+}za^L(n1->cp zO@VI;d{f|?0{?dfR3$Usb8ZF^vhOAK>AOm0oYIxA6l>SA#}yrrIgLR+vL0V5jCt?Z zGO;iKPaLK3jqA(1KX(vGs+Lk}dTyS-kn<#3>mE~TFA$ak3PI}a1cdHlbK>RZrXTeC zE`ZmO>4h_hS%0+?k{Pu&4PbW*C#?r!CMRxHeIH$^w_Gw*5zLA9D7F{h8Rl-rOwbpM zT3f?P(B+9?a11He1Am4wFgy%uckm4C9e}TL?ah%VoE%(}U)YQO{s>55Wgh!8VI%w6A zGN|;~T2E?MknWb2adx*_GU0+>djfosMQrYePM{XhF?(6-$^2{Ka}N64;GQ9|NLO5P zkyd9Ee1mRwN?pf8B{%Q#(l1YQNX~aR>-iEB<-diNAjjyb1yF7{m=C4UA23%f@BBHF z2F=%2k93gnTn6RK8%u)@8eNHpH#m5I$xgkF%QrC=s6r|d;zplGGp4QQ#>c zCH83lSff!x1y1ub`>2oxu4sZiJ7Zq>lmTiFv|&w~2{y6y2Cz`^m3S^8(?QDiOW$vT z*goIGC6;5}^;7a3)cw}Z6^&*%sO@KCR+Z5?gqilU6J6CLuk2An zFX~jqx(ph0BZ*K(|C$B&xXs87-k=@Ia78EUJ*no+JTg0NpykD3Cd~Nk27x?DYZu|{ z))X5=!|l4|DWYI zJ6+7Au|9nDe(5PYUel+vCcaTJX5ADu7~@-K)<=E@G7n1qmG4 z6?rCO*>|DCb>k~!2+n?^LK?tDj9fQy(wO#gy&GtKQl?Ydc;hB7KdbqD!B^I9#896|UPm=1Fw*uO^{j0CO`b1nr>3vfN{^X*GM@uW zBb!fZg?+!==-@D}$JBBf9~(AubmVbnjET)7}5c!aB z{Z@P8TK)oVJU2L8Hfg#k)1@Q(O^kQntB;)={9voESxer&?7~BvbhFrX@P2BKK^%L` zk#kI1yl%umg~Ba8c*flfpl{}9b&O&ah$Ou zibOj`^Mj-agJ{qDs<%q2s9&+er;g3#?2GWO&c5^_u>H7ock}2avxJ6bU7w^Pw?b<^IbF>s|KAl7rV#TV3 zH%2GDm2&eg>@NOFZ<9o{PV?99rDQIrhwFUkBJdc$Si)FrB|`;I;;6gj+{pd6skDe@ z{@W)@d0u$pOmHk|?%>RE3j2$Y>^l&>UQ;N<$ML_wnAC|O*?dz2V()F^2$c?TZ$x6S z&e;3I`J+Q^Aq|eh7RRd6)4wxAQXrnvalW@1c)$25ot3pmh0N*c3OJPysdISyq%FQd z!=HWkIRZ2Hn(SxEJN?2#W=G0AGts{qH3QySI>P>v%L%xiF#}Frhf$aAv7}`-qmqJ| zG}7){x|3S_BVhxnYR*>@$t>f`1u9yZ%p1!?ddALIb#_I$q9GA`vur zMg`j(MTw}i#@5yjQ8|+{oAwq~!B$*Y+B>wJwHCE2f980}+-oJ6(y3kTzltCFuEqU# z-@P>#hox7MP>m8Mg+}|*LgosZZ|kEE-hYIxFNHw&8^|fo%y_Nx7Bk;Z^}f)4+`?`b zF657Hmay1glf=bW3TSl>`Wu;9d2!Du?y{gkP2agL#_~Fkr>^Vl?{UM&JN%^zKbOev z{Aqj$xj`#TKvlcFHwSry!w^%;Exu!DHQRv4GF8vMR4=c2l+|P=_qzKUIkDmytwU{_ z2mKfN-QY0`=DYA?%T6)N#mWYkl|pH6`!2I)J2-CE-o0e+GLou9!JrqV4tF2f_K4?SjOIiVzD`q^9;z^MP!M=Z28pl6UsC4Gyc*o{ z|L7N)g;uXEt}UTf4Wxa{#|;(+chI`g>Nx!MlTyJ8^;(b`(Ya6MB=X67)iTb_!8A}@ z;uteurHQLzcK!qRo=3%F%j=dBA)74ATK^w69Mb)p2DnVya>az$L6L}I7Tv}=5e;P{ z&u67@$+)wPjjf^VPR7vFQX^^s_6P1(E_%nA4Y0-uT>m*X@zo7VfKn8k}=Dz?mdr4cTIm0_JNXC{P$iYOzaozGA zfp<4(UgdjWucA6p^E7dUlUChM461nn2cCEB-u_9aD24`(KF}*Np}d^X>EqSM3ep!W z?;I%(#>h8j>F=uHksX^V`@Ry&QI$UWF}ZuRb5dFCC;l8ym)n=4eA(&UMbV!vni8t? z7U|ffqUtLaYfE(FM6c$Wt+o)GcjqUEXTe)gVYJWg*^hqU*3QTWQ-u@Sg=KHB+0V9ahIPm1%G+T}%i2b8}LI_Az zUsKAYgED=Z5#R7*xZiIBBjJ!BX*9^H-C-zGNdsh;8t+?I@Y&&#A{nX-<})ql{6HI# z>3&~lcOxA3MFqc(<&eQ2<`KrHyQ_o3`oYXr;p)9loe|4eW!W#&qQ80KGRuQrg?K^Zx z>S}BjrEhh6i#8z6pVI+-$!=}D*4sHjmuK*D@YjMC9k+r*_Hr<@#~jqJo1~W|Fes=b z#QJ3mWXDXhdHZJfgd4n&LMGLC8wW6I6|Cwb{50q*1z6dVkULTNNp1FelGMi)aGig^Y?|J{XJBk<-bC4yp;Y&EV`<2ALeMfe6Jg@9~g5%@R9XLaj^2Cp|x&oef-u)79V=A#mA; z)(YPRKbCxgnYK4WQK);2%|E2rn0QLL$Pz<_)bqOfx%ha4L$9=XWec0O@TYk{z%_K1 zm;W#iLf?bruY3mEa2%teLgpVL+x8EIt|LC0tJ%UjZN(m^Q|WIQBNtxuZk1L&%gn|H zmL`QUCkKU_d34CRT`sZ> zrB#YxOl!+EQkf{rz-WdS!7$>E6n(KYs+hc9Op()*W3Ck2;iu2NYz)m@Xq1}+!Sgv7 Qw|U`Nfy#nVAXL%%2aJujPXGV_ literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000000000000000000000000000000000000..763d6430197cc42d962027ff08ad46fe4016a902 GIT binary patch literal 6668 zcmeI1X;_k5yT_m0&8238Ii%*0)-E;8p(1TNmZ_MMCYib&z#M>bfP}&<+g4hRi9@Jq zPMMNJXrj_&=7456q$pG>q#~p!sE8hV-)mp{{cz58zMS)|`+3&7f9rnkb*;7jYpqX@ zn}famS``2|Z)bhhV%Gl@`LkUI!bSvr013CLp8qvtD}`01(K?aJN&|dp)5S z_Wq3hZGHg}m;dJf#;*YYVLu?P0f4Um-+ceyLYo3%5dqSqAJP&TE*%^I)&xpQDCnHz)q&@N;f9(wuxL?+^M9_WuvYL|%@R=6v{>A8c1R^Zz=U6}O=Zv?) zknRwv_mq}BKm_0hoC2(+{C{fy=!q%-fTQyO@LTdfG5;(8sJjgSN<;s|bn*c}J`MoL z-Ix8s{r)wXwbEJ!4hMkQ5&)2e0>F-s0I=EX?}`4?_n*D^AJ)28+Gme+oha!O1cU)F zU@zbRAb|kDKuX5IVZaD5lb#r-mfZkgNO-jmkd4wTSY3l#Sj|h(X-dsTyGOauxP$M9 z$Oy)*meK(adEBW`hO|L`KUt~cqS9w7a^iJ^?jlq-rP`inaq{^5bAyF15Z#}`7-TNT zq3Tb=8xuz3&77EY zzZCeTz%K=UDey~y|1Sk@crFK#L&A-3>1(F1W^vO$_-t7yeG9@q+VaxmG9nIm(3<24;y-pnHleHFh0Cg z%$hKt@>jSaXB4KGz^Sl-AUbVz5?O5<{*s+cBvYDN=Vw#pI-Fi)o@Fu$bFiuBzr9;F zGp)AQH^+xjMo)O;F-9zw-sO9s@5Ms?qHVpq5k{^&>KO42f9K$n!YUsh=Jb!yTkm@v zdCLz#%&^>cttSm%>+`Qn`q1dL`%gNp>a0?2`%^pvV{3+nHjejUgyEPiWdg?X5c{Tx zM9u+sUi}hv#h(ji*Oj^KlY!E9Sw}l``%e0}W>rXn25?kL+>OL0p+kHj=7L@u_(G7d zCNfV6`9rc|Ps%@mSpAl};oZ43=-!hPUpmzWYISwC;sm~ocX7s$q~8t)8=f5ClRCpF z!e?l_yh6+m(etdN;qKDVTpYnyWx2h0^CcabuEsV!Ww}e{-l)DtUUs}^V27^p*o>+- zv!-$AfQnmE&MN9$hn6C)OX49O%~IV3VOE2p4H?W;cX~>U{Z|ve2CND z8W_j~fiZPtJTk7Bj;*<98sopzc6#SSKPZ>XDztANDZ;FTUP8sDJkDNaH=c1RrS(8r!#WvU=?k<__3Ln}n zk3~aVcrV`;7`q4rkrk+nm)lsi1NhNL>EFkaF=9p--Jb`4?HVJ{r}}O&Y01E0Bl&7b z6T_)flOqUrR=BXj+oQ$96ZS5?hT2ie^z;;QSd z`Uh%igN7rKg_>CzXIeVD7zvzd!VsYLSYIh6Nq+ z#1@U}#ouo=&PK``Py{#TrZ?+9Gc-QRF;KlQYWr>lb?lG2Qk!Vj2l@dpYa)>>i8?tk zeOO+Vy-)Emx2@ZV+J>I>e(*iWwVaGua^FDhG`s&1cjDd^(BefZG;0v8Pr|VcG)uM* z-khcIzmwH>r!V^F^GdVU8SCZ~E}#CaFFH7qx0`D|Wodj=Y#;+YP{W~M#)+n-u%7f! zOXeh(_uB?%vx?MkJI2N?BBpZmbE86VTe455yCL~A>MRksrx)8pr1mz!1R2@tSqiW# zL-@?H0~5`8D{C^Q*!vznR;IgihFc;=P#!^{8MElCio0&(!1r5dk}Stl7cBoN?AHM&ZR4&Fe;JJzwSYu#yRsk&9Pn zg!OGhhMK0LBbI^S>9Ojm24|cWbR$e;jWvO)4{aShZgAm>euPOv(8w;W0O12rLz&(> zSSQ4aQyyKdabybQY7e?zz*irzfm$yc)L{8i>N#{qnoF+!qiU-+{=O?Dd5?>tr7XpiK(7*Y2E16 zB~V*kx}D9G0?I=hvcG$0AbX6keh11;&lR~Rqotc}SKvRjZgR0#72D7)dI3p8z5H(A zGsW8uB`DX>H9j4Dk<*V(!cgHJRUckGwb7Udg;B3D@ebzRl%;3rt4UR*_UqPal}*n+ zpYmZ{Yo#5aGjgw-UsE^TW+9j3#SXy}X{F}fZJCJ*vviC4T26FP+FxTv5fD=GR*0;n zj>4xUc+N7uYrw2b#O%3^xiUyRrIj90GJ@l+@+>M3SGOF7N%u&gVh3wLlV19Udh~r( z$HJ9SIGQ92WKjI>+Z~Bg3W`_=ZJc_{H?z_TsGb}Gy{tRsTqZD~z6d5p?+2&^0*^HC$Izmin#DsQEI(2GPXN42Ag-5m> z=48uqV3cSlJ>g(>*|*eODy*&-iOzX3i+y!yx6HQS?ZPYyf~t`;zn5fNkc{ok>Fb!2 zBpR_~6mDed4kkNgp)|LbBV=Xn*dansX6-drl);VhL=tfY-ZI)H$)Kr5!Zz4Po(!@w zKYD#mPNnbkTpFun08O{^e09#dE~XRy#`(dJ{Nrp$33I$|>12)b$W!ltoZ^Azv}8bM zryIZNZ4R~(k!!5&hn@OrRWtluJbz7euU&Nngfj$RGj~5JpIN<|#6%jI%A}OKYWFnL zvxaVN54Da;X?A~oMYcVK4<|GkBot=|_}^~x^z-U!RiECvD}TK4Ibps{=eS90Qx1c_ zV28V%A-(lI-g_(~Le~3C+AtAE4aG6Oq)BL*^mYbdHW#!PP0yGwYDr=ToavQE%KNjt zDJ5cNUEGCZFhi>GLJ?xgjeK#*)QfdZ!0OhR%Z|bb7nVSSe(Hs`V2_&YrK|GD@4+)? z;`jev@p9AWSqp?vf-M%?%?pHj+^fT4jTECDcVnRP__|hJd~)U$5V41xnSD;fy4b6> zn_fE|>5-#2k~E=_Jl-Id#C+7gn5+v)I3sDU4ElK z%D*+%sr06*A*CiBd-gPuv}jisPm@`*X^Im~m7wQ|W+k1MKyba3jj#rA>L$Ww$ZN%s zJ6U`ROM9}jw6A4y@v7ee6CE|9ihW zDyP+x{UN=r&69gLiNQ}|@akjQcTXn`PTc1E-uT>wJ9I=CLN0bK z9y$Bf{GO>o39Ik?di{ywsftn9lxR=FALs#mXE&V~!-;1OWWGNb6txT$Q)y-q49j?$ zf0{%B6}M#QAtT3$Y9<|L4k-nP&-SPfV_Tz(YI=IZdnsiQh-A2MA)tzJf;&fPX8G03 zy2g*9RFdsK^xOH*P{Irv1dmx9+c`%vf2>e$CDR$pugC-0ik%hjD2}*H@QIWc)n}~A zIr%!OeJQJojFrlc0*99?VBZPeCn!eYD*4i7!Z2yxL!M<7F&VE6Zgc>kYmShpbTRLF zeplZLIVS~`yV2DO`ivKqaKgK?LyIlw7Oi+z*Dj0DhV480zt-%Za69@m6RNeo zY5Xs-n5f2nxck1rXMqAL7wmgPDC93owb!O5Z5;1yT7KNLW}<GuX~IsH5kOUZ7lU69fr|q@!4P{vRm~yBE?A*EL=9Mwk4UvczctWn18*j3w3+D}neCD-- za7`e`F^lbM1S$c@<1X}PVuu(Kv@*Fa^Ne=69@g!4XxUh71bRh%8MCWRyyx8c-nXV<~HlEi%0P7Jt$9&4YPB4U#s7P?mt{Rou40j@P zqjt(_mv~0}cv@HT&^QQf>`f{S?7V&Y=)wqcR)R02IJbMD?YV>!3hVN|O3$tMj)F?a zlPRb>ZMS?(LR1Wu#ebe}StllN2fw0H_9=27d#vAI$h=17hw6lk-N!siXc!BdW(#T^ zd9K>!$BzuU6g&aV@Zo&E*P*FY$Z>oLX!VD>o^@6gft=NNmaWq;(zkwbwGm*3+@uOO%#a_2ounx5`Mp-WHSCi&yV>qx%`-MhcpP u6jGomTf(Qd&b+o9Bs@#(bJw^q8HGO_kd|nt^J0}aW4LuywCXGUzw=+h03~4n literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000000000000000000000000000000000000..71255c59723f15fad9a7d3f28c375c9188e514f7 GIT binary patch literal 7022 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000000000000000000000000000000000000..870abebc982ee65de85cc42eee2ea69a149a3b3e GIT binary patch literal 946 zcmWIYbaPw9%)k)t>J$(bU=hK^z`&pY#4=#y>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@yTIiV9=LgU}va5v>;c-ee%iL^%nE& z_b-3ApjXA+Z`;N51s}2r?U!FTL!Voh`-8-tf_gdK+{S5t3%e9{bTO>s5KKN? zb)TW2bYI@OTScblPHwu#pOC{K$S@IT*2D%62L^}jxwk8lw|nN^-ZpiK{I9d$>*xHM zvS0bv`UAPrsXfQPbHV}zjsB$KIZ5SYQcTU+GBaCiOH<>`ANTBOm>Vwr`r9`1@78Wh z<~yflrRKFC4_c~W*Dor*cHQjvJnK#={k-S=Z2J0J$$KuVpMHN@cljreeZPNbdh3|k zyuNTE`tPPamoC?Q({T#1OG2oOSt#h~UnB0|$;1A47%B}16TKTP}e&X!Pj5YQ* jZri?+s^2#=;8#jUO+`sg%GaN-oYy~`eeYuZUtR_PfQR*` literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000000000000000000000000000000000000..d3412d3f2100eefc701122fcadaf19e137c2ad40 GIT binary patch literal 1134 zcmWIYbaP8%VPFV%bqWXzu!!JdU|>)HVs$X`baoDqU;=U(m?S_Xiva^eZeB@Ikh_yY zL}Zi#NDKxNlZy*rY%DY*1H-p#3_y~B;j%6kc|t;*DXGQDKt&&bxTFYZIRgV@3Xm<5 z4q;b-*hvs}4~Sh9666e2vjE7}NJnBPA+gI#3QB-#PJq-W7ZicmcYti0+?-O7T_6B* zF;8keKg93vmLmopigC3A +W+$Y2IcF+S?R^r5eQfRo|;V}(g7uB%pA)~Nl@ zif=h=Hc7-X;;QZO^9&m&s<;NZ>B`theg3!m+vof3Ke&ZAubqDAZPj5FueqswQgfFq zP!Q^2%24rW+BrwR^<{#PiXjJEXApyd&;q4|mX|uk75nURU#H&XyM5=3y=1CYY0)&x zj8}?=B2%2sz5mZ`JaeYAV*pTbfLpUqdbD2u^Y)jH#SN<_rejl-S#4IbG`4Q*M_{wk*rD+36-f@A=<*?|=N1KXf^4w&36J z2itlteeC-v2n#_XX)VQL63IOqXQ};s|0m?4l9HT~KVQwSvYeb|UK(Rt{qN7r z;`Uq1QtJC3+?*(J`ynnuplXbbg=JFG( z*Loj(aBpkPrfSpE!nZ`e^=P=d&wDK=6m-kRPOt%`YQ$~Biz|x$bm~4f^)q^Gef`w2?fOrX zcXw~?oAl$4v-a*b(K!`S@3o%pt9kL~-=hgmihE-J@2rat>Rb2x$-$k=H1F)1c;m_O zwr|)HVnZGB z4}|FqISi=`3JjhMc?`)6dO(&Dg8?v!m;qCa&jn!m&^L78VYtq+aiWTAP}()aU+>@C zZ5HOcZC3PT!IGJK&oeqndrn$XaP8f_^N)TQ+uZ&0ouTgV0e%J!7R8@Zj>hcGB3=`V zZ!FemV__EQWJ*x+OHt`~k}c#qkwJpF zU-6Xh|8IYsGfT>~X{Dyff&jj1zUMh^D?JUmHn9aW%#vbU%&0Qsze&SCW`&pAwr%x` z`M~uqAiuD@{JWEEdHM1kpC?Xuw&{OvZoy^=!>$+mnYQOnk?rZr|G*9lVXDv*{`D== z=mMg;VXEL)|USK(UIe-`Z8Tx93fG$HF&Xe}7*rDJzdH&bmt*X1(3&e`It&_C4dx0&y zJHEXC{pd69{1U=myYjDxxs0sJO83tLi)@bpPrQ-Zoi{bbv5#**?mQ2xrKkae&h>9mH)oC zA-`auj?VKBZ}Ly-r)&KdGCw7^ygnsi?)>F);(OO-NpCvGD{bub+z? zG@IFUvgYYBJNJ$(bU=hK^z`&pY#1>%W>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6U;1OF=n1M>ugSkg=ehV88k3=+2xVk!$5 z82DQl7`B}+NGwVOJB9^FGNq+4Fnn6hz`z^Hz#x2qfq^R;=1_!QL|owTs{&Au4A7tX zK$y;u!;s3Lz~IS{$B@jR2V@yB7%&(zm;qCaPaZP^gT4g=AH(^l3X@b^U%i=`{y$IB z#Uk&v+l1mp#?|YKFSt!o-dg=kdD`>yZ{J=1lV0WfM>~k~Z%_A;yAN-~9yu*vpPL$= zySFB@WBK~bgO}Y`Pq!D`xVvNi#<;q&?E9zczD=94-a(>xsZs~W)Q%4Ot1^3o&I&Rn z-J7B9cwir6>|67``>hKtYP6LM!`rt%({ef^S|S=Kv#<2G{ab05aKY-u>>cZ@l%BOE zt^2lCPJ}U5u+x&kN@(w^2Biz}N{>FcEm|#C@F!MgpQ{Rov%sMjT22!UL>yQS%@B3z z;Amx(U3Az>aN>)Gr2QN716n#5TwR(xG?aw8I4(@fjov!<$X^xpcR$tanv2-A1>)Vc{4xNo(fri>HOw(;=x}}-&wuo_m1<6owoh6 zJ|6G4^uf`2?LoIT{@8Bx^iguH{L1&&_PXENab&jby;rApJ$W%h2>Z`Uh#Z>ipXe)3j^r>Ez=_}druo&U#|eu=vlkC$srH(PGB?q*2a z>Ew3;Q(j(LvAZbEy~^(Su9Np$1447(z5SkgO2Z}m{C(>eEBD)dJ7gPsY5Lh~bLUx> zJw0ihety1v{l6RP1}4k$4vd(oqJQC&YBbzSG!Q7YY_;| ct6#tEd3X~)r>tU&fD?z}mg)a@x708I0PRcfCIA2c literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000000000000000000000000000000000000..0fea73fcb82c23e784e320a64989dbc1caa0902e GIT binary patch literal 1512 zcmWIYbaQ*a%D@or>J$(bU=hK^z`&pY#Fk*>>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@ma*oz@TsGz{gG^lBy3E?M>Q~fO57Fi77Z*L+#B(5r6Zb7v_3-^I``i3lc*DyI z=Zh+)p2ww^s7+F^oXOy6U}`#X0fUi;P(p)Bi{)zuCeC(ylkr1(x8t!R&o1un?#D0t?<=V6_ub@Tdt~k8{J34KCiXtw{9dbS*Uxi- z?bk~GYgh-a4DpMwtjgv&`AdE6d8^Wsu2XGJ)m-~EXI;pay8hGWZKvM6@n@CZPVH%P z&jd>bP2cJ(|LV*glTv@1T<6QbkJcIq{eE^wWAgEQcH0$2DIZNgl^F2z{CtYIPfMs@1Z-B~9$9?E<5v~Kr(*3adC1TQ((UHn&J zcy;E{g{|g)ED}n;PA+-7Ptg9Tl}rDZKX(rA-S3&=Uh1|X`_bD{u^)d=RF}xjsje;c zV*gb2*)1~dX-n?MDL}7?drV?oWV8RvA+NOH)7_^2r}eG>hdj(&xi0(uz9&~ceO|RM zGI>#@Z_otmV{-Q|yxse&LnwdlhRqx9r%aQtm)!qq&TXli76woMEm80{<&FD$YF5$C z7`^>}u1&4A)74nQY+3bnN#WsketEl^A0Hk%r}t{ER`Jnwultev`Ptdo=K1&bRDM3c c|C#6IoAxJKJTH55D7FYVaVY+||2diy06!7-9smFU literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000000000000000000000000000000000000..3447c5af16e7fb22a94773c9fe3006cb36709a65 GIT binary patch literal 1492 zcmWIYbaOky%D@or>J$(bU=hK^z`&pY#MWTs>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@#$q|V9>Wdz{eoZws4|~dyw1rU60Ry zzh}?ZmV4Wcuk+nrzFTgSmh7m`6F>bi{rmZP{#QFSy5g^1@LwphwWXq3uys<-^zG&X zRwpD{T^Y{&xN*Lt@6Uw098y0w_iRmXaD7~qcz%rMT#2(IMBeTd|UTyRMW-zC*@bS^FN6Md%h)1U;eb&F|K&G zyO{3Ex5xU8uX#2H&bqfM`t{8)-=fS}&+c6PDBIfbQTeZ(*QT$f+b><2`{vMszm6}P z^Nv5=bNi`YCF|~Ecg|dD*s$^4Z4=!a<{vI6oy*SkXV?9lGQ0ih(wk>DTK^H#pY^wR z7VGWall;cvX`UM|{S3~HzjWo<&jlZUTki>cl^XiKe%96>ub%KuN|>_4q#{4F!F2Pt zkn^n0_w`OTY}mYR&m7a_^JUxj?e<|z{CwrTSNpQEd*8O~S|8$l;_~;%`_1)1J?UQxhM_m8@=hf3~youd=Za$T>l>cVGL}6pcQl9?x!CXl>2@A`D1NdPN|z-_Q|C7-!(B=iYXI|-_DQNx1lUG z&;O>>8=cViD?|^wo77kSJ=QC2o)`1~S;~8HuXPh1Ubp%#BkCF`;(BpIM#=2drB4>* npGxMRQ}g0Tr?9%;9E+b9PO{I_wGD8*zv=%K>0k9v{lysoVk7ip literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png new file mode 100644 index 0000000000000000000000000000000000000000..c3804a3def5f1dc905300ff8a9d6e6a70a43482a GIT binary patch literal 2500 zcmeH_X;f3!7Jv_kwy>%QVhd}5ML-~BE-rM)=y}!HfKI`ng z&qerodpBzW5aQ(?6ddGqTnhkT45`n@<>%oMq^}OW0(E_r)z}LF2AhIM__!M%N1ZTM z#XiX?baLV+{u{3bz`_84EC4*Kzxn>3LYmPr$!I8P2GSHfbT|NN(Gcs!{mI{{IOXe4yhqX z1_)?8?hyZ1Wo@1~1^`a;0IbVhi$xUz(2xay{@_~7j1GWyCIIz4iKp0C(*YX^+Zjr=_}+S>{L-3M8Zu5tP>+EY4AuG33mh6=ibANRg#m=III>fM zsbj(-qEXrQ&pnsxF~#|})7-xmXAMp(l?Il%ME1oiIa|IMs=ta%k>ht_6So8Qog4vK!jPC}V^Ka0O+aen{Foee`t#Vg26?v2w3)22g=nfAgbCbBfLqTTha54FHi$N+?*Dtq%>0r=7A1Cv4`1PE7 z2+{m9W)C4b$kd)SoRNx_7@>YSvTwcfXk@Z=+Sv88lIhSuy35bnfx;ROQgG@?WG5pH{@@-HJLeq-Ey1Rbw-N7lDlTUTj2{F%{kx#cUWTv#uJ)-HtYh!O- zv!x7UeqCn;lij!=ZECNWJ8?10M0as$#J9st0H=SYd1KZx8mK1-W2L=>-np3+*ZIKzn{g;-VPF1`AeqUXO-@+5H?-KryT8=vB`|CyJHRD_( zZz&~Viok~IWs6H;?33~-!year7?IccJM{0#FC}T^who(C-+Q#tIA)C`x9){ag5O{* z_g)<_+Yq}#YFb+5msxfF^!@uqtKr4Tb7za)#M`Co86|eb?Zj6?pH5uT@g95{7sj3t zL?j2-$o#8JitJnqaKZ(@?%2WMZ4a+7ekGl=AWjq;RFbNBsaVqB9g^q~8rI_4V_mv= zYodhm?p7lUUr=6gmsF=#rdxg{J)V^mj%gUJlFoM2y+Ma0-`?YSQS0=xKlpPv*(3?!9h6d66DMY2S9!-dt> z!3?FpOE`{Jb$Bisb8FS6(#D0If_0^rq#lJ-gVHincBo2t_m; zziP@3vwHG87)Eko$O8p6t0Yv;vuuRZvUP-_$dzc192l<~RoI`v4frz7JJ@tRaeMe< ze0nEqab^RRd0At#=B(+3cT#-5!BpfAo-SwjJiPLSeM_p`$hv^I?cm)LKHXZPEn8=B#WIxiLrhMk# zAG+PHkjunLAG;K#Mv2+iGrKIFG%vj-vt5=2teH|=Na_w7t*bNn+;&p^>*acJfU;3P z&yzvvq}&LViins48|(_lr#m!w@RhBR6W5v5{PZPVEnA!$k!EvPN$mMfTP9J(gmP~qoAh+^1DiCT zc}6qYrG!Q%?5uY4~-!WCsVC*(mm?1fA|9drJ4Z7pH)+p9~>wF}Y=AIn$%;qL1#`YMga zmkyE>1n=eIyDU);9KPknB6W^O2pgjtDT$@m9uPFQ-jL7EH;Tzgb1*FRmVPGJ+bjF# zhz^Gn0mDxEK82f&7R2Z>Wfb^$7MIdi(SN0&oVoFSS(YW7WLudo+t+Sk7h9wZg!@I` QXMC_JDc~rZB<*Vd0+-`i>u5;=j_=(JNKKJ-<><( z`DW&R`vU_4zBB{ipugYVu)WxD7y%O2pkG(uu3dX=7sIb$vF(CgvJrrU#1#5|ydN^0 z^aXMu_Fkf>j3e*)5BwqkrW63S0LamQ@cqAqmc_&}sBqFtSX1cm;Q%a(f!Uh&8y{WZ z=->G40@Dxd-v#Fs!|X!)9Y_C;p_C&ja8Bn!KJ^HFf%{FpGF!=!d-@{>6Xj6$$ULgZoT^9~y`Uu>c7IK_Z|63{0M2 zBk%xQ;Tsd|Uw z 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 Zg|^eTNwM2XT@Jx#_QACk_3!i7{Ts=oz3>14 literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000000000000000000000000000000000000..1debb946616c95ee6a17594f9cf838689d71f24d GIT binary patch literal 3174 zcmeH_XIPV27J#p!BMJst#K=;mh=WK3ks6$pBA^bvLi&H%9s0H7pPm*0l9nVH@Gt->kTx_{GdI|@KxP#E69(o_j?&P{1E_Ek_m zp}}AIPy7}Dc<+JG0`Tt0pZx!Cp`E_yP#ayMAKzC$3)3L-}jlr5@x3pZ_5d8j`A^$36Y zzdG>$)&YD59ci9JG&i#=Y=msj=oLx-ho5g(>Gp(Kpa9|=B?iKOi#5n`$@-M zvU`N^sz%dNYpLwycrqN*MPOK$$U4J_2d9fvtkrK>QKD8!O47;V%k4=MuD4seh`H1x znfXA>Cy$54P_ko640h!XCU&)2fnx}LA|8P0Xd7jXpWP=}D;jmg zc&96KPNaLLKjeJJvB`;%M{Dbu`Zt%#Hl)#bWq)m*kFe%$Pd4j{WSHiCj;^2)q??$jn(Sp#IthcEdt^M_mFSRE{7sVCxjmn<2J^FJ3rdUTHQ3Y&Vr@Z@3K(oEz@r}yfV}1z2Rmq8gDVRXcG6KPvOgq@P6e> z)pVpoKa$=Nqz?|z!uu}-9c=bFFDbBMF-*w%ykc}tzw{ecY3qq| zgbTJ4-OUjWnHcT>d4MxQpjHG+@^(vFE-g|pr*L|mUdNp%m9layGv35KqETstttY?1 zq~oo1{S;c(EkWV==<$}0I)kI1($FVUq6*swzK?^fLllt#m)2*Ubz69TEQGYy&x1|# zU56nBIdP4{*r0tA9?zY~XpO-E?%Iu^j$CF>+x!bRU2OWoUFzkGsYR?_=jckvXfLfQlbnBu@$`fKh;D919b0klMtrA3X|Fk} znN!W`Yz-)lp3<*h;Ja&zvBND5Gd|7G186PRa1nzm5%r`MWEE^6D=;*>Vlg`DyEYhv zPV7tHL5Xfwz-7|>eW>;f+ozp*l~XB4=DktF@^vr?`a(Q&T{f+gfQryA*)PX>g^9BJ z@k-1Jx7WBI+82GN(WzMBDs#QigM4k+*o z`dWMG{kVmpUN`gXEXnptF1tCd9>?Xk>8LlRns!`cyOKTgZE2krp>-Z*4)&|t*CyF6 z?eVdZ%Y7&C?Fg4-)fhrrC||R&-!P6q_RuJ_JCiAB;Z5apa^9^o*8|eD2$$bn?wIQ& zM4QWaomYwoRtXb%~&-O8Dy9f0FQ3={OSqvAr-_b{qQ;f4o7d0ThoZdr`mY1|(kX`}?+7o1654aJO|g+=d(cc*2$Y4$*=tuiDOEA`cPb#psYKBX1b3 zUcgzXymzCCUSgMbbRr?rR8s^>(zTztLsmPrHzqy%q^7-0l0_PJ+X>{a8hhy*>ad+6 F;9ve>BRc>9 literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json index d8db8d65..65b74d7e 100644 --- a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,98 +1 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/Contents.json b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/Contents.json index da4a164c..73c00596 100644 --- a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/Contents.json +++ b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json new file mode 100644 index 00000000..5b130017 --- /dev/null +++ b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "playstore.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png b/iOS Example Frame SPM/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..460881f92669088e15815b329ab814ac2462dc79 GIT binary patch literal 33636 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame SPM/iOS Example Frame/Base.lproj/LaunchScreen.storyboard b/iOS Example Frame SPM/iOS Example Frame/Base.lproj/LaunchScreen.storyboard index f83f6fd5..f3aeef58 100644 --- a/iOS Example Frame SPM/iOS Example Frame/Base.lproj/LaunchScreen.storyboard +++ b/iOS Example Frame SPM/iOS Example Frame/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,9 @@ - - + + + - + + @@ -11,15 +13,32 @@ - + - + + + + + + + + + + + + + + + - + + + + diff --git a/iOS Example Frame SPM/iOS Example Frame/Base.lproj/Main.storyboard b/iOS Example Frame SPM/iOS Example Frame/Base.lproj/Main.storyboard index a153749b..2a09e621 100644 --- a/iOS Example Frame SPM/iOS Example Frame/Base.lproj/Main.storyboard +++ b/iOS Example Frame SPM/iOS Example Frame/Base.lproj/Main.storyboard @@ -1,12 +1,9 @@ - - - - + + - - + @@ -19,25 +16,77 @@ - + + + + + + + + - + + - - + + + + + + + + + - - - - @@ -52,7 +101,7 @@ - + @@ -74,7 +123,7 @@ - + @@ -92,14 +141,14 @@ - + + - @@ -112,7 +161,7 @@ - + @@ -125,4 +174,10 @@ + + + + + + diff --git a/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift b/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift index 0514308e..5ac725ba 100644 --- a/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift +++ b/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift @@ -12,8 +12,15 @@ import Frames class MainViewController: UIViewController, CardViewControllerDelegate { @IBOutlet weak var goToPaymentPageButton: UIButton! + var isNewUI: Bool = false @IBAction func goToPaymentPage(_ sender: Any) { + cardViewController.isNewUI = false + navigationController?.pushViewController(cardViewController, animated: true) + } + + @IBAction func goToNewPaymentPage(_ sender: Any) { + cardViewController.isNewUI = true navigationController?.pushViewController(cardViewController, animated: true) } @@ -25,31 +32,23 @@ class MainViewController: UIViewController, CardViewControllerDelegate { lazy var cardViewController: CardViewController = { let checkoutAPIClient = CheckoutAPIClient(publicKey: "pk_test_6e40a700-d563-43cd-89d0-f9bb17d35e73", environment: .sandbox) - let b = CardViewController(checkoutApiClient: checkoutAPIClient, cardHolderNameState: .normal, billingDetailsState: .normal, defaultRegionCode: "GB") - b.billingDetailsAddress = CkoAddress(addressLine1: "Test line1", addressLine2: "Test line2", city: "London", state: "London", zip: "N12345", country: "GB") - b.billingDetailsPhone = CkoPhoneNumber(countryCode: "44", number: "77 1234 1234") - b.delegate = self - b.addressViewController.setFields(address: b.billingDetailsAddress!, phone: b.billingDetailsPhone!) - return b + let view = CardViewController(checkoutApiClient: checkoutAPIClient, cardHolderNameState: .normal, billingDetailsState: .normal, defaultRegionCode: "GB") + view.billingDetailsAddress = CkoAddress(addressLine1: "Test line1", addressLine2: "Test line2", city: "London", state: "London", zip: "N12345", country: "GB") + view.billingDetailsPhone = CkoPhoneNumber(countryCode: "44", number: "77 1234 1234") + view.delegate = self + view.addressViewController.setFields(address: view.billingDetailsAddress!, phone: view.billingDetailsPhone!) + view.delegate = self + view.rightBarButtonItem = UIBarButtonItem(title: "Pay", style: .done, target: nil, action: nil) + view.availableSchemes = [.visa, .mastercard, .maestro] + view.setDefault(regionCode: "GB") + view.addressViewController.setCountrySelected(country: "GB", regionCode: "GB") + return view }() @IBAction func onClickGoToPaymentPage(_ sender: Any) { navigationController?.pushViewController(cardViewController, animated: true) } - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - cardViewController.delegate = self - cardViewController.rightBarButtonItem = UIBarButtonItem(title: "Pay", style: .done, target: nil, action: nil) - cardViewController.availableSchemes = [.visa, .mastercard, .maestro] - cardViewController.setDefault(regionCode: "GB") - } - - override func viewDidAppear(_ animated: Bool) { - cardViewController.addressViewController.setCountrySelected(country: "GB", regionCode: "GB") - } - func onTapDone(controller: CardViewController, cardToken: CkoCardTokenResponse?, status: CheckoutTokenStatus) { UIApplication.shared.isNetworkActivityIndicatorVisible = false switch status { From 1d5aae94cddd494f04679b7de7ed0998138bef31 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 26 Apr 2022 21:32:01 +0100 Subject: [PATCH 02/55] Fix logging issue --- Source/UI/Controllers/CardViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index d171c1be..c85d3004 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -160,13 +160,13 @@ public class CardViewController: UIViewController, } @objc func onTapAddressView() { + checkoutApiClient?.logger.log(.billingFormPresented) guard isNewUI else { navigationController?.pushViewController(addressViewController, animated: true) return } let viewController = BillingFormFactory.getBillingFormViewController(delegate: self) navigationController?.present(viewController, animated: true) - checkoutApiClient?.logger.log(.billingFormPresented) loggedForCurrentCorrelationID = true } From 02641fb80ed6c202195227fa74eba84dfbb28167 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 14:53:21 +0100 Subject: [PATCH 03/55] Fix `DefaultFormStylePostcodedCell` typo --- Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift | 2 +- ...lePostcodedCell.swift => DefaultFormStylePostcodeCell.swift} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/{DefaultFormStylePostcodedCell.swift => DefaultFormStylePostcodeCell.swift} (90%) diff --git a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift index 9a219dc3..f1c947c4 100644 --- a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift +++ b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift @@ -8,7 +8,7 @@ struct BillingFormFactory { DefaultFormStyleAddressLine2Cell(), DefaultFormStyleCityCell(), DefaultFormStyleStateCell(), - DefaultFormStylePostcodedCell(), + DefaultFormStylePostcodeCell(), DefaultFormStyleCountryCell(), DefaultFormStylePhoneNumberCell() ] diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodedCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift similarity index 90% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodedCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift index bbf25b98..341efd0e 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodedCell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStylePostcodedCell : BillingFormTextFieldCellStyle { +struct DefaultFormStylePostcodeCell : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? From 8bb68d245d1652b7439e9780130b47f1529a8710 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 14:58:03 +0100 Subject: [PATCH 04/55] Fix 'hight' typo --- .../Header/Cancel/DefaultCancelButtonFormStyle.swift | 6 +++--- .../Header/Done/DefaultDoneFormButtonStyle.swift | 6 +++--- .../NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift | 2 +- .../View/TableViewCell/Header/BillingFormHeaderCell.swift | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift index b321fe08..5b140859 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift @@ -9,7 +9,7 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { var inActiveTintColor: UIColor var activeTintColor: UIColor var backgroundColor: UIColor - var hight: Double + var height: Double var width: Double init( isEnabled: Bool = true, @@ -20,7 +20,7 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { inActiveTintColor: UIColor = .doveGray, activeTintColor: UIColor = .brandeisBlue, backgroundColor: UIColor = .white, - hight: Double = 44, + height: Double = 44, width: Double = 53) { self.isEnabled = isEnabled self.text = text @@ -30,7 +30,7 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { self.inActiveTintColor = inActiveTintColor self.activeTintColor = activeTintColor self.backgroundColor = backgroundColor - self.hight = hight + self.height = height self.width = width } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift index c3c0c8c0..8019b168 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift @@ -9,7 +9,7 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { var inActiveTintColor: UIColor var activeTintColor: UIColor var backgroundColor: UIColor - var hight: Double + var height: Double var width: Double init( isEnabled: Bool = true, @@ -20,7 +20,7 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { inActiveTintColor: UIColor = .doveGray, activeTintColor: UIColor = .brandeisBlue, backgroundColor: UIColor = .white, - hight: Double = 44, + height: Double = 44, width: Double = 53) { self.isEnabled = isEnabled self.text = text @@ -30,7 +30,7 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { self.inActiveTintColor = inActiveTintColor self.activeTintColor = activeTintColor self.backgroundColor = backgroundColor - self.hight = hight + self.height = height self.width = width } } diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift index 82560292..12c4cdd3 100644 --- a/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift @@ -10,6 +10,6 @@ public protocol FormButtonStyle { var inActiveTintColor: UIColor { get } var activeTintColor: UIColor { get } var backgroundColor: UIColor { get } - var hight: Double { get } + var height: Double { get } var width: Double { get } } diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index 0d70ecbf..a114f6e8 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -90,7 +90,7 @@ extension BillingFormHeaderCell { equalTo: contentView.safeLeadingAnchor, constant: 20), cancel.heightAnchor.constraint( - equalToConstant: style.cancelButton.hight), + equalToConstant: style.cancelButton.height), cancel.widthAnchor.constraint( equalToConstant: style.cancelButton.width) ]) @@ -106,7 +106,7 @@ extension BillingFormHeaderCell { equalTo: contentView.safeTrailingAnchor, constant: -20), done.heightAnchor.constraint( - equalToConstant: style.doneButton.hight), + equalToConstant: style.doneButton.height), done.widthAnchor.constraint( equalToConstant: style.doneButton.width) ]) From 0201e01f2faf2cb55e53386062ea4db5ac441659 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 14:59:34 +0100 Subject: [PATCH 05/55] Fix typo in folder name --- .../Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift | 0 .../Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift | 0 .../BillingForm/Fields/City/DefaultFormStyleCityCell.swift | 0 .../BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift | 0 .../Fields/FullName}/DefaultFormStyleFullNameCell.swift | 0 .../Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift | 0 .../Fields/Postcode/DefaultFormStylePostcodeCell.swift | 0 .../BillingForm/Fields/State/DefaultFormStyleStateCell.swift | 0 .../BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift | 0 .../BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift | 0 .../Header/Main/DefaultBillingFormHeaderCellStyle.swift | 0 .../BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift | 0 .../BillingForm/Main/DefaultBillingFormStyle.swift | 0 .../Elements/Error/DefaultErrorInputLabelStyle.swift | 0 .../Elements/Hint/DefaultHintInputLabelStyle.swift | 0 .../Elements/TextField/DefaultTextField.swift | 0 .../Elements/Title/DefaultTitleLabelStyle.swift | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Fields/City/DefaultFormStyleCityCell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation/BillingForm/Fields/Fullname => Default Implementation/BillingForm/Fields/FullName}/DefaultFormStyleFullNameCell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Fields/State/DefaultFormStyleStateCell.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/BillingForm/Main/DefaultBillingFormStyle.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/Elements/Error/DefaultErrorInputLabelStyle.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/Elements/Hint/DefaultHintInputLabelStyle.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/Elements/TextField/DefaultTextField.swift (100%) rename Source/UI/NewUI/BillingForm/Style/{Default Implmentation => Default Implementation}/Elements/Title/DefaultTitleLabelStyle.swift (100%) diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Fullname/DefaultFormStyleFullNameCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultFormStyleFullNameCell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Fullname/DefaultFormStyleFullNameCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultFormStyleFullNameCell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Main/DefaultBillingFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Main/DefaultBillingFormStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/BillingForm/Main/DefaultBillingFormStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Main/DefaultBillingFormStyle.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Error/DefaultErrorInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Error/DefaultErrorInputLabelStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Hint/DefaultHintInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Hint/DefaultHintInputLabelStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/TextField/DefaultTextField.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/TextField/DefaultTextField.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Title/DefaultTitleLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Title/DefaultTitleLabelStyle.swift similarity index 100% rename from Source/UI/NewUI/BillingForm/Style/Default Implmentation/Elements/Title/DefaultTitleLabelStyle.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Title/DefaultTitleLabelStyle.swift From 0f918de693f1ab866b170ff70eee1ffd30c58ec2 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:06:29 +0100 Subject: [PATCH 06/55] remove explicite `Bool` --- Source/UI/Controllers/CardViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index c85d3004..bdca9192 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -43,7 +43,7 @@ public class CardViewController: UIViewController, var topConstraint: NSLayoutConstraint? private var loggedForCurrentCorrelationID = false - public var isNewUI: Bool = false + public var isNewUI = false // MARK: - Initialization /// Returns a newly initialized view controller with the cardholder's name and billing details From 4373e90fab9b818213a0de056e86dd2cad176b19 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:08:36 +0100 Subject: [PATCH 07/55] Fix 'BillForm' to be `BillingForm` --- ...ormTextField.swift => BillingFormTextField.swift} | 2 +- .../View/Field/BillingFormTextFieldView.swift | 2 +- .../ViewController/BillingFormViewController.swift | 8 ++++---- .../ViewModel/DefaultBillingFormViewModel.swift | 4 ++-- .../BillingFormViewControllerMockDelegate.swift | 12 ++++++------ .../View/BillingFormFullNameTextFieldCellTests.swift | 6 +++--- .../BillingFormViewControllerTests.swift | 8 ++++---- .../ViewModel/BillingFormViewModelTests.swift | 6 +++--- 8 files changed, 24 insertions(+), 24 deletions(-) rename Source/UI/NewUI/BillingForm/View/Field/{BillFormTextField.swift => BillingFormTextField.swift} (84%) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillFormTextField.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift similarity index 84% rename from Source/UI/NewUI/BillingForm/View/Field/BillFormTextField.swift rename to Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift index d00c5c36..99ed5cbc 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillFormTextField.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift @@ -1,6 +1,6 @@ import UIKit -final class BillFormTextField: UITextField { +final class BillingFormTextField: UITextField { var type: BillingFormCellType init(type: BillingFormCellType) { self.type = type diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index 30f38565..b12d0786 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -49,7 +49,7 @@ final class BillingFormTextFieldView: UIView { }() private(set) lazy var textField: UITextField = { - let view: UITextField = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type) : BillFormTextField(type: self.type) + let view: UITextField = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type) : BillingFormTextField(type: self.type) view.text = style.textfield.text view.font = style.textfield.font view.placeholder = style.textfield.placeHolder diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 928c56f5..9625866e 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -6,8 +6,8 @@ protocol BillingFormViewControllerDeleagte: AnyObject { func tableView(numberOfRowsInSection section: Int) -> Int func tableView(cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell func tableView(estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat - func validate(textField: BillFormTextField) - func textFieldIsChanged(textField: BillFormTextField, replacementString: String) + func validate(textField: BillingFormTextField) + func textFieldIsChanged(textField: BillingFormTextField, replacementString: String) } final class BillingFormViewController: UIViewController { @@ -125,12 +125,12 @@ extension BillingFormViewController: UITableViewDataSource { //FormCellDelegate extension BillingFormViewController: BillingFormTextFieldCellDelegate { func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) { - guard let textField = textField as? BillFormTextField else { return } + guard let textField = textField as? BillingFormTextField else { return } delegate?.textFieldIsChanged(textField: textField, replacementString: replacementString) } func textFieldDidEndEditing(textField: UITextField) { - guard let textField = textField as? BillFormTextField else { return } + guard let textField = textField as? BillingFormTextField else { return } delegate?.validate(textField: textField) } diff --git a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift index 0920070d..b2d515e5 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift @@ -63,7 +63,7 @@ final class DefaultBillingFormViewModel: BillingFormViewModel { } extension DefaultBillingFormViewModel: BillingFormViewControllerDeleagte { - func textFieldIsChanged(textField: BillFormTextField, replacementString: String) { + func textFieldIsChanged(textField: BillingFormTextField, replacementString: String) { if !replacementString.isEmpty { textValueOfCellType[textField.type] = replacementString } @@ -103,7 +103,7 @@ extension DefaultBillingFormViewModel: BillingFormViewControllerDeleagte { sender.dismiss(animated: true) } - func validate(textField: BillFormTextField) { + func validate(textField: BillingFormTextField) { let type = textField.type let text = textField.text textValueOfCellType[type] = text diff --git a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift index 7ff7e379..8eed5261 100644 --- a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift +++ b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift @@ -20,10 +20,10 @@ class BillingFormViewControllerMockDelegate: BillingFormViewControllerDeleagte { var estimatedHeightForRowLastCalledWithIndexPath: IndexPath? var validateCalledTimes = 0 - var validateLastCalledWithBillFormTextField: BillFormTextField? + var validateLastCalledWithBillingFormTextField: BillingFormTextField? var textFieldIsChangedCalledTimes = 0 - var textFieldIsChangedLastCalledWithBillFormTextField: BillFormTextField? + var textFieldIsChangedLastCalledWithBillingFormTextField: BillingFormTextField? var textFieldIsChangedLastCalledWithReplacementString: String? func doneButtonIsPressed(sender: UIViewController) { @@ -55,14 +55,14 @@ class BillingFormViewControllerMockDelegate: BillingFormViewControllerDeleagte { return 100 } - func validate(textField: BillFormTextField) { + func validate(textField: BillingFormTextField) { validateCalledTimes += 1 - validateLastCalledWithBillFormTextField = textField + validateLastCalledWithBillingFormTextField = textField } - func textFieldIsChanged(textField: BillFormTextField, replacementString: String) { + func textFieldIsChanged(textField: BillingFormTextField, replacementString: String) { textFieldIsChangedCalledTimes += 1 - textFieldIsChangedLastCalledWithBillFormTextField = textField + textFieldIsChangedLastCalledWithBillingFormTextField = textField textFieldIsChangedLastCalledWithReplacementString = replacementString } diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift index d2a0710d..10e9e030 100644 --- a/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift +++ b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift @@ -11,7 +11,7 @@ class BillingFormTextFieldCellTests: XCTestCase { func testCallDelegateMethodTextFieldShouldBeginEditing() { let delegate = BillingFormTextFieldCellMockDelegate() - let textField = BillFormTextField(type: .fullName) + let textField = BillingFormTextField(type: .fullName) view.delegate = delegate view.textFieldShouldBeginEditing(textField: textField) @@ -30,7 +30,7 @@ class BillingFormTextFieldCellTests: XCTestCase { func testCallDelegateMethodTextFieldDidEndEditing() { let delegate = BillingFormTextFieldCellMockDelegate() - let textField = BillFormTextField(type: .fullName) + let textField = BillingFormTextField(type: .fullName) view.delegate = delegate view.textFieldDidEndEditing(textField: textField) @@ -41,7 +41,7 @@ class BillingFormTextFieldCellTests: XCTestCase { func testCallDelegateMethodTextFieldDidChangeCharacters() { let delegate = BillingFormTextFieldCellMockDelegate() - let textField = BillFormTextField(type: .fullName) + let textField = BillingFormTextField(type: .fullName) let text = "test" view.delegate = delegate diff --git a/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift b/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift index a5df0b72..b16c0530 100644 --- a/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift +++ b/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift @@ -86,12 +86,12 @@ class BillingFormViewControllerTests: XCTestCase { billingFormViewController.viewDidLoad() billingFormViewController.delegate = delegate - let textfield = BillFormTextField(type: .fullName) + let textfield = BillingFormTextField(type: .fullName) billingFormViewController.textFieldDidEndEditing(textField: textfield) XCTAssertEqual(delegate.validateCalledTimes, 1) - XCTAssertEqual(delegate.validateLastCalledWithBillFormTextField, textfield) + XCTAssertEqual(delegate.validateLastCalledWithBillingFormTextField, textfield) } func testCallDelegateMethodTextFieldIsChanged() { @@ -99,12 +99,12 @@ class BillingFormViewControllerTests: XCTestCase { billingFormViewController.viewDidLoad() billingFormViewController.delegate = delegate - let textfield = BillFormTextField(type: .fullName) + let textfield = BillingFormTextField(type: .fullName) let text = "Test" billingFormViewController.textFieldDidChangeCharacters(textField: textfield, replacementString: text) XCTAssertEqual(delegate.textFieldIsChangedCalledTimes, 1) XCTAssertEqual(delegate.textFieldIsChangedLastCalledWithReplacementString, text) - XCTAssertEqual(delegate.textFieldIsChangedLastCalledWithBillFormTextField, textfield) + XCTAssertEqual(delegate.textFieldIsChangedLastCalledWithBillingFormTextField, textfield) } } diff --git a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift index bbb635d0..86f15aba 100644 --- a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift +++ b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift @@ -28,7 +28,7 @@ class BillingFormViewModelTests: XCTestCase { let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) let expectedType = BillingFormCellType.fullName let text = "" - let textField = BillFormTextField(type: expectedType) + let textField = BillingFormTextField(type: expectedType) textField.text = text viewModel.updateRow = { @@ -47,7 +47,7 @@ class BillingFormViewModelTests: XCTestCase { let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) let expectedType = BillingFormCellType.fullName let text = "fullName" - let textField = BillFormTextField(type: expectedType) + let textField = BillingFormTextField(type: expectedType) textField.text = text viewModel.updateRow = { @@ -106,7 +106,7 @@ class BillingFormViewModelTests: XCTestCase { viewModel.textValueOfCellType = textValueOfCellType viewModel.editDelegate = delegate - viewModel.textFieldIsChanged(textField: BillFormTextField(type: .fullName), replacementString: "text") + viewModel.textFieldIsChanged(textField: BillingFormTextField(type: .fullName), replacementString: "text") XCTAssertEqual(delegate.didFinishEditingBillingFormCalledTimes, 1) XCTAssertEqual(delegate.didFinishEditingBillingFormLastCalledWithSuccessfully, false) From e2efe8f6a803aa0d82cb3af160544afe9e2bfadc Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:11:18 +0100 Subject: [PATCH 08/55] Remove unused commented code --- .../ViewController/BillingFormViewController.swift | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 9625866e..372879ef 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -99,11 +99,6 @@ extension BillingFormViewController { registerKeyboardHandlers(notificationCenter: notificationCenter, keyboardWillShow: #selector(keyboardWillShow), keyboardWillHide: #selector(keyboardWillHide)) - -// let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:))) -// view.addGestureRecognizer(tapGesture) -// NotificationCenter.default.addObserver(self, selector: #selector(BillingFormViewController.keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) -// NotificationCenter.default.addObserver(self, selector: #selector(BillingFormViewController.keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) } } From 86fed89067f6e0a50dc25ad3d702792a671ef213 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:11:44 +0100 Subject: [PATCH 09/55] fix `deleagte` typo --- .../View/TableViewCell/Header/BillingFormHeaderCell.swift | 8 ++++---- .../ViewController/BillingFormViewController.swift | 6 +++--- .../ViewModel/DefaultBillingFormViewModel.swift | 2 +- Tests/Mocks/BillingFormViewControllerMockDelegate.swift | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index a114f6e8..2dbc6e3c 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -7,7 +7,7 @@ protocol BillingFormHeaderCellDelegate: AnyObject { final class BillingFormHeaderCell: UITableViewCell { private var style: BillingFormHeaderCellStyle - private weak var deleagte: BillingFormHeaderCellDelegate? + private weak var delegate: BillingFormHeaderCellDelegate? private lazy var cancel: UIButton = { let view = UIButton() @@ -50,7 +50,7 @@ final class BillingFormHeaderCell: UITableViewCell { init(style: BillingFormHeaderCellStyle , delegate: BillingFormHeaderCellDelegate?) { self.style = style super.init(style: .default, reuseIdentifier: nil) - self.deleagte = delegate + self.delegate = delegate setupViews() } @@ -59,11 +59,11 @@ final class BillingFormHeaderCell: UITableViewCell { } @objc private func doneAction(){ - deleagte?.doneButtonIsPressed() + delegate?.doneButtonIsPressed() } @objc private func cancelAction(){ - deleagte?.cancelButtonIsPressed() + delegate?.cancelButtonIsPressed() } private func shouldEnableDoneButton(flag: Bool) { diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 372879ef..2da6a993 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -1,6 +1,6 @@ import UIKit -protocol BillingFormViewControllerDeleagte: AnyObject { +protocol BillingFormViewControllerdelegate: AnyObject { func doneButtonIsPressed(sender: UIViewController) func cancelButtonIsPressed(sender: UIViewController) func tableView(numberOfRowsInSection section: Int) -> Int @@ -11,7 +11,7 @@ protocol BillingFormViewControllerDeleagte: AnyObject { } final class BillingFormViewController: UIViewController { - weak var delegate: BillingFormViewControllerDeleagte? + weak var delegate: BillingFormViewControllerdelegate? fileprivate var focusedTextField: UITextField? private var viewModel: BillingFormViewModel @@ -49,7 +49,7 @@ final class BillingFormViewController: UIViewController { init(viewModel: BillingFormViewModel) { self.viewModel = viewModel - self.delegate = viewModel as? BillingFormViewControllerDeleagte + self.delegate = viewModel as? BillingFormViewControllerdelegate super.init(nibName: nil, bundle: nil) self.setupViewModel() } diff --git a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift index b2d515e5..9575e687 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift @@ -62,7 +62,7 @@ final class DefaultBillingFormViewModel: BillingFormViewModel { } } -extension DefaultBillingFormViewModel: BillingFormViewControllerDeleagte { +extension DefaultBillingFormViewModel: BillingFormViewControllerdelegate { func textFieldIsChanged(textField: BillingFormTextField, replacementString: String) { if !replacementString.isEmpty { textValueOfCellType[textField.type] = replacementString diff --git a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift index 8eed5261..f9a3ca59 100644 --- a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift +++ b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift @@ -1,7 +1,7 @@ import UIKit @testable import Frames -class BillingFormViewControllerMockDelegate: BillingFormViewControllerDeleagte { +class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { var doneButtonIsPressedCalledTimes = 0 var doneButtonIsPressedLastCalledWithSender: UIViewController? From 77e19982d7630e9d140c0b3e2c60a6f9b81beff1 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:13:14 +0100 Subject: [PATCH 10/55] Renaming some variables `doneButton` and `cancelButton` --- .../TableViewCell/Header/BillingFormHeaderCell.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index 2dbc6e3c..d7535139 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -9,7 +9,7 @@ final class BillingFormHeaderCell: UITableViewCell { private var style: BillingFormHeaderCellStyle private weak var delegate: BillingFormHeaderCellDelegate? - private lazy var cancel: UIButton = { + private lazy var cancelButton: UIButton = { let view = UIButton() view.setTitle(style.cancelButton.text, for: .normal) view.titleLabel?.font = style.cancelButton.font @@ -81,17 +81,17 @@ extension BillingFormHeaderCell { } private func setupCancelButton() { - contentView.addSubview(cancel) + contentView.addSubview(cancelButton) NSLayoutConstraint.activate([ - cancel.topAnchor.constraint( + cancelButton.topAnchor.constraint( equalTo: safeTopAnchor, constant: 0), - cancel.leadingAnchor.constraint( + cancelButton.leadingAnchor.constraint( equalTo: contentView.safeLeadingAnchor, constant: 20), - cancel.heightAnchor.constraint( + cancelButton.heightAnchor.constraint( equalToConstant: style.cancelButton.height), - cancel.widthAnchor.constraint( + cancelButton.widthAnchor.constraint( equalToConstant: style.cancelButton.width) ]) } From 3551409a575da01ab27abe2bc47779680f3f53d3 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:44:35 +0100 Subject: [PATCH 11/55] Update UIColor+Extension --- Source/CheckoutColor.swift | 24 +++----------- Source/Extensions/UIColor+Extension.swift | 33 +++++++++++++++++++ .../Error/DefaultErrorInputLabelStyle.swift | 4 +-- .../Elements/TextField/DefaultTextField.swift | 2 +- 4 files changed, 41 insertions(+), 22 deletions(-) create mode 100644 Source/Extensions/UIColor+Extension.swift diff --git a/Source/CheckoutColor.swift b/Source/CheckoutColor.swift index 625fa5ed..a18419cf 100644 --- a/Source/CheckoutColor.swift +++ b/Source/CheckoutColor.swift @@ -1,23 +1,9 @@ import UIKit extension UIColor { -// Blue - //#0B5FF0 - public static var brandeisBlue = UIColor(red: 11/255, green: 95/255, blue: 240/255, alpha: 1) - -// Gray - //#636363 - public static var doveGray = UIColor(red: 99/255, green: 99/255, blue: 99/255, alpha: 1) - - //#141414 - public static var codGray = UIColor(red: 20/255, green: 20/255, blue: 20/255, alpha: 1) - - //#8A8A8A - public static var mediumGray = UIColor(red: 138/255, green: 138/255, blue: 138/255, alpha: 1) - -// Red - //#AD283E - public static var tallPoppy = UIColor(red: 173/255, green: 40/255, blue: 62/255, alpha: 1) - + public static let brandeisBlue = UIColor(hex: "#0B5FF0") + public static let doveGray = UIColor(hex: "#636363") + public static let codGray = UIColor(hex: "#141414") + public static let mediumGray = UIColor(hex: "#8A8A8A") + public static let tallPoppyRed = UIColor(hex: "#AD283E") } - diff --git a/Source/Extensions/UIColor+Extension.swift b/Source/Extensions/UIColor+Extension.swift new file mode 100644 index 00000000..2093cf34 --- /dev/null +++ b/Source/Extensions/UIColor+Extension.swift @@ -0,0 +1,33 @@ +// +// File.swift +// +// +// Created by Ehab Alsharkawy on 27/04/2022. +// + +import Foundation +import UIKit + +extension UIColor { + convenience init(hex: String, alpha: CGFloat = 1.0) { + var cString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() + + if cString.hasPrefix("#") { cString.removeFirst() } + + guard cString.count == 6 else { + self.init(hex: "ff0000") // gray color + return + } + + var rgbValue: UInt64 = 0 + Scanner(string: cString).scanHexInt64(&rgbValue) + + self.init ( + red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgbValue & 0x0000FF) / 255.0, + alpha: CGFloat(1.0) + ) + } + +} diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift index cf605bcb..32479963 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift @@ -12,10 +12,10 @@ struct DefaultErrorInputLabelStyle: ErrorInputLabelStyle { init(isHidden: Bool = true, backgroundColor: UIColor = .white, - tintColor: UIColor = .tallPoppy, + tintColor: UIColor = .tallPoppyRed, text: String = "", font: UIFont = UIFont.systemFont(ofSize: 15), - textColor: UIColor = .tallPoppy, + textColor: UIColor = .tallPoppyRed, isWarningSympoleOnLeft: Bool = true, height: Double = 18.0) { self.isHidden = isHidden diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift index 2e2b420f..4fde3f5e 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift @@ -23,7 +23,7 @@ struct DefaultTextField: TextFieldStyle { textColor: UIColor = .codGray, normalBorderColor: UIColor = .mediumGray, focusBorderColor: UIColor = .brandeisBlue, - errorBorderColor: UIColor = .tallPoppy, + errorBorderColor: UIColor = .tallPoppyRed, backgroundColor: UIColor = .white, tintColor: UIColor = .codGray, width: Double = 335.0, From 311a63ab3641783966b2d74b0350bcbf38419473 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:50:25 +0100 Subject: [PATCH 12/55] remove unused code --- iOS Example Frame SPM/iOS Example Frame/MainViewController.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift b/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift index 5ac725ba..524c8c80 100644 --- a/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift +++ b/iOS Example Frame SPM/iOS Example Frame/MainViewController.swift @@ -12,7 +12,6 @@ import Frames class MainViewController: UIViewController, CardViewControllerDelegate { @IBOutlet weak var goToPaymentPageButton: UIButton! - var isNewUI: Bool = false @IBAction func goToPaymentPage(_ sender: Any) { cardViewController.isNewUI = false From 7a6107160196d4b587a49b4a1df333fdddecd81e Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 15:57:48 +0100 Subject: [PATCH 13/55] Renaming correction --- .../BillingForm/Factory/BillingFormFactory.swift | 16 ++++++++-------- ...efaultBillingFormAddressLine1CellStyle.swift} | 3 +-- ...efaultBillingFormAddressLine2CellStyle.swift} | 2 +- ...ift => DefaultBillingFormCityCellStyle.swift} | 2 +- ... => DefaultBillingFormCountryCellStyle.swift} | 2 +- ...=> DefaultBillingFormFullNameCellStyle.swift} | 2 +- ...DefaultBillingFormPhoneNumberCellStyle.swift} | 2 +- ...=> DefaultBillingFormPostCodeCellStyle.swift} | 2 +- ...ft => DefaultBillingFormStateCellStyle.swift} | 2 +- .../ViewModel/BillingFormCellType.swift | 2 +- Source/Validator/PostCodeValidator.swift | 2 +- .../Validator/PostCodeValidatorTests.swift | 2 +- .../ViewModel/BillingFormCellTypeTests.swift | 2 +- 13 files changed, 20 insertions(+), 21 deletions(-) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/{DefaultFormStyleAddressLine1Cell.swift => DefaultBillingFormAddressLine1CellStyle.swift} (88%) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/{DefaultFormStyleAddressLine2Cell.swift => DefaultBillingFormAddressLine2CellStyle.swift} (89%) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/{DefaultFormStyleCityCell.swift => DefaultBillingFormCityCellStyle.swift} (90%) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/{DefaultFormStyleCountryCell.swift => DefaultBillingFormCountryCellStyle.swift} (89%) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/{DefaultFormStyleFullNameCell.swift => DefaultBillingFormFullNameCellStyle.swift} (89%) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/{DefaultFormStylePhoneNumberCell.swift => DefaultBillingFormPhoneNumberCellStyle.swift} (91%) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/{DefaultFormStylePostcodeCell.swift => DefaultBillingFormPostCodeCellStyle.swift} (89%) rename Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/{DefaultFormStyleStateCell.swift => DefaultBillingFormStateCellStyle.swift} (90%) diff --git a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift index f1c947c4..0a1038c9 100644 --- a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift +++ b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift @@ -3,14 +3,14 @@ import UIKit struct BillingFormFactory { // in order static let styles: [BillingFormTextFieldCellStyle] = [ - DefaultFormStyleFullNameCell(), - DefaultFormStyleAddressLine1Cell(), - DefaultFormStyleAddressLine2Cell(), - DefaultFormStyleCityCell(), - DefaultFormStyleStateCell(), - DefaultFormStylePostcodeCell(), - DefaultFormStyleCountryCell(), - DefaultFormStylePhoneNumberCell() + DefaultBillingFormFullNameCellStyle(), + DefaultBillingFormAddressLine1CellStyle(), + DefaultBillingFormAddressLine2CellStyle(), + DefaultBillingFormCityCellStyle(), + DefaultBillingFormStateCellStyle(), + DefaultBillingFormPostcodeCellStyle(), + DefaultBillingFormCountryCellStyle(), + DefaultBillingFormPhoneNumberCellStyle() ] static func getBillingFormViewController(delegate: BillingFormViewModelDelegate) -> UIViewController { diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift similarity index 88% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift index 54c93ab3..75840caf 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultFormStyleAddressLine1Cell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift @@ -1,7 +1,6 @@ import UIKit -//Address line 1 -struct DefaultFormStyleAddressLine1Cell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormAddressLine1CellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift similarity index 89% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift index 3a2b61ba..62bc3046 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultFormStyleAddressLine2Cell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStyleAddressLine2Cell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormAddressLine2CellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift similarity index 90% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift index ef38ba4f..564f819a 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultFormStyleCityCell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStyleCityCell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormCityCellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift similarity index 89% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift index 6b81af4a..b066c080 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultFormStyleCountryCell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStyleCountryCell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormCountryCellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultFormStyleFullNameCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift similarity index 89% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultFormStyleFullNameCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift index 95b2e44a..41670b0d 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultFormStyleFullNameCell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStyleFullNameCell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormFullNameCellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift similarity index 91% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift index 0a579f7a..2f6d9120 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultFormStylePhoneNumberCell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStylePhoneNumberCell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormPhoneNumberCellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift similarity index 89% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift index 341efd0e..240a7261 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultFormStylePostcodeCell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStylePostcodeCell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormPostcodeCellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift similarity index 90% rename from Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift rename to Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift index 08f26287..b0e4c02c 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultFormStyleStateCell.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift @@ -1,6 +1,6 @@ import UIKit -struct DefaultFormStyleStateCell : BillingFormTextFieldCellStyle { +struct DefaultBillingFormStateCellStyle : BillingFormTextFieldCellStyle { var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? diff --git a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift index 5e7f4062..36b0e034 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift @@ -17,7 +17,7 @@ import Foundation case .addressLine2: return AddressLine2Validator() case .city: return CityValidator() case .state: return StateValidator() - case .postcode: return PostCodeValidator() + case .postcode: return PostcodeValidator() case .country: return CountryValidator() case .phoneNumber: return PhoneNumberValidator() } diff --git a/Source/Validator/PostCodeValidator.swift b/Source/Validator/PostCodeValidator.swift index 0073c932..73492dbc 100644 --- a/Source/Validator/PostCodeValidator.swift +++ b/Source/Validator/PostCodeValidator.swift @@ -1,6 +1,6 @@ import Foundation -class PostCodeValidator: Validator { +class PostcodeValidator: Validator { func validate(text: String?) -> Bool { return isEmpty(text: text) } diff --git a/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift index c627ed10..c4f39d7b 100644 --- a/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift @@ -1,7 +1,7 @@ import XCTest @testable import Frames -class PostCodeValidatorTests: XCTestCase { +class PostcodeValidatorTests: XCTestCase { func testValidationWhenTextIsEmptyThenShouldBeTrue() { let expectedType = BillingFormCellType.postcode diff --git a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift index b6e3effe..2644903c 100644 --- a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift +++ b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormCellTypeTests.swift @@ -30,7 +30,7 @@ class BillingFormCellTypeTests: XCTestCase { } func testPostcodeValidatorType(){ - XCTAssertTrue(BillingFormCellType.postcode.validator is PostCodeValidator) + XCTAssertTrue(BillingFormCellType.postcode.validator is PostcodeValidator) } func testPhoneNumberValidatorType(){ From 88bc829d54793a26d66cbce23f500f872c8c1cf2 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 23:39:43 +0100 Subject: [PATCH 14/55] Following the same code style pattern, remove extra `self` --- .../NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index b12d0786..424ac65f 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -151,7 +151,7 @@ extension BillingFormTextFieldView: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { textFieldContainer.layer.borderColor = style.textfield.focusBorderColor.cgColor - self.delegate?.textFieldShouldBeginEditing(textField: textField) + delegate?.textFieldShouldBeginEditing(textField: textField) } func textFieldDidEndEditing(_ textField: UITextField) { From d0f46cf2beee5f33e29f22e6a26e50a411f50870 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 23:41:03 +0100 Subject: [PATCH 15/55] Simplifying the code --- Source/Validator/AddressLine1Validator.swift | 2 +- Source/Validator/AddressLine2Validator.swift | 2 +- Source/Validator/CityValidator.swift | 2 +- Source/Validator/CountryValidator.swift | 2 +- Source/Validator/FullNameValidator.swift | 2 +- Source/Validator/PhoneNumberValidator.swift | 2 +- Source/Validator/PostCodeValidator.swift | 2 +- Source/Validator/StateValidator.swift | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Validator/AddressLine1Validator.swift b/Source/Validator/AddressLine1Validator.swift index 237d4d78..c18361d4 100644 --- a/Source/Validator/AddressLine1Validator.swift +++ b/Source/Validator/AddressLine1Validator.swift @@ -6,7 +6,7 @@ class AddressLine1Validator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } diff --git a/Source/Validator/AddressLine2Validator.swift b/Source/Validator/AddressLine2Validator.swift index 8a1c271c..7a3f03db 100644 --- a/Source/Validator/AddressLine2Validator.swift +++ b/Source/Validator/AddressLine2Validator.swift @@ -6,7 +6,7 @@ class AddressLine2Validator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } diff --git a/Source/Validator/CityValidator.swift b/Source/Validator/CityValidator.swift index 35fdc35c..2f90c801 100644 --- a/Source/Validator/CityValidator.swift +++ b/Source/Validator/CityValidator.swift @@ -6,7 +6,7 @@ class CityValidator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } diff --git a/Source/Validator/CountryValidator.swift b/Source/Validator/CountryValidator.swift index 45094ed2..b664fb74 100644 --- a/Source/Validator/CountryValidator.swift +++ b/Source/Validator/CountryValidator.swift @@ -6,7 +6,7 @@ class CountryValidator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } diff --git a/Source/Validator/FullNameValidator.swift b/Source/Validator/FullNameValidator.swift index 86884bbf..cbe4da8d 100644 --- a/Source/Validator/FullNameValidator.swift +++ b/Source/Validator/FullNameValidator.swift @@ -6,7 +6,7 @@ class FullNameValidator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } diff --git a/Source/Validator/PhoneNumberValidator.swift b/Source/Validator/PhoneNumberValidator.swift index fb2439c3..1bb71698 100644 --- a/Source/Validator/PhoneNumberValidator.swift +++ b/Source/Validator/PhoneNumberValidator.swift @@ -6,7 +6,7 @@ class PhoneNumberValidator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } diff --git a/Source/Validator/PostCodeValidator.swift b/Source/Validator/PostCodeValidator.swift index 73492dbc..aaa4f81a 100644 --- a/Source/Validator/PostCodeValidator.swift +++ b/Source/Validator/PostCodeValidator.swift @@ -6,7 +6,7 @@ class PostcodeValidator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } diff --git a/Source/Validator/StateValidator.swift b/Source/Validator/StateValidator.swift index da7f5213..9adfb624 100644 --- a/Source/Validator/StateValidator.swift +++ b/Source/Validator/StateValidator.swift @@ -6,7 +6,7 @@ class StateValidator: Validator { } private func isEmpty(text: String?) -> Bool { - guard let text = text, !text.isEmpty else { return true } + guard text?.isEmpty != false else { return true } return false } From f94e42a1a0cc3de494d920bae5ce0d7d7848bc37 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 23:41:30 +0100 Subject: [PATCH 16/55] Remove unused `import UIKit` --- Tests/Mocks/AddressViewControllerMockDelegate.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Mocks/AddressViewControllerMockDelegate.swift b/Tests/Mocks/AddressViewControllerMockDelegate.swift index af7fd0fc..169e327b 100644 --- a/Tests/Mocks/AddressViewControllerMockDelegate.swift +++ b/Tests/Mocks/AddressViewControllerMockDelegate.swift @@ -1,4 +1,3 @@ -import UIKit @testable import Frames class AddressViewControllerMockDelegate: AddressViewControllerDelegate { From 5b742d97a56e681500fd35ad15be32576c2c3de8 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 23:42:45 +0100 Subject: [PATCH 17/55] Use `XCTAssertFalse` or `XCTAssertTrue` instead of `XCTAssertEqual` --- .../BillingForm/Validator/AddressLine1ValidatorTests.swift | 4 ++-- .../BillingForm/Validator/AddressLine2ValidatorTests.swift | 4 ++-- .../UI/New UI/BillingForm/Validator/CityValidatorTests.swift | 4 ++-- .../New UI/BillingForm/Validator/CountryValidatorTests.swift | 4 ++-- .../New UI/BillingForm/Validator/FullNameValidatorTests.swift | 4 ++-- .../BillingForm/Validator/PhoneNumberValidatorTests.swift | 4 ++-- .../New UI/BillingForm/Validator/PostCodeValidatorTests.swift | 4 ++-- .../UI/New UI/BillingForm/Validator/StateValidatorTests.swift | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift index b59e62c6..bb38be17 100644 --- a/Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/AddressLine1ValidatorTests.swift @@ -7,13 +7,13 @@ class AddressLine1ValidatorTests: XCTestCase { let expectedType = BillingFormCellType.addressLine1 let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.addressLine1 let text = "addressLine1" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } diff --git a/Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift index 5f408a89..4cc8aa24 100644 --- a/Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/AddressLine2ValidatorTests.swift @@ -7,13 +7,13 @@ class AddressLine2ValidatorTests: XCTestCase { let expectedType = BillingFormCellType.addressLine2 let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.addressLine2 let text = "addressLine2" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } diff --git a/Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift index 9be38cb9..7e74398c 100644 --- a/Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/CityValidatorTests.swift @@ -7,13 +7,13 @@ class CityValidatorTests: XCTestCase { let expectedType = BillingFormCellType.city let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.city let text = "City" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } diff --git a/Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift index 5f0fa413..1b5e1085 100644 --- a/Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/CountryValidatorTests.swift @@ -7,13 +7,13 @@ class CountryValidatorTests: XCTestCase { let expectedType = BillingFormCellType.country let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.country let text = "Country" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } diff --git a/Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift index 1cb0340c..fedf918e 100644 --- a/Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/FullNameValidatorTests.swift @@ -7,13 +7,13 @@ class FullNameValidatorTests: XCTestCase { let expectedType = BillingFormCellType.fullName let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.fullName let text = "fullName" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } diff --git a/Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift index 83c3f575..0a5b4990 100644 --- a/Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/PhoneNumberValidatorTests.swift @@ -7,13 +7,13 @@ class PhoneNumberValidatorTests: XCTestCase { let expectedType = BillingFormCellType.phoneNumber let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.phoneNumber let text = "phoneNumber" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } diff --git a/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift index c4f39d7b..ab4424ce 100644 --- a/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/PostCodeValidatorTests.swift @@ -7,13 +7,13 @@ class PostcodeValidatorTests: XCTestCase { let expectedType = BillingFormCellType.postcode let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.postcode let text = "postcode" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } diff --git a/Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift b/Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift index 9bb8cd37..a0b77eb4 100644 --- a/Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift +++ b/Tests/UI/New UI/BillingForm/Validator/StateValidatorTests.swift @@ -7,13 +7,13 @@ class StateValidatorTests: XCTestCase { let expectedType = BillingFormCellType.state let text = "" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, true) + XCTAssertTrue(isValid) } func testValidationWhenTextIsNonEmptyThenShouldBeFalse() { let expectedType = BillingFormCellType.state let text = "postcode" let isValid = expectedType.validator.validate(text: text) - XCTAssertEqual(isValid, false) + XCTAssertFalse(isValid) } } From 9e5b7a281aa73769c7e45d6123088dc99c4ffe10 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 27 Apr 2022 23:42:54 +0100 Subject: [PATCH 18/55] Clean code --- .../View/BillingFormFullNameTextFieldCellTests.swift | 2 +- .../New UI/BillingForm/View/BillingFormTextFieldViewTests.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift index 10e9e030..b5d7710f 100644 --- a/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift +++ b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift @@ -6,7 +6,7 @@ class BillingFormTextFieldCellTests: XCTestCase { override func setUp() { super.setUp() - view = BillingFormTextFieldCell(type: .fullName, style: DefaultFormStyleFullNameCell(), delegate: nil) + view = BillingFormTextFieldCell(type: .fullName, style: DefaultBillingFormFullNameCellStyle(), delegate: nil) } func testCallDelegateMethodTextFieldShouldBeginEditing() { diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift index b8120be5..6d05a316 100644 --- a/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift +++ b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift @@ -3,7 +3,7 @@ import XCTest class BillingFormTextFieldViewTests: XCTestCase { var view: BillingFormTextFieldView! - let style = DefaultFormStyleFullNameCell() + let style = DefaultBillingFormFullNameCellStyle() override func setUp() { super.setUp() From ca3e7a96a66a9e77ba57370d8cd319366487f5a7 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Thu, 28 Apr 2022 15:17:51 +0100 Subject: [PATCH 19/55] Support localised strings --- Source/Extensions/StringExtensions.swift | 4 ++-- .../DefaultBillingFormAddressLine1CellStyle.swift | 5 +++-- .../DefaultBillingFormAddressLine2CellStyle.swift | 4 ++-- .../Fields/City/DefaultBillingFormCityCellStyle.swift | 4 ++-- .../Country/DefaultBillingFormCountryCellStyle.swift | 4 ++-- .../FullName/DefaultBillingFormFullNameCellStyle.swift | 4 ++-- .../DefaultBillingFormPhoneNumberCellStyle.swift | 7 +++---- .../Postcode/DefaultBillingFormPostCodeCellStyle.swift | 4 ++-- .../Fields/State/DefaultBillingFormStateCellStyle.swift | 4 ++-- .../Header/Cancel/DefaultCancelButtonFormStyle.swift | 2 +- .../Header/Done/DefaultDoneFormButtonStyle.swift | 2 +- .../Header/Title/DefaultHeaderLabelFormStyle.swift | 2 +- .../View/Field/BillingFormPhoneNumberText.swift | 1 - .../ViewController/BillingFormViewController.swift | 1 - 14 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Source/Extensions/StringExtensions.swift b/Source/Extensions/StringExtensions.swift index b102999d..0a7276c8 100644 --- a/Source/Extensions/StringExtensions.swift +++ b/Source/Extensions/StringExtensions.swift @@ -3,7 +3,7 @@ import UIKit extension String { - private func getBundle(forClass: AnyClass) -> Foundation.Bundle { + private func getBundle(forClass: Any.Type) -> Foundation.Bundle { #if SWIFT_PACKAGE let baseBundle = Bundle.module #else @@ -13,7 +13,7 @@ extension String { return path == nil ? baseBundle : Foundation.Bundle(path: path!)! } - func localized(forClass: AnyClass, comment: String = "") -> String { + func localized(forClass: Any.Type, comment: String = "") -> String { let bundle = getBundle(forClass: forClass) return NSLocalizedString(self, bundle: bundle, comment: "") } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift index 75840caf..081cc6cf 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift @@ -1,6 +1,7 @@ import UIKit struct DefaultBillingFormAddressLine1CellStyle : BillingFormTextFieldCellStyle { + var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? @@ -8,10 +9,10 @@ struct DefaultBillingFormAddressLine1CellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "Address line 1"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine1".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Address line 1")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormAddressLine1".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift index 62bc3046..69b3838b 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift @@ -8,10 +8,10 @@ struct DefaultBillingFormAddressLine2CellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "Address line 2"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine2".localized(forClass: DefaultBillingFormAddressLine2CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Address line 2")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormAddressLine2".localized(forClass: DefaultBillingFormAddressLine2CellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift index 564f819a..77a2111e 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift @@ -8,10 +8,10 @@ struct DefaultBillingFormCityCellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "City"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "city".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing City")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCity".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift index b066c080..e267c9b2 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift @@ -8,10 +8,10 @@ struct DefaultBillingFormCountryCellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "Country"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "country".localized(forClass: DefaultBillingFormCountryCellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Country")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCountry".localized(forClass: DefaultBillingFormCountryCellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift index 41670b0d..89a9425e 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift @@ -8,10 +8,10 @@ struct DefaultBillingFormFullNameCellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "Full name"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "name".localized(forClass: DefaultBillingFormFullNameCellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Full name")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCityFullName".localized(forClass: DefaultBillingFormFullNameCellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift index 2f6d9120..35a6d301 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift @@ -8,11 +8,10 @@ struct DefaultBillingFormPhoneNumberCellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "Phone number"), - hint: InputLabelStyle? = DefaultHintInputLabelStyle(isHidden: false, - text: "We will only use this to confirm identity if neccessary"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "phone".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self)), + hint: InputLabelStyle? = DefaultHintInputLabelStyle(isHidden: false,text: "billingFormPhoneNumberHint".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self)), textfield: TextFieldStyle = DefaultTextField(isSupprtingNumbericKeyboard: true), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Phone number")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCity".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift index 240a7261..c49850ec 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift @@ -8,10 +8,10 @@ struct DefaultBillingFormPostcodeCellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "Postcode/Zip"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "postcode".localized(forClass: DefaultBillingFormPostcodeCellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing Postcode/Zip")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormPostcode".localized(forClass: DefaultBillingFormPostcodeCellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift index b0e4c02c..5cadd8c5 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift @@ -8,10 +8,10 @@ struct DefaultBillingFormStateCellStyle : BillingFormTextFieldCellStyle { var error: ErrorInputLabelStyle init(backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "State"), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "countryRegion".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missing State")) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormState".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift index 5b140859..c3d315f0 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift @@ -13,7 +13,7 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { var width: Double init( isEnabled: Bool = true, - text: String = "Cancel", + text: String = "cancel".localized(forClass: DefaultCancelButtonFormStyle.self), font: UIFont = UIFont.systemFont(ofSize: 17), activeTitleColor: UIColor = .brandeisBlue, inActiveTitleColor: UIColor = .doveGray, diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift index 8019b168..85bcac0d 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift @@ -13,7 +13,7 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { var width: Double init( isEnabled: Bool = true, - text: String = "Done", + text: String = "done".localized(forClass: DefaultDoneFormButtonStyle.self), font: UIFont = UIFont.systemFont(ofSize: 17), activeTitleColor: UIColor = .brandeisBlue, inActiveTitleColor: UIColor = .doveGray, diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift index 629846be..b1e9e1b8 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift @@ -2,7 +2,7 @@ import UIKit struct DefaultHeaderLabelFormStyle: InputLabelStyle { var isHidden: Bool { false } - var text: String { "Billing address" } + var text: String { "billingAddressTitle".localized(forClass: DefaultHeaderLabelFormStyle.self) } var font: UIFont { UIFont.systemFont(ofSize: 24) } var textColor: UIColor { .codGray } } diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index bae99c90..5d38d2d2 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -40,7 +40,6 @@ final class BillingFormPhoneNumberText: UITextField { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") - setup() } private func setup() { diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 2da6a993..2d8d4062 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -95,7 +95,6 @@ extension BillingFormViewController { } private func setUpKeyboard() { - title = "addressViewControllerTitle".localized(forClass: AddressViewController.self) registerKeyboardHandlers(notificationCenter: notificationCenter, keyboardWillShow: #selector(keyboardWillShow), keyboardWillHide: #selector(keyboardWillHide)) From 42a7f4ebfd3e6be2682d6703337540e24cf9e256 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Thu, 28 Apr 2022 22:57:51 +0100 Subject: [PATCH 20/55] Clean validators code --- Source/Validator/AddressLine1Validator.swift | 5 ++--- Source/Validator/AddressLine2Validator.swift | 5 ++--- Source/Validator/CityValidator.swift | 5 ++--- Source/Validator/CountryValidator.swift | 5 ++--- Source/Validator/FullNameValidator.swift | 5 ++--- Source/Validator/PhoneNumberValidator.swift | 5 ++--- Source/Validator/PostCodeValidator.swift | 5 ++--- Source/Validator/StateValidator.swift | 5 ++--- 8 files changed, 16 insertions(+), 24 deletions(-) diff --git a/Source/Validator/AddressLine1Validator.swift b/Source/Validator/AddressLine1Validator.swift index c18361d4..e8a71395 100644 --- a/Source/Validator/AddressLine1Validator.swift +++ b/Source/Validator/AddressLine1Validator.swift @@ -2,12 +2,11 @@ import Foundation class AddressLine1Validator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } diff --git a/Source/Validator/AddressLine2Validator.swift b/Source/Validator/AddressLine2Validator.swift index 7a3f03db..4c033ddc 100644 --- a/Source/Validator/AddressLine2Validator.swift +++ b/Source/Validator/AddressLine2Validator.swift @@ -2,12 +2,11 @@ import Foundation class AddressLine2Validator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } diff --git a/Source/Validator/CityValidator.swift b/Source/Validator/CityValidator.swift index 2f90c801..57785ebd 100644 --- a/Source/Validator/CityValidator.swift +++ b/Source/Validator/CityValidator.swift @@ -2,12 +2,11 @@ import Foundation class CityValidator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } diff --git a/Source/Validator/CountryValidator.swift b/Source/Validator/CountryValidator.swift index b664fb74..aaf06ad9 100644 --- a/Source/Validator/CountryValidator.swift +++ b/Source/Validator/CountryValidator.swift @@ -2,12 +2,11 @@ import Foundation class CountryValidator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } diff --git a/Source/Validator/FullNameValidator.swift b/Source/Validator/FullNameValidator.swift index cbe4da8d..55efdb51 100644 --- a/Source/Validator/FullNameValidator.swift +++ b/Source/Validator/FullNameValidator.swift @@ -2,12 +2,11 @@ import Foundation class FullNameValidator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } diff --git a/Source/Validator/PhoneNumberValidator.swift b/Source/Validator/PhoneNumberValidator.swift index 1bb71698..a0f2f1f0 100644 --- a/Source/Validator/PhoneNumberValidator.swift +++ b/Source/Validator/PhoneNumberValidator.swift @@ -2,12 +2,11 @@ import Foundation class PhoneNumberValidator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } diff --git a/Source/Validator/PostCodeValidator.swift b/Source/Validator/PostCodeValidator.swift index aaa4f81a..9d4c24b7 100644 --- a/Source/Validator/PostCodeValidator.swift +++ b/Source/Validator/PostCodeValidator.swift @@ -2,12 +2,11 @@ import Foundation class PostcodeValidator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } diff --git a/Source/Validator/StateValidator.swift b/Source/Validator/StateValidator.swift index 9adfb624..5dcb03a5 100644 --- a/Source/Validator/StateValidator.swift +++ b/Source/Validator/StateValidator.swift @@ -2,12 +2,11 @@ import Foundation class StateValidator: Validator { func validate(text: String?) -> Bool { - return isEmpty(text: text) + isEmpty(text: text) } private func isEmpty(text: String?) -> Bool { - guard text?.isEmpty != false else { return true } - return false + text?.isEmpty ?? false } } From a7e0c319d04ac059f30d456eb9d654500dd00ef1 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Thu, 28 Apr 2022 22:58:39 +0100 Subject: [PATCH 21/55] Fix phone number clears after scrolling off of view (unable to click done as result) --- .../View/Field/BillingFormPhoneNumberText.swift | 14 ++++++-------- .../View/Field/BillingFormTextField.swift | 2 +- .../View/Field/BillingFormTextFieldView.swift | 2 +- .../ViewModel/DefaultBillingFormViewModel.swift | 13 ++++++++----- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index 5d38d2d2..b7d31d3f 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -1,8 +1,7 @@ import UIKit import PhoneNumberKit -final class BillingFormPhoneNumberText: UITextField { - var type: BillingFormCellType +final class BillingFormPhoneNumberText: BillingFormTextField { /// Phone Number Kit let phoneNumberKit = PhoneNumberKit() var partialFormatter: PartialFormatter { @@ -10,13 +9,13 @@ final class BillingFormPhoneNumberText: UITextField { } /// National Number (e.g. ) - public var nationalNumber: String { + var nationalNumber: String { let rawNumber = self.text ?? "" return partialFormatter.nationalNumber(from: rawNumber) } /// True if the phone number is valid, false otherwise - public var isValidNumber: Bool { + var isValidNumber: Bool { let rawNumber = self.text ?? "" do { phoneNumber = try phoneNumberKit.parse(rawNumber.replacingOccurrences(of: " ", with: "")) @@ -27,14 +26,13 @@ final class BillingFormPhoneNumberText: UITextField { } /// Phone Number - public var phoneNumber: PhoneNumber? + var phoneNumber: PhoneNumber? private var previousTextCount = 0 private var previousFormat = "" - init(type: BillingFormCellType) { - self.type = type - super.init(frame: .zero) + override init(type: BillingFormCellType) { + super.init(type: type) setup() } diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift index 99ed5cbc..bf33e307 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift @@ -1,6 +1,6 @@ import UIKit -final class BillingFormTextField: UITextField { +class BillingFormTextField: UITextField { var type: BillingFormCellType init(type: BillingFormCellType) { self.type = type diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index 424ac65f..818552f8 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -49,7 +49,7 @@ final class BillingFormTextFieldView: UIView { }() private(set) lazy var textField: UITextField = { - let view: UITextField = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type) : BillingFormTextField(type: self.type) + let view = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type) : BillingFormTextField(type: self.type) view.text = style.textfield.text view.font = style.textfield.font view.placeholder = style.textfield.placeHolder diff --git a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift index 9575e687..43214cde 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift @@ -9,15 +9,18 @@ final class DefaultBillingFormViewModel: BillingFormViewModel { } } - lazy var errorFlagOfCellType = [BillingFormCellType: Bool]() - lazy var textValueOfCellType = [BillingFormCellType: String]() + var errorFlagOfCellType = [BillingFormCellType: Bool]() + var textValueOfCellType = [BillingFormCellType: String]() private var initialCountry: String private var initialRegionCode: String? var editDelegate: BillingFormViewModelEditingDelegate? var delegate: BillingFormViewModelDelegate? - init(style: BillingFormStyle, initialCountry: String = "", initialRegionCode: String? = nil, delegate: BillingFormViewModelDelegate? = nil) { + init(style: BillingFormStyle, + initialCountry: String = "", + initialRegionCode: String? = nil, + delegate: BillingFormViewModelDelegate? = nil) { self.style = style self.initialCountry = initialCountry self.initialRegionCode = initialRegionCode @@ -86,8 +89,8 @@ extension DefaultBillingFormViewModel: BillingFormViewControllerdelegate { } func doneButtonIsPressed(sender: UIViewController) { - let countryCode = "44" //"\(addressView.phoneInputView.phoneNumber?.countryCode ?? 44)" - let phone = CkoPhoneNumber(countryCode: countryCode, +// let countryCode = "\(addressView.phoneInputView.phoneNumber?.countryCode ?? 44)" + let phone = CkoPhoneNumber(countryCode: "44", number: textValueOfCellType[.phoneNumber]) let address = CkoAddress(addressLine1: textValueOfCellType[.addressLine1], addressLine2: textValueOfCellType[.addressLine2], From d56979d81c4f299d432f5d269c9e4711b9a53e99 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Fri, 29 Apr 2022 03:01:44 +0100 Subject: [PATCH 22/55] Header is currently part of the scroll view and can be scrolled off of the screen. Remove BillingFormCellType raw Int type --- .../UIViewControllerExtensions.swift | 1 + .../Cell/BillingFormHeaderCellStyle.swift | 2 + .../Cell/BillingFormTextFieldCellStyle.swift | 1 + ...aultBillingFormAddressLine1CellStyle.swift | 5 +- ...aultBillingFormAddressLine2CellStyle.swift | 6 +- .../DefaultBillingFormCityCellStyle.swift | 6 +- .../DefaultBillingFormCountryCellStyle.swift | 6 +- .../DefaultBillingFormFullNameCellStyle.swift | 6 +- ...faultBillingFormPhoneNumberCellStyle.swift | 6 +- .../DefaultBillingFormPostCodeCellStyle.swift | 6 +- .../DefaultBillingFormStateCellStyle.swift | 6 +- .../DefaultBillingFormHeaderCellStyle.swift | 9 ++- .../Field/BillingFormPhoneNumberText.swift | 4 +- .../View/Field/BillingFormTextField.swift | 3 +- .../View/Field/BillingFormTextFieldView.swift | 19 ++--- .../Fields/BillingFormTextFieldCell.swift | 33 +++++---- .../Header/BillingFormHeaderCell.swift | 23 +++--- .../BillingFormViewController.swift | 54 ++++++++++---- .../ViewModel/BillingFormCellType.swift | 4 +- .../DefaultBillingFormViewModel.swift | 73 ++++++++++--------- 20 files changed, 169 insertions(+), 104 deletions(-) diff --git a/Source/Extensions/UIViewControllerExtensions.swift b/Source/Extensions/UIViewControllerExtensions.swift index da6c7527..8ad77c8c 100644 --- a/Source/Extensions/UIViewControllerExtensions.swift +++ b/Source/Extensions/UIViewControllerExtensions.swift @@ -25,6 +25,7 @@ extension UIViewController { let activeTextFieldOrigin: CGPoint? = activeTextFieldRect?.origin if !aRect.contains(activeTextFieldOrigin!) { scrollView.scrollRectToVisible(activeTextFieldRect!, animated: true) + } } } diff --git a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift index 2118ea37..ef36590f 100644 --- a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift @@ -1,7 +1,9 @@ import Foundation +import UIKit // Header Cell public protocol BillingFormHeaderCellStyle { + var backgroundColor: UIColor { get } var headerLabel: InputLabelStyle { get } var cancelButton: FormButtonStyle { get } var doneButton: FormButtonStyle { get set} diff --git a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift index ba3e3616..662b4586 100644 --- a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift @@ -2,6 +2,7 @@ import UIKit // Field Cell public protocol BillingFormTextFieldCellStyle { + var type: BillingFormCellType { get } var backgroundColor: UIColor { get } var title: InputLabelStyle? { get } var hint: InputLabelStyle? { get } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift index 081cc6cf..27ee1c98 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift @@ -2,13 +2,15 @@ import UIKit struct DefaultBillingFormAddressLine1CellStyle : BillingFormTextFieldCellStyle { + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .addressLine1, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine1".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), @@ -18,6 +20,7 @@ struct DefaultBillingFormAddressLine1CellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift index 69b3838b..7fff7b09 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift @@ -1,13 +1,16 @@ import UIKit struct DefaultBillingFormAddressLine2CellStyle : BillingFormTextFieldCellStyle { + + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .addressLine2, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine2".localized(forClass: DefaultBillingFormAddressLine2CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), @@ -17,6 +20,7 @@ struct DefaultBillingFormAddressLine2CellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift index 77a2111e..28d476f2 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift @@ -1,13 +1,16 @@ import UIKit struct DefaultBillingFormCityCellStyle : BillingFormTextFieldCellStyle { + + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .city, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "city".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), @@ -17,6 +20,7 @@ struct DefaultBillingFormCityCellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift index e267c9b2..ac999209 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift @@ -1,13 +1,16 @@ import UIKit struct DefaultBillingFormCountryCellStyle : BillingFormTextFieldCellStyle { + + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .country, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "country".localized(forClass: DefaultBillingFormCountryCellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), @@ -17,6 +20,7 @@ struct DefaultBillingFormCountryCellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift index 89a9425e..2d783898 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift @@ -1,13 +1,16 @@ import UIKit struct DefaultBillingFormFullNameCellStyle : BillingFormTextFieldCellStyle { + + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .fullName, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "name".localized(forClass: DefaultBillingFormFullNameCellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), @@ -17,6 +20,7 @@ struct DefaultBillingFormFullNameCellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift index 35a6d301..2023ae84 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift @@ -1,13 +1,16 @@ import UIKit struct DefaultBillingFormPhoneNumberCellStyle : BillingFormTextFieldCellStyle { + + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .phoneNumber, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "phone".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self)), hint: InputLabelStyle? = DefaultHintInputLabelStyle(isHidden: false,text: "billingFormPhoneNumberHint".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self)), textfield: TextFieldStyle = DefaultTextField(isSupprtingNumbericKeyboard: true), @@ -17,6 +20,7 @@ struct DefaultBillingFormPhoneNumberCellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift index c49850ec..1f72451f 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift @@ -1,13 +1,16 @@ import UIKit struct DefaultBillingFormPostcodeCellStyle : BillingFormTextFieldCellStyle { + + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .postcode, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "postcode".localized(forClass: DefaultBillingFormPostcodeCellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), @@ -17,6 +20,7 @@ struct DefaultBillingFormPostcodeCellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift index 5cadd8c5..6645d432 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift @@ -1,13 +1,16 @@ import UIKit struct DefaultBillingFormStateCellStyle : BillingFormTextFieldCellStyle { + + var type: BillingFormCellType var backgroundColor: UIColor var title: InputLabelStyle? var hint: InputLabelStyle? var textfield: TextFieldStyle var error: ErrorInputLabelStyle - init(backgroundColor: UIColor = .white, + init(type: BillingFormCellType = .state, + backgroundColor: UIColor = .white, header: InputLabelStyle = DefaultTitleLabelStyle(text: "countryRegion".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), @@ -17,6 +20,7 @@ struct DefaultBillingFormStateCellStyle : BillingFormTextFieldCellStyle { self.hint = hint self.textfield = textfield self.error = error + self.type = type } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift index fef1fc0f..4393b30e 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift @@ -1,13 +1,16 @@ -import Foundation +import UIKit -// Header Cell struct DefaultBillingFormHeaderCellStyle: BillingFormHeaderCellStyle { + + var backgroundColor: UIColor var headerLabel: InputLabelStyle var cancelButton: FormButtonStyle var doneButton: FormButtonStyle - init(headerLabel: InputLabelStyle = DefaultHeaderLabelFormStyle(), + init(backgroundColor: UIColor = .white, + headerLabel: InputLabelStyle = DefaultHeaderLabelFormStyle(), cancelButton: FormButtonStyle = DefaultCancelButtonFormStyle(), doneButton: FormButtonStyle = DefaultDoneFormButtonStyle()) { + self.backgroundColor = backgroundColor self.headerLabel = headerLabel self.doneButton = doneButton self.cancelButton = cancelButton diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index b7d31d3f..ba1a6116 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -31,8 +31,8 @@ final class BillingFormPhoneNumberText: BillingFormTextField { private var previousTextCount = 0 private var previousFormat = "" - override init(type: BillingFormCellType) { - super.init(type: type) + override init(type: BillingFormCellType, tag: Int) { + super.init(type: type,tag: tag) setup() } diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift index bf33e307..ff3b6f14 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift @@ -2,9 +2,10 @@ import UIKit class BillingFormTextField: UITextField { var type: BillingFormCellType - init(type: BillingFormCellType) { + init(type: BillingFormCellType, tag: Int) { self.type = type super.init(frame: .zero) + self.tag = tag } required init?(coder: NSCoder) { diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index 818552f8..2950488e 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -3,8 +3,7 @@ import UIKit protocol BillingFormTextFieldViewDelegate: AnyObject { func textFieldShouldBeginEditing(textField: UITextField) func textFieldShouldReturn() - func textFieldDidEndEditing(textField: UITextField) - func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) + func textFieldShouldEndEditing(textField: UITextField, replacementString: String) } final class BillingFormTextFieldView: UIView { @@ -49,7 +48,7 @@ final class BillingFormTextFieldView: UIView { }() private(set) lazy var textField: UITextField = { - let view = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type) : BillingFormTextField(type: self.type) + let view = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type, tag: tag) : BillingFormTextField(type: self.type, tag: tag) view.text = style.textfield.text view.font = style.textfield.font view.placeholder = style.textfield.placeHolder @@ -67,11 +66,12 @@ final class BillingFormTextFieldView: UIView { return view }() - init(type: BillingFormCellType, style: BillingFormTextFieldCellStyle, delegate: BillingFormTextFieldViewDelegate? = nil) { + init(type: BillingFormCellType, tag: Int, style: BillingFormTextFieldCellStyle, delegate: BillingFormTextFieldViewDelegate? = nil) { self.style = style self.type = type super.init(frame: .zero) self.delegate = delegate + self.tag = tag self.setupViews() } @@ -154,18 +154,13 @@ extension BillingFormTextFieldView: UITextFieldDelegate { delegate?.textFieldShouldBeginEditing(textField: textField) } - func textFieldDidEndEditing(_ textField: UITextField) { - textFieldContainer.layer.borderColor = style.textfield.normalBorderColor.cgColor - delegate?.textFieldDidEndEditing(textField: textField) + func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { + delegate?.textFieldShouldEndEditing(textField: textField, replacementString: textField.text ?? "") + return true } func textFieldShouldReturn(_ textField: UITextField) -> Bool { delegate?.textFieldShouldReturn() return false } - - func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { - delegate?.textFieldDidChangeCharacters(textField: textField, replacementString: string) - return true - } } diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift index df38e23a..7ea39f6b 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift @@ -4,29 +4,33 @@ import PhoneNumberKit protocol BillingFormTextFieldCellDelegate: AnyObject { func textFieldShouldBeginEditing(textField: UITextField) func textFieldShouldReturn() - func textFieldDidEndEditing(textField: UITextField) - func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) + func textFieldShouldEndEditing(textField: UITextField, replacementString: String) } final class BillingFormTextFieldCell: UITableViewCell { weak var delegate: BillingFormTextFieldCellDelegate? - private var style: BillingFormTextFieldCellStyle - private var type: BillingFormCellType + var style: BillingFormTextFieldCellStyle? = nil + + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + } - init(type: BillingFormCellType, style: BillingFormTextFieldCellStyle, delegate: BillingFormTextFieldCellDelegate?) { + func update(style: BillingFormTextFieldCellStyle, tag: Int) { self.style = style - self.type = type - super.init(style: .default, reuseIdentifier: nil) - self.delegate = delegate + self.tag = tag setupViews() } - required init?(coder: NSCoder) { + + @available(*, unavailable) + required init?(coder _: NSCoder) { fatalError("init(coder:) has not been implemented") } - private lazy var paymentInputView: BillingFormTextFieldView = { - let view = BillingFormTextFieldView(type: type, style: style,delegate: self) + private lazy var paymentInputView: UIView = { + guard let style = style else { return UIView() } + let view = BillingFormTextFieldView(type: style.type, tag: tag, style: style ,delegate: self) view.translatesAutoresizingMaskIntoConstraints = false return view }() @@ -56,9 +60,6 @@ extension BillingFormTextFieldCell { } extension BillingFormTextFieldCell: BillingFormTextFieldViewDelegate { - func textFieldDidEndEditing(textField: UITextField) { - delegate?.textFieldDidEndEditing(textField: textField) - } func textFieldShouldBeginEditing(textField: UITextField) { delegate?.textFieldShouldBeginEditing(textField: textField) @@ -67,8 +68,8 @@ extension BillingFormTextFieldCell: BillingFormTextFieldViewDelegate { delegate?.textFieldShouldReturn() } - func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) { - delegate?.textFieldDidChangeCharacters(textField: textField, replacementString: replacementString) + func textFieldShouldEndEditing(textField: UITextField, replacementString: String) { + delegate?.textFieldShouldEndEditing(textField: textField, replacementString: replacementString) } } diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index d7535139..4916dca9 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -5,7 +5,7 @@ protocol BillingFormHeaderCellDelegate: AnyObject { func cancelButtonIsPressed() } -final class BillingFormHeaderCell: UITableViewCell { +final class BillingFormHeaderCell: UIView { private var style: BillingFormHeaderCellStyle private weak var delegate: BillingFormHeaderCellDelegate? @@ -49,7 +49,7 @@ final class BillingFormHeaderCell: UITableViewCell { init(style: BillingFormHeaderCellStyle , delegate: BillingFormHeaderCellDelegate?) { self.style = style - super.init(style: .default, reuseIdentifier: nil) + super.init(frame: .zero) self.delegate = delegate setupViews() } @@ -75,19 +75,20 @@ final class BillingFormHeaderCell: UITableViewCell { extension BillingFormHeaderCell { private func setupViews() { + backgroundColor = style.backgroundColor setupCancelButton() setupDoneButton() setupHeaderLabel() } private func setupCancelButton() { - contentView.addSubview(cancelButton) + addSubview(cancelButton) NSLayoutConstraint.activate([ cancelButton.topAnchor.constraint( equalTo: safeTopAnchor, constant: 0), cancelButton.leadingAnchor.constraint( - equalTo: contentView.safeLeadingAnchor, + equalTo: safeLeadingAnchor, constant: 20), cancelButton.heightAnchor.constraint( equalToConstant: style.cancelButton.height), @@ -97,13 +98,13 @@ extension BillingFormHeaderCell { } private func setupDoneButton() { - contentView.addSubview(done) + addSubview(done) NSLayoutConstraint.activate([ done.topAnchor.constraint( equalTo: safeTopAnchor, constant: 0), done.trailingAnchor.constraint( - equalTo: contentView.safeTrailingAnchor, + equalTo: safeTrailingAnchor, constant: -20), done.heightAnchor.constraint( equalToConstant: style.doneButton.height), @@ -113,19 +114,19 @@ extension BillingFormHeaderCell { } private func setupHeaderLabel() { - contentView.addSubview(headerLabel) + addSubview(headerLabel) NSLayoutConstraint.activate([ headerLabel.topAnchor.constraint( - equalTo: contentView.safeTopAnchor, + equalTo: safeTopAnchor, constant: 58), headerLabel.leadingAnchor.constraint( - equalTo: contentView.safeLeadingAnchor, + equalTo: safeLeadingAnchor, constant: 20), headerLabel.trailingAnchor.constraint( - equalTo: contentView.safeTrailingAnchor, + equalTo: safeTrailingAnchor, constant: -20), headerLabel.bottomAnchor.constraint( - equalTo: contentView.safeBottomAnchor, + equalTo: safeBottomAnchor, constant: -40) ]) } diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 2d8d4062..257c2471 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -4,10 +4,12 @@ protocol BillingFormViewControllerdelegate: AnyObject { func doneButtonIsPressed(sender: UIViewController) func cancelButtonIsPressed(sender: UIViewController) func tableView(numberOfRowsInSection section: Int) -> Int - func tableView(cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell + func getViewForHeader(sender: UIViewController) -> UIView? + func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat + func tableView(tableView: UITableView, cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell func tableView(estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat func validate(textField: BillingFormTextField) - func textFieldIsChanged(textField: BillingFormTextField, replacementString: String) + func textFieldShouldEndEditing(textField: BillingFormTextField, replacementString: String) } final class BillingFormViewController: UIViewController { @@ -17,9 +19,16 @@ final class BillingFormViewController: UIViewController { private var viewModel: BillingFormViewModel private var notificationCenter = NotificationCenter.default + private lazy var headerView: UIView = { + let view = delegate?.getViewForHeader(sender: self) + view?.translatesAutoresizingMaskIntoConstraints = false + return view ?? UIView() + }() + private lazy var tableView: UITableView = { let view = UITableView() view.dataSource = self + view.delegate = self view.rowHeight = UITableView.automaticDimension view.estimatedRowHeight = 300 view.separatorStyle = .none @@ -27,12 +36,14 @@ final class BillingFormViewController: UIViewController { view.showsHorizontalScrollIndicator = false view.allowsSelection = false view.translatesAutoresizingMaskIntoConstraints = false + view.register(BillingFormTextFieldCell.self, forCellReuseIdentifier: "BillingFormTextFieldCellId") return view }() override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = viewModel.style.mainBackground + setupHeaderView() setupTableView() } @@ -65,7 +76,7 @@ final class BillingFormViewController: UIViewController { @objc func keyboardWillShow(notification: NSNotification) { scrollViewOnKeyboardWillShow(notification: notification, scrollView: tableView as UIScrollView, - activeField: nil) + activeField: focusedTextField) } @objc func keyboardWillHide(notification: Notification) { @@ -76,12 +87,30 @@ final class BillingFormViewController: UIViewController { // setup views extension BillingFormViewController { + + private func setupHeaderView(){ + view.addSubview(headerView) + NSLayoutConstraint.activate([ + headerView.topAnchor.constraint( + equalTo: view.safeTopAnchor, + constant: 20), + headerView.leadingAnchor.constraint( + equalTo: view.safeLeadingAnchor, + constant: 20), + headerView.trailingAnchor.constraint( + equalTo: view.safeTrailingAnchor, + constant: -20), + headerView.heightAnchor.constraint( + equalToConstant: 130) + ]) + } + private func setupTableView() { view.addSubview(tableView) NSLayoutConstraint.activate([ tableView.topAnchor.constraint( - equalTo: view.safeTopAnchor, - constant: 20), + equalTo: headerView.safeBottomAnchor, + constant: 0), tableView.leadingAnchor.constraint( equalTo: view.safeLeadingAnchor, constant: 20), @@ -102,13 +131,14 @@ extension BillingFormViewController { } // UITableViewDataSource -extension BillingFormViewController: UITableViewDataSource { +extension BillingFormViewController: UITableViewDataSource, UITableViewDelegate{ + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { delegate?.tableView(numberOfRowsInSection: section) ?? 0 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - delegate?.tableView(cellForRowAt: indexPath, sender: self) ?? UITableViewCell() + delegate?.tableView(tableView: tableView, cellForRowAt: indexPath, sender: self) ?? UITableViewCell() } func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { @@ -118,17 +148,11 @@ extension BillingFormViewController: UITableViewDataSource { //FormCellDelegate extension BillingFormViewController: BillingFormTextFieldCellDelegate { - func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) { + func textFieldShouldEndEditing(textField: UITextField, replacementString: String) { guard let textField = textField as? BillingFormTextField else { return } - delegate?.textFieldIsChanged(textField: textField, replacementString: replacementString) + delegate?.textFieldShouldEndEditing(textField: textField, replacementString: replacementString) } - func textFieldDidEndEditing(textField: UITextField) { - guard let textField = textField as? BillingFormTextField else { return } - delegate?.validate(textField: textField) - } - - func textFieldShouldBeginEditing(textField: UITextField) { self.focusedTextField = textField } diff --git a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift index 36b0e034..89f8e497 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift @@ -1,6 +1,6 @@ import Foundation -@frozen enum BillingFormCellType: Int, CaseIterable { +@frozen public enum BillingFormCellType: Int, CaseIterable { case fullName = 1 case addressLine1 = 2 case addressLine2 = 3 @@ -10,7 +10,7 @@ import Foundation case country = 7 case phoneNumber = 8 - var validator: Validator { + internal var validator: Validator { switch self { case .fullName: return FullNameValidator() case .addressLine1: return AddressLine1Validator() diff --git a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift index 43214cde..3084b597 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift @@ -26,53 +26,55 @@ final class DefaultBillingFormViewModel: BillingFormViewModel { self.initialRegionCode = initialRegionCode self.delegate = delegate } - - func getCell(for row: Int, delegate: UIViewController? = nil) -> UITableViewCell { - if row == 0 { - return getHeaderCell(delegate: delegate as? BillingFormHeaderCellDelegate) - } - return getFieldCell(for: row, delegate: delegate as? BillingFormTextFieldCellDelegate) - } - private func getHeaderCell(delegate: BillingFormHeaderCellDelegate?) -> UITableViewCell { + func getHeaderView(delegate: BillingFormHeaderCellDelegate?) -> UIView { var style = style.header - updateHeaderView(with: &style) - let cell = BillingFormHeaderCell(style: style, delegate: delegate) - self.editDelegate = cell - return cell - } - - private func getFieldCell(for row: Int, delegate: BillingFormTextFieldCellDelegate?) -> UITableViewCell { - guard let type = BillingFormCellType(rawValue: row) else { return UITableViewCell()} - var style = style.fields[row - 1] - updateErrorView(with: &style, type: type) - updateTextField(with: &style, type: type) - return BillingFormTextFieldCell(type: type, style: style, delegate: delegate) + style.doneButton.isEnabled = textValueOfCellType.values.count == self.style.fields.count + let view = BillingFormHeaderCell(style: style, delegate: delegate) + self.editDelegate = view + return view } - private func updateHeaderView(with style: inout BillingFormHeaderCellStyle) { - style.doneButton.isEnabled = textValueOfCellType.values.count == self.style.fields.count + func update(cell: BillingFormTextFieldCell, row: Int, delegate: BillingFormTextFieldCellDelegate?) -> UITableViewCell { + guard style.fields.count > row else { return UITableViewCell() } + var style = style.fields[row] + updateErrorView(with: &style) + updateTextField(with: &style) + cell.delegate = delegate + cell.update(style: style, tag: row) + return cell } - private func updateErrorView(with style: inout BillingFormTextFieldCellStyle, type: BillingFormCellType) { - guard let hasError = errorFlagOfCellType[type] else { return } + private func updateErrorView(with style: inout BillingFormTextFieldCellStyle) { + guard let hasError = errorFlagOfCellType[style.type] else { return } style.error.isHidden = !hasError } - private func updateTextField(with style: inout BillingFormTextFieldCellStyle, type: BillingFormCellType) { - guard let text = textValueOfCellType[type] else { return } + private func updateTextField(with style: inout BillingFormTextFieldCellStyle) { + guard let text = textValueOfCellType[style.type] else { return } style.textfield.text = text } } extension DefaultBillingFormViewModel: BillingFormViewControllerdelegate { - func textFieldIsChanged(textField: BillingFormTextField, replacementString: String) { + func getViewForHeader(sender: UIViewController) -> UIView? { + return getHeaderView(delegate: sender as? BillingFormHeaderCellDelegate) + } + + func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + UITableView.automaticDimension + } + + func textFieldShouldEndEditing(textField: BillingFormTextField, replacementString: String) { + validate(textField: textField) + if !replacementString.isEmpty { textValueOfCellType[textField.type] = replacementString } if textValueOfCellType.values.count == style.fields.count { - editDelegate?.didFinishEditingBillingForm(successfully: !errorFlagOfCellType.values.allSatisfy({$0})) + let isSuccessful = (errorFlagOfCellType.isEmpty || errorFlagOfCellType.values.allSatisfy({$0})) + editDelegate?.didFinishEditingBillingForm(successfully: isSuccessful) } } @@ -81,11 +83,12 @@ extension DefaultBillingFormViewModel: BillingFormViewControllerdelegate { } func tableView(numberOfRowsInSection section: Int) -> Int { - style.fields.count + 1 + style.fields.count } - func tableView(cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell { - getCell(for: indexPath.row, delegate: sender) + func tableView(tableView: UITableView, cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell { + let cell = BillingFormTextFieldCell() + return update(cell: cell, row: indexPath.row, delegate: sender as? BillingFormViewController) } func doneButtonIsPressed(sender: UIViewController) { @@ -109,14 +112,16 @@ extension DefaultBillingFormViewModel: BillingFormViewControllerdelegate { func validate(textField: BillingFormTextField) { let type = textField.type let text = textField.text - textValueOfCellType[type] = text + + defer { + textValueOfCellType[type] = text + updatedRow = textField.tag + } guard !type.validator.validate(text: textField.text) else { errorFlagOfCellType[type] = true - updatedRow = type.rawValue return } errorFlagOfCellType[type] = false - updatedRow = type.rawValue } } From 1674596ce1950a07cfc4451c19ea8295975b55b3 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 10:14:20 +0100 Subject: [PATCH 23/55] Update `updateRow` code to be without implicitly capturing `self` --- .../ViewController/BillingFormViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 257c2471..bb23ba88 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -179,9 +179,9 @@ extension BillingFormViewController { private func setupViewModel() { viewModel.updateRow = { DispatchQueue.main.async { [weak self] in - guard let self = self, let row = self.viewModel.updatedRow else { return } + guard let row = self?.viewModel.updatedRow else { return } let indexPath = IndexPath(row: row, section: 0) - self.tableView.reloadRows(at: [indexPath], with: .automatic) + self?.tableView.reloadRows(at: [indexPath], with: .automatic) } } From ba10ffebfb461303d58e487fc7c68533af5f7505 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 10:47:02 +0100 Subject: [PATCH 24/55] Update `UIColor` initialisation using `hex` --- Source/CheckoutColor.swift | 26 +++++++++++++++++- Source/Extensions/UIColor+Extension.swift | 33 ----------------------- 2 files changed, 25 insertions(+), 34 deletions(-) delete mode 100644 Source/Extensions/UIColor+Extension.swift diff --git a/Source/CheckoutColor.swift b/Source/CheckoutColor.swift index a18419cf..de0d2de3 100644 --- a/Source/CheckoutColor.swift +++ b/Source/CheckoutColor.swift @@ -5,5 +5,29 @@ extension UIColor { public static let doveGray = UIColor(hex: "#636363") public static let codGray = UIColor(hex: "#141414") public static let mediumGray = UIColor(hex: "#8A8A8A") - public static let tallPoppyRed = UIColor(hex: "#AD283E") + public static let tallPoppyRed = UIColor(hex: "#AD283E") +} + +extension UIColor { + fileprivate convenience init(hex: String, alpha: CGFloat = 1.0) { + var cString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() + + if cString.hasPrefix("#") { cString.removeFirst() } + + guard cString.count == 6 else { + self.init(hex: "ff0000") // gray color + return + } + + var rgbValue: UInt64 = 0 + Scanner(string: cString).scanHexInt64(&rgbValue) + + self.init ( + red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgbValue & 0x0000FF) / 255.0, + alpha: CGFloat(1.0) + ) + } + } diff --git a/Source/Extensions/UIColor+Extension.swift b/Source/Extensions/UIColor+Extension.swift deleted file mode 100644 index 2093cf34..00000000 --- a/Source/Extensions/UIColor+Extension.swift +++ /dev/null @@ -1,33 +0,0 @@ -// -// File.swift -// -// -// Created by Ehab Alsharkawy on 27/04/2022. -// - -import Foundation -import UIKit - -extension UIColor { - convenience init(hex: String, alpha: CGFloat = 1.0) { - var cString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() - - if cString.hasPrefix("#") { cString.removeFirst() } - - guard cString.count == 6 else { - self.init(hex: "ff0000") // gray color - return - } - - var rgbValue: UInt64 = 0 - Scanner(string: cString).scanHexInt64(&rgbValue) - - self.init ( - red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, - green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, - blue: CGFloat(rgbValue & 0x0000FF) / 255.0, - alpha: CGFloat(1.0) - ) - } - -} From 31c2a02861df498044106e01781458409d387b39 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 10:49:13 +0100 Subject: [PATCH 25/55] Rename `inActive` to `disabled` --- .../Header/Cancel/DefaultCancelButtonFormStyle.swift | 12 ++++++------ .../Header/Done/DefaultDoneFormButtonStyle.swift | 12 ++++++------ .../Style/Protocols/FormButtonStyle.swift | 4 ++-- .../TableViewCell/Header/BillingFormHeaderCell.swift | 8 ++++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift index c3d315f0..484b137d 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift @@ -5,8 +5,8 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { var text: String var font: UIFont var activeTitleColor: UIColor - var inActiveTitleColor: UIColor - var inActiveTintColor: UIColor + var disabledTitleColor: UIColor + var disabledTintColor: UIColor var activeTintColor: UIColor var backgroundColor: UIColor var height: Double @@ -16,8 +16,8 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { text: String = "cancel".localized(forClass: DefaultCancelButtonFormStyle.self), font: UIFont = UIFont.systemFont(ofSize: 17), activeTitleColor: UIColor = .brandeisBlue, - inActiveTitleColor: UIColor = .doveGray, - inActiveTintColor: UIColor = .doveGray, + disabledTitleColor: UIColor = .doveGray, + disabledTintColor: UIColor = .doveGray, activeTintColor: UIColor = .brandeisBlue, backgroundColor: UIColor = .white, height: Double = 44, @@ -26,8 +26,8 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { self.text = text self.font = font self.activeTitleColor = activeTitleColor - self.inActiveTitleColor = inActiveTitleColor - self.inActiveTintColor = inActiveTintColor + self.disabledTitleColor = disabledTitleColor + self.disabledTintColor = disabledTintColor self.activeTintColor = activeTintColor self.backgroundColor = backgroundColor self.height = height diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift index 85bcac0d..5cbe7122 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift @@ -5,8 +5,8 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { var text: String var font: UIFont var activeTitleColor: UIColor - var inActiveTitleColor: UIColor - var inActiveTintColor: UIColor + var disabledTitleColor: UIColor + var disabledTintColor: UIColor var activeTintColor: UIColor var backgroundColor: UIColor var height: Double @@ -16,8 +16,8 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { text: String = "done".localized(forClass: DefaultDoneFormButtonStyle.self), font: UIFont = UIFont.systemFont(ofSize: 17), activeTitleColor: UIColor = .brandeisBlue, - inActiveTitleColor: UIColor = .doveGray, - inActiveTintColor: UIColor = .doveGray, + disabledTitleColor: UIColor = .doveGray, + disabledTintColor: UIColor = .doveGray, activeTintColor: UIColor = .brandeisBlue, backgroundColor: UIColor = .white, height: Double = 44, @@ -26,8 +26,8 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { self.text = text self.font = font self.activeTitleColor = activeTitleColor - self.inActiveTitleColor = inActiveTitleColor - self.inActiveTintColor = inActiveTintColor + self.disabledTitleColor = disabledTitleColor + self.disabledTintColor = disabledTintColor self.activeTintColor = activeTintColor self.backgroundColor = backgroundColor self.height = height diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift index 12c4cdd3..84eb750a 100644 --- a/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/FormButtonStyle.swift @@ -6,8 +6,8 @@ public protocol FormButtonStyle { var font: UIFont { get } var isEnabled: Bool { get set} var activeTitleColor: UIColor { get } - var inActiveTitleColor: UIColor { get } - var inActiveTintColor: UIColor { get } + var disabledTitleColor: UIColor { get } + var disabledTintColor: UIColor { get } var activeTintColor: UIColor { get } var backgroundColor: UIColor { get } var height: Double { get } diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index 4916dca9..62ecee94 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -14,8 +14,8 @@ final class BillingFormHeaderCell: UIView { view.setTitle(style.cancelButton.text, for: .normal) view.titleLabel?.font = style.cancelButton.font view.setTitleColor(style.cancelButton.activeTitleColor, for: .normal) - view.setTitleColor(style.cancelButton.inActiveTitleColor, for: .disabled) - view.tintColor = view.isEnabled ? style.cancelButton.activeTintColor : style.cancelButton.inActiveTintColor + view.setTitleColor(style.cancelButton.disabledTitleColor, for: .disabled) + view.tintColor = view.isEnabled ? style.cancelButton.activeTintColor : style.cancelButton.disabledTintColor view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = style.cancelButton.backgroundColor view.addTarget(self, action: #selector(cancelAction), for: .touchUpInside) @@ -28,8 +28,8 @@ final class BillingFormHeaderCell: UIView { view.setTitle(style.doneButton.text, for: .normal) view.titleLabel?.font = style.doneButton.font view.setTitleColor(style.doneButton.activeTitleColor, for: .normal) - view.setTitleColor(style.doneButton.inActiveTitleColor, for: .disabled) - view.tintColor = view.isEnabled ? style.doneButton.activeTintColor : style.doneButton.inActiveTintColor + view.setTitleColor(style.doneButton.disabledTitleColor, for: .disabled) + view.tintColor = view.isEnabled ? style.doneButton.activeTintColor : style.doneButton.disabledTintColor view.translatesAutoresizingMaskIntoConstraints = false view.backgroundColor = style.doneButton.backgroundColor view.addTarget(self, action: #selector(doneAction), for: .touchUpInside) From 44fe19911b4b331e3cd3cbb3b1c1d3023a80dce4 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 10:55:06 +0100 Subject: [PATCH 26/55] Update `phoneNumberKit` to be `private` --- .../BillingForm/View/Field/BillingFormPhoneNumberText.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index ba1a6116..12919f5a 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -3,7 +3,7 @@ import PhoneNumberKit final class BillingFormPhoneNumberText: BillingFormTextField { /// Phone Number Kit - let phoneNumberKit = PhoneNumberKit() + private let phoneNumberKit = PhoneNumberKit() var partialFormatter: PartialFormatter { return PartialFormatter.init(phoneNumberKit: phoneNumberKit, defaultRegion: "GB", withPrefix: true) } From 7b6b139224f1a69f21e938aecde609ff5ec93c0c Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 10:57:23 +0100 Subject: [PATCH 27/55] Update `partialFormatter` to be `lazy` --- .../BillingForm/View/Field/BillingFormPhoneNumberText.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index 12919f5a..7fb4b2c8 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -4,9 +4,8 @@ import PhoneNumberKit final class BillingFormPhoneNumberText: BillingFormTextField { /// Phone Number Kit private let phoneNumberKit = PhoneNumberKit() - var partialFormatter: PartialFormatter { - return PartialFormatter.init(phoneNumberKit: phoneNumberKit, defaultRegion: "GB", withPrefix: true) - } + + private lazy var partialFormatter = PartialFormatter(phoneNumberKit: phoneNumberKit, defaultRegion: "GB", withPrefix: true) /// National Number (e.g. ) var nationalNumber: String { From 64559f6faac2ca9a45a050dad85c922d06c853a4 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 10:59:39 +0100 Subject: [PATCH 28/55] Sorted `BillingFormPhoneNumberText` variables by their access level --- .../Field/BillingFormPhoneNumberText.swift | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index 7fb4b2c8..58a049be 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -2,18 +2,12 @@ import UIKit import PhoneNumberKit final class BillingFormPhoneNumberText: BillingFormTextField { - /// Phone Number Kit - private let phoneNumberKit = PhoneNumberKit() - - private lazy var partialFormatter = PartialFormatter(phoneNumberKit: phoneNumberKit, defaultRegion: "GB", withPrefix: true) - /// National Number (e.g. ) + var phoneNumber: PhoneNumber? var nationalNumber: String { let rawNumber = self.text ?? "" return partialFormatter.nationalNumber(from: rawNumber) } - - /// True if the phone number is valid, false otherwise var isValidNumber: Bool { let rawNumber = self.text ?? "" do { @@ -23,13 +17,12 @@ final class BillingFormPhoneNumberText: BillingFormTextField { return false } } - - /// Phone Number - var phoneNumber: PhoneNumber? - + private var previousTextCount = 0 private var previousFormat = "" - + private let phoneNumberKit = PhoneNumberKit() + private lazy var partialFormatter = PartialFormatter(phoneNumberKit: phoneNumberKit, defaultRegion: "GB", withPrefix: true) + override init(type: BillingFormCellType, tag: Int) { super.init(type: type,tag: tag) setup() @@ -44,7 +37,7 @@ final class BillingFormPhoneNumberText: BillingFormTextField { } /// Called when the text changed. - @objc public func textFieldDidChange(textField: UITextField) { + @objc private func textFieldDidChange(textField: UITextField) { var targetCursorPosition = 0 if let startPosition = textField.selectedTextRange?.start { targetCursorPosition = textField.offset(from: textField.beginningOfDocument, to: startPosition) From fc01d9c41cffbd43402b2d5face3d7f7addfc5c0 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 11:04:45 +0100 Subject: [PATCH 29/55] Update `delegate` to be `weak` --- .../NewUI/BillingForm/ViewModel/BillingFormViewModel.swift | 6 +----- .../BillingForm/ViewModel/DefaultBillingFormViewModel.swift | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift index 74ae130f..2103b009 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift @@ -1,10 +1,6 @@ import Foundation -protocol BillingFormViewModelDelegate { - /// Executed when an user tap on the done button. - /// - /// - parameter controller: `AddressViewController` - /// - parameter address: Address entered by the user +protocol BillingFormViewModelDelegate: AnyObject { func onTapDoneButton(address: CkoAddress, phone: CkoPhoneNumber) } diff --git a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift index 3084b597..2e0cc855 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift @@ -11,11 +11,11 @@ final class DefaultBillingFormViewModel: BillingFormViewModel { var errorFlagOfCellType = [BillingFormCellType: Bool]() var textValueOfCellType = [BillingFormCellType: String]() + var editDelegate: BillingFormViewModelEditingDelegate? + weak var delegate: BillingFormViewModelDelegate? private var initialCountry: String private var initialRegionCode: String? - var editDelegate: BillingFormViewModelEditingDelegate? - var delegate: BillingFormViewModelDelegate? init(style: BillingFormStyle, initialCountry: String = "", From 96ee26cc2c52f40dd5e927ecfd01e4e7a1264eb5 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 11:06:30 +0100 Subject: [PATCH 30/55] Add `keyboardType` to be `.phonePad` for `BillingFormPhoneNumberText` --- .../BillingForm/View/Field/BillingFormPhoneNumberText.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index 58a049be..cf2e8813 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -33,6 +33,7 @@ final class BillingFormPhoneNumberText: BillingFormTextField { } private func setup() { + keyboardType = .phonePad addTarget(self, action: #selector(textFieldDidChange), for: UIControl.Event.editingChanged) } From f1dbfe5f65156da8bd589e8b3b37f69198c1fd97 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 11:08:23 +0100 Subject: [PATCH 31/55] Clean code --- .../UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift index ff3b6f14..4b9e8c2a 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextField.swift @@ -1,7 +1,7 @@ import UIKit class BillingFormTextField: UITextField { - var type: BillingFormCellType + let type: BillingFormCellType init(type: BillingFormCellType, tag: Int) { self.type = type super.init(frame: .zero) From 347c1068b43961ab6b38ce6de96565180f9d1924 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 12:27:40 +0100 Subject: [PATCH 32/55] Update Localization --- Source/Resources/en.lproj/Localizable.strings | 14 +++++++++++++- .../DefaultBillingFormFullNameCellStyle.swift | 2 +- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Resources/en.lproj/Localizable.strings b/Source/Resources/en.lproj/Localizable.strings index 2abebf34..e7cf31f4 100644 --- a/Source/Resources/en.lproj/Localizable.strings +++ b/Source/Resources/en.lproj/Localizable.strings @@ -1,4 +1,16 @@ - +"missingBillingFormFullName" = "Missing Name"; +"missingBillingFormAddressLine1" = "Missing Address Line 1"; +"missingBillingFormAddressLine2" = "Missing Address Line 2"; +"missingBillingFormCity" = "Missing City"; +"missingBillingFormState" = "Missing State"; +"missingBillingFormPostcode" = "Missing Postcode"; +"missingBillingFormPhoneNumber" = "Missing Phone Number"; +"missingBillingFormCountry" = "Missing Country"; +"billingFormPhoneNumberHint" = "Phone Number"; +"billingAddressTitle" = "Billing address"; +"city" = "City"; +"cancel" = "Cancel"; +"done" = "Done"; "cardNumber" = "Card Number*"; "cardholderName" = "Cardholder's name"; "cardholderNameRequired" = "Cardholder's name*"; diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift index 2d783898..b7c39741 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift @@ -14,7 +14,7 @@ struct DefaultBillingFormFullNameCellStyle : BillingFormTextFieldCellStyle { header: InputLabelStyle = DefaultTitleLabelStyle(text: "name".localized(forClass: DefaultBillingFormFullNameCellStyle.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCityFullName".localized(forClass: DefaultBillingFormFullNameCellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormFullName".localized(forClass: DefaultBillingFormFullNameCellStyle.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint From e77207e183894a40bc74f8b39108c36c23699191 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 12:31:28 +0100 Subject: [PATCH 33/55] Update Example test UI Test --- .../iOS Example FrameUITests/iOS_Example_FrameUITests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS Example Frame SPM/iOS Example FrameUITests/iOS_Example_FrameUITests.swift b/iOS Example Frame SPM/iOS Example FrameUITests/iOS_Example_FrameUITests.swift index 4552f1a1..ad8f1a41 100644 --- a/iOS Example Frame SPM/iOS Example FrameUITests/iOS_Example_FrameUITests.swift +++ b/iOS Example Frame SPM/iOS Example FrameUITests/iOS_Example_FrameUITests.swift @@ -33,7 +33,7 @@ class iOS_Example_FrameUITests: XCTestCase { // Use XCTAssert and related functions to verify your tests produce the correct results. let app = XCUIApplication() - app.buttons["Go to payment page"].tap() + app.buttons["OLD"].tap() let elementsQuery = app.scrollViews.otherElements elementsQuery.textFields["4242"].tap() elementsQuery.textFields["4242"].typeText("424242424242424242") From 52267b18f68fe06b9f5ec7e0ebda3e31c52f74c4 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 13:04:47 +0100 Subject: [PATCH 34/55] Fix Test cases --- ...BillingFormTextFieldCellMockDelegate.swift | 18 ++----- ...illingFormViewControllerMockDelegate.swift | 50 ++++++++++++++++--- ...illingFormFullNameTextFieldCellTests.swift | 37 +++++--------- .../View/BillingFormTextFieldViewTests.swift | 2 +- .../BillingFormViewControllerTests.swift | 33 ++---------- .../ViewModel/BillingFormViewModelTests.swift | 26 ++++------ 6 files changed, 76 insertions(+), 90 deletions(-) diff --git a/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift b/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift index 34f29ef7..2505971b 100644 --- a/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift +++ b/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift @@ -8,11 +8,8 @@ class BillingFormTextFieldCellMockDelegate: BillingFormTextFieldCellDelegate { var textFieldShouldReturnCalledTimes = 0 - var textFieldDidEndEditingCalledTimes = 0 - var textFieldDidEndEditingLastCalledWithTextField: UITextField? - - var textFieldDidChangeCharactersCalledTimes = 0 - var textFieldDidChangeCharactersLastCalledWithTextField: UITextField? + var textFieldShouldEndEditingCalledTimes = 0 + var textFieldShouldEndEditingLastCalledWithTextField: UITextField? var textFieldDidChangeCharactersLastCalledWithReplacementString: String? func textFieldShouldBeginEditing(textField: UITextField) { @@ -24,14 +21,9 @@ class BillingFormTextFieldCellMockDelegate: BillingFormTextFieldCellDelegate { textFieldShouldReturnCalledTimes += 1 } - func textFieldDidEndEditing(textField: UITextField) { - textFieldDidEndEditingCalledTimes += 1 - textFieldDidEndEditingLastCalledWithTextField = textField - } - - func textFieldDidChangeCharacters(textField: UITextField, replacementString: String) { - textFieldDidChangeCharactersCalledTimes += 1 - textFieldDidChangeCharactersLastCalledWithTextField = textField + func textFieldShouldEndEditing(textField: UITextField, replacementString: String) { + textFieldShouldEndEditingCalledTimes += 1 + textFieldShouldEndEditingLastCalledWithTextField = textField textFieldDidChangeCharactersLastCalledWithReplacementString = replacementString } } diff --git a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift index f9a3ca59..53c24be2 100644 --- a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift +++ b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift @@ -1,7 +1,7 @@ import UIKit @testable import Frames -class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { +class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { var doneButtonIsPressedCalledTimes = 0 var doneButtonIsPressedLastCalledWithSender: UIViewController? @@ -11,11 +11,7 @@ class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { var numberOfRowsInSectionCalledTimes = 0 var numberOfRowsInSectionLastCalledWithSection: Int? - - var cellForRowAtCalledTimes = 0 - var cellForRowAtLastCalledWithIndexPath: IndexPath? - var cellForRowAtLastCalledWithSender: UIViewController? - + var estimatedHeightForRowCalledTimes = 0 var estimatedHeightForRowLastCalledWithIndexPath: IndexPath? @@ -26,6 +22,22 @@ class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { var textFieldIsChangedLastCalledWithBillingFormTextField: BillingFormTextField? var textFieldIsChangedLastCalledWithReplacementString: String? + var getViewForHeaderCalledTimes = 0 + var getViewForHeaderLastCalledWithSender: UIViewController? + + var heightForHeaderInSectionCalledTimes = 0 + var heightForHeaderInSectionLastCalledWithTableView: UITableView? + var heightForHeaderInSectionLastCalledWithSection: Int? + + var cellForRowAtCalledTimes = 0 + var cellForRowAtLastCalledWithTableView: UITableView? + var cellForRowAtLastCalledWithIndexPath: IndexPath? + var cellForRowAtLastCalledWithSender: UIViewController? + + var textFieldShouldEndEditingCalledTimes = 0 + var textFieldShouldEndEditingLastCalledWithBillingFormTextField: BillingFormTextField? + var textFieldShouldEndEditingLastCalledWithReplacementString: String? + func doneButtonIsPressed(sender: UIViewController) { doneButtonIsPressedCalledTimes += 1 doneButtonIsPressedLastCalledWithSender = sender @@ -66,4 +78,30 @@ class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { textFieldIsChangedLastCalledWithReplacementString = replacementString } + func getViewForHeader(sender: UIViewController) -> UIView? { + getViewForHeaderCalledTimes += 1 + getViewForHeaderLastCalledWithSender = sender + return UIView() + } + + func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + heightForHeaderInSectionCalledTimes += 1 + heightForHeaderInSectionLastCalledWithTableView = tableView + heightForHeaderInSectionLastCalledWithSection = section + return 10.0 + } + + func tableView(tableView: UITableView, cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell { + cellForRowAtCalledTimes += 1 + cellForRowAtLastCalledWithTableView = tableView + cellForRowAtLastCalledWithIndexPath = indexPath + cellForRowAtLastCalledWithSender = sender + return UITableViewCell() + } + + func textFieldShouldEndEditing(textField: BillingFormTextField, replacementString: String) { + textFieldShouldEndEditingCalledTimes += 1 + textFieldShouldEndEditingLastCalledWithBillingFormTextField = textField + textFieldShouldEndEditingLastCalledWithReplacementString = replacementString + } } diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift index b5d7710f..800406d1 100644 --- a/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift +++ b/Tests/UI/New UI/BillingForm/View/BillingFormFullNameTextFieldCellTests.swift @@ -2,19 +2,19 @@ import XCTest @testable import Frames class BillingFormTextFieldCellTests: XCTestCase { - var view: BillingFormTextFieldCell! + var cell: BillingFormTextFieldCell! override func setUp() { super.setUp() - view = BillingFormTextFieldCell(type: .fullName, style: DefaultBillingFormFullNameCellStyle(), delegate: nil) + cell = BillingFormTextFieldCell() } func testCallDelegateMethodTextFieldShouldBeginEditing() { let delegate = BillingFormTextFieldCellMockDelegate() - let textField = BillingFormTextField(type: .fullName) - view.delegate = delegate + let textField = BillingFormTextField(type: .fullName, tag: 2) + cell.delegate = delegate - view.textFieldShouldBeginEditing(textField: textField) + cell.textFieldShouldBeginEditing(textField: textField) XCTAssertEqual(delegate.textFieldShouldBeginEditingCalledTimes, 1) XCTAssertEqual(delegate.textFieldShouldBeginEditingLastCalledWithTextField, textField) @@ -22,34 +22,21 @@ class BillingFormTextFieldCellTests: XCTestCase { func testCallDelegateMethodTextFieldShouldReturn() { let delegate = BillingFormTextFieldCellMockDelegate() - view.delegate = delegate + cell.delegate = delegate - view.textFieldShouldReturn() + cell.textFieldShouldReturn() XCTAssertEqual(delegate.textFieldShouldReturnCalledTimes, 1) } func testCallDelegateMethodTextFieldDidEndEditing() { let delegate = BillingFormTextFieldCellMockDelegate() - let textField = BillingFormTextField(type: .fullName) - view.delegate = delegate + let textField = BillingFormTextField(type: .fullName, tag: 2) + cell.delegate = delegate - view.textFieldDidEndEditing(textField: textField) + cell.textFieldShouldEndEditing(textField: textField, replacementString: "test") - XCTAssertEqual(delegate.textFieldDidEndEditingCalledTimes, 1) - XCTAssertEqual(delegate.textFieldDidEndEditingLastCalledWithTextField, textField) - } - - func testCallDelegateMethodTextFieldDidChangeCharacters() { - let delegate = BillingFormTextFieldCellMockDelegate() - let textField = BillingFormTextField(type: .fullName) - let text = "test" - view.delegate = delegate - - view.textFieldDidChangeCharacters(textField: textField, replacementString: text) - - XCTAssertEqual(delegate.textFieldDidChangeCharactersCalledTimes, 1) - XCTAssertEqual(delegate.textFieldDidChangeCharactersLastCalledWithTextField, textField) - XCTAssertEqual(delegate.textFieldDidChangeCharactersLastCalledWithReplacementString, text) + XCTAssertEqual(delegate.textFieldShouldEndEditingCalledTimes, 1) + XCTAssertEqual(delegate.textFieldShouldEndEditingLastCalledWithTextField, textField) } } diff --git a/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift index 6d05a316..c48c1a58 100644 --- a/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift +++ b/Tests/UI/New UI/BillingForm/View/BillingFormTextFieldViewTests.swift @@ -7,7 +7,7 @@ class BillingFormTextFieldViewTests: XCTestCase { override func setUp() { super.setUp() - view = BillingFormTextFieldView(type: .fullName, style: style, delegate: nil) + view = BillingFormTextFieldView(type: .fullName, tag: 2, style: style, delegate: nil) } func testHeaderLabelStyle(){ diff --git a/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift b/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift index b16c0530..416d36e2 100644 --- a/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift +++ b/Tests/UI/New UI/BillingForm/ViewController/BillingFormViewControllerTests.swift @@ -17,8 +17,9 @@ class BillingFormViewControllerTests: XCTestCase { func testInitialization() { billingFormViewController.viewDidLoad() billingFormViewController.viewDidLayoutSubviews() - XCTAssertEqual(billingFormViewController.view.subviews.count, 1) - XCTAssertTrue(billingFormViewController.view.subviews.first is UITableView) + XCTAssertEqual(billingFormViewController.view.subviews.count, 2) + XCTAssertTrue(billingFormViewController.view.subviews.first is BillingFormHeaderCell) + XCTAssertTrue(billingFormViewController.view.subviews.last is UITableView) } func testCallDelegateMethodOnTapDoneButton() { @@ -80,31 +81,5 @@ class BillingFormViewControllerTests: XCTestCase { XCTAssertEqual(delegate.estimatedHeightForRowCalledTimes, 1) XCTAssertEqual(delegate.estimatedHeightForRowLastCalledWithIndexPath, indexthPath) } - - func testCallDelegateMethodValidate() { - let delegate = BillingFormViewControllerMockDelegate() - billingFormViewController.viewDidLoad() - billingFormViewController.delegate = delegate - - let textfield = BillingFormTextField(type: .fullName) - - billingFormViewController.textFieldDidEndEditing(textField: textfield) - - XCTAssertEqual(delegate.validateCalledTimes, 1) - XCTAssertEqual(delegate.validateLastCalledWithBillingFormTextField, textfield) - } - - func testCallDelegateMethodTextFieldIsChanged() { - let delegate = BillingFormViewControllerMockDelegate() - billingFormViewController.viewDidLoad() - billingFormViewController.delegate = delegate - - let textfield = BillingFormTextField(type: .fullName) - let text = "Test" - billingFormViewController.textFieldDidChangeCharacters(textField: textfield, replacementString: text) - - XCTAssertEqual(delegate.textFieldIsChangedCalledTimes, 1) - XCTAssertEqual(delegate.textFieldIsChangedLastCalledWithReplacementString, text) - XCTAssertEqual(delegate.textFieldIsChangedLastCalledWithBillingFormTextField, textfield) - } + } diff --git a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift index 86f15aba..ca1e9db7 100644 --- a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift +++ b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift @@ -11,28 +11,21 @@ class BillingFormViewModelTests: XCTestCase { // TableView Cells func testGetHeaderCell() { let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) - let cell = viewModel.getCell(for: 0) - XCTAssertNotNil(cell) - XCTAssertTrue(cell is BillingFormHeaderCell) - } - - func testGetFieldCell() { - let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) - let cell = viewModel.getCell(for: 1) - XCTAssertNotNil(cell) - XCTAssertTrue(cell is BillingFormTextFieldCell) + let view = viewModel.getViewForHeader(sender: UIViewController()) + XCTAssertNotNil(view) } func testValidationWhenTextFieldIsEmptyThenShowError() { let expectation = expectation(description: #function) let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) let expectedType = BillingFormCellType.fullName + let tag = 2 let text = "" - let textField = BillingFormTextField(type: expectedType) + let textField = BillingFormTextField(type: expectedType, tag: tag) textField.text = text viewModel.updateRow = { - XCTAssertEqual(viewModel.updatedRow, expectedType.rawValue) + XCTAssertEqual(viewModel.updatedRow, tag) XCTAssertEqual(viewModel.errorFlagOfCellType[expectedType], true) XCTAssertEqual(viewModel.textValueOfCellType[expectedType], text) expectation.fulfill() @@ -47,11 +40,12 @@ class BillingFormViewModelTests: XCTestCase { let viewModel = DefaultBillingFormViewModel(style: DefaultBillingFormStyle()) let expectedType = BillingFormCellType.fullName let text = "fullName" - let textField = BillingFormTextField(type: expectedType) + let tag = 2 + let textField = BillingFormTextField(type: expectedType, tag: tag) textField.text = text viewModel.updateRow = { - XCTAssertEqual(viewModel.updatedRow, expectedType.rawValue) + XCTAssertEqual(viewModel.updatedRow, tag) XCTAssertEqual(viewModel.errorFlagOfCellType[expectedType], false) XCTAssertEqual(viewModel.textValueOfCellType[expectedType], text) expectation.fulfill() @@ -106,10 +100,10 @@ class BillingFormViewModelTests: XCTestCase { viewModel.textValueOfCellType = textValueOfCellType viewModel.editDelegate = delegate - viewModel.textFieldIsChanged(textField: BillingFormTextField(type: .fullName), replacementString: "text") + viewModel.textFieldShouldEndEditing(textField: BillingFormTextField(type: .fullName, tag: 2), replacementString: "text") XCTAssertEqual(delegate.didFinishEditingBillingFormCalledTimes, 1) - XCTAssertEqual(delegate.didFinishEditingBillingFormLastCalledWithSuccessfully, false) + XCTAssertEqual(delegate.didFinishEditingBillingFormLastCalledWithSuccessfully, true) } } From 4045c05038f5242b73d837986f5fa9ba4f656240 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 14:56:56 +0100 Subject: [PATCH 35/55] Support Carthage --- Source/Extensions/StringExtensions.swift | 4 +- ...aultBillingFormAddressLine1CellStyle.swift | 4 +- ...aultBillingFormAddressLine2CellStyle.swift | 4 +- .../DefaultBillingFormCityCellStyle.swift | 4 +- .../DefaultBillingFormCountryCellStyle.swift | 4 +- .../DefaultBillingFormFullNameCellStyle.swift | 4 +- ...faultBillingFormPhoneNumberCellStyle.swift | 6 +- .../DefaultBillingFormPostCodeCellStyle.swift | 4 +- .../DefaultBillingFormStateCellStyle.swift | 4 +- .../Cancel/DefaultCancelButtonFormStyle.swift | 2 +- .../Done/DefaultDoneFormButtonStyle.swift | 2 +- .../Title/DefaultHeaderLabelFormStyle.swift | 2 +- .../project.pbxproj | 1539 +++++++++++------ .../AppIcon.appiconset/100.png | Bin 0 -> 3730 bytes .../AppIcon.appiconset/1024.png | Bin 0 -> 122426 bytes .../AppIcon.appiconset/114.png | Bin 0 -> 4426 bytes .../AppIcon.appiconset/120.png | Bin 0 -> 4706 bytes .../AppIcon.appiconset/144.png | Bin 0 -> 5964 bytes .../AppIcon.appiconset/152.png | Bin 0 -> 6668 bytes .../AppIcon.appiconset/167.png | Bin 0 -> 7022 bytes .../AppIcon.appiconset/180.png | Bin 0 -> 7758 bytes .../Assets.xcassets/AppIcon.appiconset/20.png | Bin 0 -> 840 bytes .../Assets.xcassets/AppIcon.appiconset/29.png | Bin 0 -> 946 bytes .../Assets.xcassets/AppIcon.appiconset/40.png | Bin 0 -> 1134 bytes .../Assets.xcassets/AppIcon.appiconset/50.png | Bin 0 -> 1302 bytes .../Assets.xcassets/AppIcon.appiconset/57.png | Bin 0 -> 1460 bytes .../Assets.xcassets/AppIcon.appiconset/58.png | Bin 0 -> 1512 bytes .../Assets.xcassets/AppIcon.appiconset/60.png | Bin 0 -> 1492 bytes .../Assets.xcassets/AppIcon.appiconset/72.png | Bin 0 -> 2500 bytes .../Assets.xcassets/AppIcon.appiconset/76.png | Bin 0 -> 2662 bytes .../Assets.xcassets/AppIcon.appiconset/80.png | Bin 0 -> 2852 bytes .../Assets.xcassets/AppIcon.appiconset/87.png | Bin 0 -> 3174 bytes .../AppIcon.appiconset/Contents.json | 99 +- .../Assets.xcassets/Contents.json | 6 +- .../logo.imageset/Contents.json | 21 + .../logo.imageset/playstore.png | Bin 0 -> 33636 bytes .../Base.lproj/LaunchScreen.storyboard | 31 +- .../Base.lproj/Main.storyboard | 99 +- .../MainViewController.swift | 36 +- .../de.lproj/LaunchScreen.strings | 1 + .../fr.lproj/LaunchScreen.strings | 1 + .../it.lproj/LaunchScreen.strings | 1 + .../nl.lproj/LaunchScreen.strings | 1 + .../iOS_Example_FrameUITests.swift | 2 +- 44 files changed, 1188 insertions(+), 693 deletions(-) create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/144.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/180.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/20.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/50.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/57.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/76.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/80.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json create mode 100644 iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png create mode 100644 iOS Example Frame Carthage/iOS Example Frame/de.lproj/LaunchScreen.strings create mode 100644 iOS Example Frame Carthage/iOS Example Frame/fr.lproj/LaunchScreen.strings create mode 100644 iOS Example Frame Carthage/iOS Example Frame/it.lproj/LaunchScreen.strings create mode 100644 iOS Example Frame Carthage/iOS Example Frame/nl.lproj/LaunchScreen.strings diff --git a/Source/Extensions/StringExtensions.swift b/Source/Extensions/StringExtensions.swift index 0a7276c8..13aa8993 100644 --- a/Source/Extensions/StringExtensions.swift +++ b/Source/Extensions/StringExtensions.swift @@ -3,7 +3,7 @@ import UIKit extension String { - private func getBundle(forClass: Any.Type) -> Foundation.Bundle { + private func getBundle(forClass: Swift.AnyClass) -> Foundation.Bundle { #if SWIFT_PACKAGE let baseBundle = Bundle.module #else @@ -13,7 +13,7 @@ extension String { return path == nil ? baseBundle : Foundation.Bundle(path: path!)! } - func localized(forClass: Any.Type, comment: String = "") -> String { + func localized(forClass: Swift.AnyClass, comment: String = "") -> String { let bundle = getBundle(forClass: forClass) return NSLocalizedString(self, bundle: bundle, comment: "") } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift index 27ee1c98..d4dba73d 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormAddressLine1CellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .addressLine1, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine1".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine1".localized(forClass: CheckoutTheme.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormAddressLine1".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormAddressLine1".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift index 7fff7b09..fe113275 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormAddressLine2CellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .addressLine2, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine2".localized(forClass: DefaultBillingFormAddressLine2CellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "addressLine2".localized(forClass: CheckoutTheme.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormAddressLine2".localized(forClass: DefaultBillingFormAddressLine2CellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormAddressLine2".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift index 28d476f2..fc05aec7 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormCityCellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .city, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "city".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "city".localized(forClass: CheckoutTheme.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCity".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCity".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift index ac999209..d5de9588 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormCountryCellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .country, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "country".localized(forClass: DefaultBillingFormCountryCellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "country".localized(forClass: CheckoutTheme.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCountry".localized(forClass: DefaultBillingFormCountryCellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCountry".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift index b7c39741..54d15428 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormFullNameCellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .fullName, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "name".localized(forClass: DefaultBillingFormFullNameCellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "name".localized(forClass: CheckoutTheme.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormFullName".localized(forClass: DefaultBillingFormFullNameCellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormFullName".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift index 2023ae84..0f3fc93f 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormPhoneNumberCellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .phoneNumber, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "phone".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self)), - hint: InputLabelStyle? = DefaultHintInputLabelStyle(isHidden: false,text: "billingFormPhoneNumberHint".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "phone".localized(forClass: CheckoutTheme.self)), + hint: InputLabelStyle? = DefaultHintInputLabelStyle(isHidden: false,text: "billingFormPhoneNumberHint".localized(forClass: CheckoutTheme.self)), textfield: TextFieldStyle = DefaultTextField(isSupprtingNumbericKeyboard: true), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCity".localized(forClass: DefaultBillingFormPhoneNumberCellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormCity".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift index 1f72451f..3b105939 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormPostcodeCellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .postcode, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "postcode".localized(forClass: DefaultBillingFormPostcodeCellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "postcode".localized(forClass: CheckoutTheme.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormPostcode".localized(forClass: DefaultBillingFormPostcodeCellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormPostcode".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift index 6645d432..a3e15191 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift @@ -11,10 +11,10 @@ struct DefaultBillingFormStateCellStyle : BillingFormTextFieldCellStyle { init(type: BillingFormCellType = .state, backgroundColor: UIColor = .white, - header: InputLabelStyle = DefaultTitleLabelStyle(text: "countryRegion".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self)), + header: InputLabelStyle = DefaultTitleLabelStyle(text: "countryRegion".localized(forClass: CheckoutTheme.self)), hint: InputLabelStyle? = nil, textfield: TextFieldStyle = DefaultTextField(), - error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormState".localized(forClass: DefaultBillingFormAddressLine1CellStyle.self))) { + error: ErrorInputLabelStyle = DefaultErrorInputLabelStyle(text: "missingBillingFormState".localized(forClass: CheckoutTheme.self))) { self.backgroundColor = backgroundColor self.title = header self.hint = hint diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift index 484b137d..e6c86a06 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift @@ -13,7 +13,7 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { var width: Double init( isEnabled: Bool = true, - text: String = "cancel".localized(forClass: DefaultCancelButtonFormStyle.self), + text: String = "cancel".localized(forClass: CheckoutTheme.self), font: UIFont = UIFont.systemFont(ofSize: 17), activeTitleColor: UIColor = .brandeisBlue, disabledTitleColor: UIColor = .doveGray, diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift index 5cbe7122..baa3072e 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift @@ -13,7 +13,7 @@ struct DefaultDoneFormButtonStyle: FormButtonStyle { var width: Double init( isEnabled: Bool = true, - text: String = "done".localized(forClass: DefaultDoneFormButtonStyle.self), + text: String = "done".localized(forClass: CheckoutTheme.self), font: UIFont = UIFont.systemFont(ofSize: 17), activeTitleColor: UIColor = .brandeisBlue, disabledTitleColor: UIColor = .doveGray, diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift index b1e9e1b8..a4f65657 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift @@ -2,7 +2,7 @@ import UIKit struct DefaultHeaderLabelFormStyle: InputLabelStyle { var isHidden: Bool { false } - var text: String { "billingAddressTitle".localized(forClass: DefaultHeaderLabelFormStyle.self) } + var text: String { "billingAddressTitle".localized(forClass: CheckoutTheme.self) } var font: UIFont { UIFont.systemFont(ofSize: 24) } var textColor: UIColor { .codGray } } diff --git a/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj b/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj index bc448193..7f2a52e4 100644 --- a/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj +++ b/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj @@ -23,127 +23,174 @@ /* Begin PBXBuildFile section */ 4422777226163748009626A0 /* Frames.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4422775D26163748009626A0 /* Frames.framework */; }; 4422777326163748009626A0 /* Frames.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 4422775D26163748009626A0 /* Frames.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 442277E82616376E009626A0 /* CheckoutTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4422777E2616376D009626A0 /* CheckoutTheme.swift */; }; - 442277E92616376E009626A0 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 442277802616376D009626A0 /* Localizable.strings */; }; - 442277EA2616376E009626A0 /* icon-visa.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277832616376D009626A0 /* icon-visa.png */; }; - 442277EB2616376E009626A0 /* icon-maestro.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277842616376D009626A0 /* icon-maestro.png */; }; - 442277EC2616376E009626A0 /* icon-visa@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277852616376D009626A0 /* icon-visa@2x.png */; }; - 442277ED2616376E009626A0 /* icon-mastercard@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277862616376D009626A0 /* icon-mastercard@2x.png */; }; - 442277EE2616376E009626A0 /* icon-mastercard@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277872616376D009626A0 /* icon-mastercard@3x.png */; }; - 442277EF2616376E009626A0 /* icon-visa@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277882616376D009626A0 /* icon-visa@3x.png */; }; - 442277F02616376E009626A0 /* icon-dinersclub.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277892616376D009626A0 /* icon-dinersclub.png */; }; - 442277F12616376E009626A0 /* icon-mastercard.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422778A2616376D009626A0 /* icon-mastercard.png */; }; - 442277F22616376E009626A0 /* icon-jcb.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422778B2616376D009626A0 /* icon-jcb.png */; }; - 442277F32616376E009626A0 /* icon-amex.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422778C2616376D009626A0 /* icon-amex.png */; }; - 442277F42616376E009626A0 /* icon-maestro@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422778D2616376D009626A0 /* icon-maestro@3x.png */; }; - 442277F52616376E009626A0 /* icon-jcb@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422778E2616376D009626A0 /* icon-jcb@2x.png */; }; - 442277F62616376E009626A0 /* icon-amex@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422778F2616376D009626A0 /* icon-amex@2x.png */; }; - 442277F72616376E009626A0 /* icon-amex@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277902616376D009626A0 /* icon-amex@3x.png */; }; - 442277F82616376E009626A0 /* icon-jcb@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277912616376D009626A0 /* icon-jcb@3x.png */; }; - 442277F92616376E009626A0 /* icon-maestro@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277922616376D009626A0 /* icon-maestro@2x.png */; }; - 442277FA2616376E009626A0 /* icon-dinersclub@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277932616376D009626A0 /* icon-dinersclub@3x.png */; }; - 442277FB2616376E009626A0 /* icon-discover@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277942616376D009626A0 /* icon-discover@2x.png */; }; - 442277FC2616376E009626A0 /* icon-discover@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277952616376D009626A0 /* icon-discover@3x.png */; }; - 442277FD2616376E009626A0 /* icon-discover.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277962616376D009626A0 /* icon-discover.png */; }; - 442277FE2616376E009626A0 /* icon-dinersclub@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277972616376D009626A0 /* icon-dinersclub@2x.png */; }; - 442277FF2616376E009626A0 /* checkmark.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422779B2616376D009626A0 /* checkmark.png */; }; - 442278002616376E009626A0 /* checkmark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422779C2616376D009626A0 /* checkmark@2x.png */; }; - 442278012616376E009626A0 /* checkmark@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4422779D2616376D009626A0 /* checkmark@3x.png */; }; - 442278022616376E009626A0 /* keyboard-previous@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A02616376D009626A0 /* keyboard-previous@2x.png */; }; - 442278032616376E009626A0 /* keyboard-next@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A12616376D009626A0 /* keyboard-next@3x.png */; }; - 442278042616376E009626A0 /* keyboard-next@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A22616376D009626A0 /* keyboard-next@2x.png */; }; - 442278052616376E009626A0 /* keyboard-previous@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A32616376D009626A0 /* keyboard-previous@3x.png */; }; - 442278062616376E009626A0 /* keyboard-down.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A42616376D009626A0 /* keyboard-down.png */; }; - 442278072616376E009626A0 /* keyboard-previous.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A52616376D009626A0 /* keyboard-previous.png */; }; - 442278082616376E009626A0 /* keyboard-next.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A62616376D009626A0 /* keyboard-next.png */; }; - 442278092616376E009626A0 /* keyboard-down@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A72616376D009626A0 /* keyboard-down@2x.png */; }; - 4422780A2616376E009626A0 /* keyboard-down@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 442277A82616376D009626A0 /* keyboard-down@3x.png */; }; - 4422780B2616376E009626A0 /* CardListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277AC2616376E009626A0 /* CardListCell.swift */; }; - 4422780C2616376E009626A0 /* ExpirationDatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277AD2616376E009626A0 /* ExpirationDatePicker.swift */; }; - 4422780D2616376E009626A0 /* CardListCellName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277AE2616376E009626A0 /* CardListCellName.swift */; }; - 4422780E2616376E009626A0 /* CardNumberInputViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B02616376E009626A0 /* CardNumberInputViewDelegate.swift */; }; - 4422780F2616376E009626A0 /* CvvConfirmationViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B12616376E009626A0 /* CvvConfirmationViewControllerDelegate.swift */; }; - 442278102616376E009626A0 /* ThreedsWebViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B22616376E009626A0 /* ThreedsWebViewControllerDelegate.swift */; }; - 442278112616376E009626A0 /* CountrySelectionViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B32616376E009626A0 /* CountrySelectionViewControllerDelegate.swift */; }; - 442278122616376E009626A0 /* ExpirationDatePickerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B42616376E009626A0 /* ExpirationDatePickerDelegate.swift */; }; - 442278132616376E009626A0 /* CardViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B52616376E009626A0 /* CardViewControllerDelegate.swift */; }; - 442278142616376E009626A0 /* CvvInputViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B62616376E009626A0 /* CvvInputViewDelegate.swift */; }; - 442278152616376E009626A0 /* AddressViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B72616376E009626A0 /* AddressViewControllerDelegate.swift */; }; - 442278162616376E009626A0 /* CardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277B92616376E009626A0 /* CardViewController.swift */; }; - 442278172616376E009626A0 /* CvvConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277BA2616376E009626A0 /* CvvConfirmationViewController.swift */; }; - 442278182616376E009626A0 /* CountrySelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277BB2616376E009626A0 /* CountrySelectionViewController.swift */; }; - 442278192616376E009626A0 /* SimpleLoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277BC2616376E009626A0 /* SimpleLoadingViewController.swift */; }; - 4422781A2616376E009626A0 /* ThreedsWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277BD2616376E009626A0 /* ThreedsWebViewController.swift */; }; - 4422781B2616376E009626A0 /* AddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277BE2616376E009626A0 /* AddressViewController.swift */; }; - 4422781C2616376E009626A0 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C02616376E009626A0 /* CardView.swift */; }; - 4422781D2616376E009626A0 /* DetailsInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C12616376E009626A0 /* DetailsInputView.swift */; }; - 4422781E2616376E009626A0 /* SchemeIconsStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C22616376E009626A0 /* SchemeIconsStackView.swift */; }; - 4422781F2616376E009626A0 /* StandardInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C32616376E009626A0 /* StandardInputView.swift */; }; - 442278202616376E009626A0 /* PhoneNumberInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C42616376E009626A0 /* PhoneNumberInputView.swift */; }; - 442278212616376E009626A0 /* AddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C52616376E009626A0 /* AddressView.swift */; }; - 442278222616376E009626A0 /* CardNumberInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C62616376E009626A0 /* CardNumberInputView.swift */; }; - 442278232616376E009626A0 /* CvvInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C72616376E009626A0 /* CvvInputView.swift */; }; - 442278242616376E009626A0 /* ExpirationDateInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277C82616376E009626A0 /* ExpirationDateInputView.swift */; }; - 442278252616376E009626A0 /* CkoPhoneNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277CA2616376E009626A0 /* CkoPhoneNumber.swift */; }; - 442278262616376E009626A0 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277CB2616376E009626A0 /* Environment.swift */; }; - 442278272616376E009626A0 /* CardScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277CC2616376E009626A0 /* CardScheme.swift */; }; - 442278282616376E009626A0 /* CardProviderResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277CD2616376E009626A0 /* CardProviderResponse.swift */; }; - 442278292616376E009626A0 /* CkoCardTokenResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277CE2616376E009626A0 /* CkoCardTokenResponse.swift */; }; - 4422782A2616376E009626A0 /* Customer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277CF2616376E009626A0 /* Customer.swift */; }; - 4422782B2616376E009626A0 /* CardProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D02616376E009626A0 /* CardProvider.swift */; }; - 4422782C2616376E009626A0 /* CkoAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D12616376E009626A0 /* CkoAddress.swift */; }; - 4422782D2616376E009626A0 /* CardType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D22616376E009626A0 /* CardType.swift */; }; - 4422782E2616376E009626A0 /* CustomerCardList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D32616376E009626A0 /* CustomerCardList.swift */; }; - 4422782F2616376E009626A0 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D42616376E009626A0 /* InputState.swift */; }; - 442278302616376E009626A0 /* CkoCardTokenRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D52616376E009626A0 /* CkoCardTokenRequest.swift */; }; - 442278312616376E009626A0 /* CheckoutTokenStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D62616376E009626A0 /* CheckoutTokenStatus.swift */; }; - 442278322616376E009626A0 /* ErrorResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D72616376E009626A0 /* ErrorResponse.swift */; }; - 442278332616376E009626A0 /* ApplePayTokenRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D82616376E009626A0 /* ApplePayTokenRequest.swift */; }; - 442278342616376E009626A0 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277D92616376E009626A0 /* NetworkError.swift */; }; - 442278352616376E009626A0 /* CustomerCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277DA2616376E009626A0 /* CustomerCard.swift */; }; - 442278372616376E009626A0 /* CheckoutSdkIos.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277DC2616376E009626A0 /* CheckoutSdkIos.swift */; }; - 442278392616376E009626A0 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277DF2616376E009626A0 /* StringExtensions.swift */; }; - 4422783A2616376E009626A0 /* UIViewControllerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277E02616376E009626A0 /* UIViewControllerExtensions.swift */; }; - 4422783B2616376E009626A0 /* UIViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277E12616376E009626A0 /* UIViewExtensions.swift */; }; - 4422783C2616376E009626A0 /* UIResponderExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277E22616376E009626A0 /* UIResponderExtensions.swift */; }; - 4422783D2616376E009626A0 /* CardUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277E32616376E009626A0 /* CardUtils.swift */; }; 4422783E2616376E009626A0 /* CheckoutSdkIos.h in Headers */ = {isa = PBXBuildFile; fileRef = 442277E52616376E009626A0 /* CheckoutSdkIos.h */; }; - 442278402616376E009626A0 /* CheckoutAPIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 442277E72616376E009626A0 /* CheckoutAPIClient.swift */; }; - 4452A1AD26FB5875006AF798 /* URLHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4452A1AC26FB5874006AF798 /* URLHelper.swift */; }; 44796B51262F31A600F28C6E /* CheckoutEventLoggerKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 44796B50262F31A600F28C6E /* CheckoutEventLoggerKit.xcframework */; }; 44A4DFE5261CC59B00E0C349 /* PhoneNumberKit.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 44A4DFBE261CA91300E0C349 /* PhoneNumberKit.xcframework */; settings = {ATTRIBUTES = (Required, ); }; }; - 44F095202625F7E700CB287F /* FramesLogEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44F095162625F7E600CB287F /* FramesLogEvent.swift */; }; - 44F095A72629DCF200CB287F /* UIDeviceExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44F095A52629DCF100CB287F /* UIDeviceExtensions.swift */; }; 44FD98ED26302125001B8FD2 /* CheckoutEventLoggerKit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 44796B50262F31A600F28C6E /* CheckoutEventLoggerKit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 44FD98EF26302125001B8FD2 /* PhoneNumberKit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 44A4DFF5261CCA7700E0C349 /* PhoneNumberKit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 44FD9E262636B31D001B8FD2 /* CheckoutEventLoggerKit.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 44796B50262F31A600F28C6E /* CheckoutEventLoggerKit.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 57256C44269F0F81001EC3D8 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C41269F0F81001EC3D8 /* Request.swift */; }; - 57256C45269F0F81001EC3D8 /* RequestExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C42269F0F81001EC3D8 /* RequestExecutor.swift */; }; - 57256C46269F0F81001EC3D8 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C43269F0F81001EC3D8 /* HTTPMethod.swift */; }; - 57256C50269F0F90001EC3D8 /* DateProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C49269F0F90001EC3D8 /* DateProvider.swift */; }; - 57256C51269F0F90001EC3D8 /* TokenType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C4A269F0F90001EC3D8 /* TokenType.swift */; }; - 57256C53269F0F90001EC3D8 /* CorrelationIDGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C4C269F0F90001EC3D8 /* CorrelationIDGenerator.swift */; }; - 57256C54269F0F90001EC3D8 /* NetworkFlowLoggerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C4D269F0F90001EC3D8 /* NetworkFlowLoggerFactory.swift */; }; - 57256C55269F0F90001EC3D8 /* FramesEventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C4E269F0F90001EC3D8 /* FramesEventLogger.swift */; }; - 57256C56269F0F90001EC3D8 /* NetworkFlowLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C4F269F0F90001EC3D8 /* NetworkFlowLogger.swift */; }; - 57256C5E269F0FA0001EC3D8 /* TopLevelDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C59269F0FA0001EC3D8 /* TopLevelDecoder.swift */; }; - 57256C5F269F0FA0001EC3D8 /* Dispatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C5A269F0FA0001EC3D8 /* Dispatching.swift */; }; - 57256C60269F0FA0001EC3D8 /* TopLevelEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C5B269F0FA0001EC3D8 /* TopLevelEncoder.swift */; }; - 57256C61269F0FA0001EC3D8 /* ContentTypeProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C5C269F0FA0001EC3D8 /* ContentTypeProviding.swift */; }; - 57256C62269F0FA0001EC3D8 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C5D269F0FA0001EC3D8 /* Constants.swift */; }; - 57256C6C269F0FB0001EC3D8 /* JSONEncoder+TopLevelEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C65269F0FB0001EC3D8 /* JSONEncoder+TopLevelEncoder.swift */; }; - 57256C6D269F0FB0001EC3D8 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C66269F0FB0001EC3D8 /* URL+Extensions.swift */; }; - 57256C6E269F0FB0001EC3D8 /* JSONEncoder+ContentTypeProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C67269F0FB0001EC3D8 /* JSONEncoder+ContentTypeProviding.swift */; }; - 57256C6F269F0FB0001EC3D8 /* ErrorResponse+PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C68269F0FB0001EC3D8 /* ErrorResponse+PropertyProviding.swift */; }; - 57256C70269F0FB0001EC3D8 /* DispatchQueue+Dispatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C69269F0FB0001EC3D8 /* DispatchQueue+Dispatching.swift */; }; - 57256C71269F0FB0001EC3D8 /* JSONDecoder+TopLevelDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256C6A269F0FB0001EC3D8 /* JSONDecoder+TopLevelDecoder.swift */; }; 57256C7E269F1181001EC3D8 /* Frames.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4422775D26163748009626A0 /* Frames.framework */; platformFilter = ios; }; - 57256DEC269FA42E001EC3D8 /* Dictionary+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 57256DEB269FA42E001EC3D8 /* Dictionary+Additions.swift */; }; - CB00CA0427EB4B27000069BE /* UIColor+PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA0327EB4B27000069BE /* UIColor+PropertyProviding.swift */; }; - CB00CA0627EB51B8000069BE /* UIFont+PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA0527EB51B8000069BE /* UIFont+PropertyProviding.swift */; }; - CB00CA0827EB5836000069BE /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA0727EB5836000069BE /* Theme.swift */; }; - CB00CA0A27EB5842000069BE /* PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA0927EB5842000069BE /* PropertyProviding.swift */; }; - CB00CA0C27ECA7A1000069BE /* UIBarStyle+stringValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA0B27ECA7A1000069BE /* UIBarStyle+stringValue.swift */; }; + 95FD4D522829533D00A7E295 /* CardUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C792829533D00A7E295 /* CardUtils.swift */; }; + 95FD4D532829533D00A7E295 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C7B2829533D00A7E295 /* Constants.swift */; }; + 95FD4D542829533D00A7E295 /* CkoPhoneNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C7C2829533D00A7E295 /* CkoPhoneNumber.swift */; }; + 95FD4D552829533D00A7E295 /* URLHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C7D2829533D00A7E295 /* URLHelper.swift */; }; + 95FD4D562829533D00A7E295 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C7E2829533D00A7E295 /* Environment.swift */; }; + 95FD4D572829533D00A7E295 /* TopLevelEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C7F2829533D00A7E295 /* TopLevelEncoder.swift */; }; + 95FD4D582829533D00A7E295 /* CardScheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C802829533D00A7E295 /* CardScheme.swift */; }; + 95FD4D592829533D00A7E295 /* CardProviderResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C812829533D00A7E295 /* CardProviderResponse.swift */; }; + 95FD4D5A2829533D00A7E295 /* TopLevelDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C822829533D00A7E295 /* TopLevelDecoder.swift */; }; + 95FD4D5B2829533D00A7E295 /* CkoCardTokenResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C832829533D00A7E295 /* CkoCardTokenResponse.swift */; }; + 95FD4D5C2829533D00A7E295 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C852829533D00A7E295 /* HTTPMethod.swift */; }; + 95FD4D5D2829533D00A7E295 /* RequestExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C862829533D00A7E295 /* RequestExecutor.swift */; }; + 95FD4D5E2829533D00A7E295 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C872829533D00A7E295 /* Request.swift */; }; + 95FD4D5F2829533D00A7E295 /* Customer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C882829533D00A7E295 /* Customer.swift */; }; + 95FD4D602829533D00A7E295 /* CardProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C892829533D00A7E295 /* CardProvider.swift */; }; + 95FD4D612829533D00A7E295 /* Dispatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C8A2829533D00A7E295 /* Dispatching.swift */; }; + 95FD4D622829533D00A7E295 /* CkoAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C8B2829533D00A7E295 /* CkoAddress.swift */; }; + 95FD4D632829533D00A7E295 /* CardType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C8C2829533D00A7E295 /* CardType.swift */; }; + 95FD4D642829533D00A7E295 /* CustomerCardList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C8D2829533D00A7E295 /* CustomerCardList.swift */; }; + 95FD4D652829533D00A7E295 /* InputState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C8E2829533D00A7E295 /* InputState.swift */; }; + 95FD4D662829533D00A7E295 /* CkoCardTokenRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C8F2829533D00A7E295 /* CkoCardTokenRequest.swift */; }; + 95FD4D672829533D00A7E295 /* CheckoutTokenStatus.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C902829533D00A7E295 /* CheckoutTokenStatus.swift */; }; + 95FD4D682829533D00A7E295 /* ErrorResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C912829533D00A7E295 /* ErrorResponse.swift */; }; + 95FD4D692829533D00A7E295 /* ApplePayTokenRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C922829533D00A7E295 /* ApplePayTokenRequest.swift */; }; + 95FD4D6A2829533D00A7E295 /* ContentTypeProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C932829533D00A7E295 /* ContentTypeProviding.swift */; }; + 95FD4D6B2829533D00A7E295 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C942829533D00A7E295 /* NetworkError.swift */; }; + 95FD4D6C2829533D00A7E295 /* NetworkFlowLoggerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C962829533D00A7E295 /* NetworkFlowLoggerFactory.swift */; }; + 95FD4D6D2829533D00A7E295 /* FramesEventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C972829533D00A7E295 /* FramesEventLogger.swift */; }; + 95FD4D6E2829533D00A7E295 /* FramesLogEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C982829533D00A7E295 /* FramesLogEvent.swift */; }; + 95FD4D6F2829533D00A7E295 /* PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C992829533D00A7E295 /* PropertyProviding.swift */; }; + 95FD4D702829533D00A7E295 /* DateProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C9A2829533D00A7E295 /* DateProvider.swift */; }; + 95FD4D712829533D00A7E295 /* TokenType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C9B2829533D00A7E295 /* TokenType.swift */; }; + 95FD4D722829533D00A7E295 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C9C2829533D00A7E295 /* Theme.swift */; }; + 95FD4D732829533D00A7E295 /* CorrelationIDGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C9D2829533D00A7E295 /* CorrelationIDGenerator.swift */; }; + 95FD4D742829533D00A7E295 /* NetworkFlowLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C9E2829533D00A7E295 /* NetworkFlowLogger.swift */; }; + 95FD4D752829533D00A7E295 /* CustomerCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4C9F2829533D00A7E295 /* CustomerCard.swift */; }; + 95FD4D762829533D00A7E295 /* UIFont+PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA12829533D00A7E295 /* UIFont+PropertyProviding.swift */; }; + 95FD4D772829533D00A7E295 /* UIBarStyle+stringValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA22829533D00A7E295 /* UIBarStyle+stringValue.swift */; }; + 95FD4D782829533D00A7E295 /* StringExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA32829533D00A7E295 /* StringExtensions.swift */; }; + 95FD4D792829533D00A7E295 /* ErrorResponse+PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA42829533D00A7E295 /* ErrorResponse+PropertyProviding.swift */; }; + 95FD4D7A2829533D00A7E295 /* DispatchQueue+Dispatching.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA52829533D00A7E295 /* DispatchQueue+Dispatching.swift */; }; + 95FD4D7B2829533D00A7E295 /* JSONEncoder+ContentTypeProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA62829533D00A7E295 /* JSONEncoder+ContentTypeProviding.swift */; }; + 95FD4D7C2829533D00A7E295 /* JSONEncoder+TopLevelEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA72829533D00A7E295 /* JSONEncoder+TopLevelEncoder.swift */; }; + 95FD4D7D2829533D00A7E295 /* UIViewControllerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA82829533D00A7E295 /* UIViewControllerExtensions.swift */; }; + 95FD4D7E2829533D00A7E295 /* JSONDecoder+TopLevelDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CA92829533D00A7E295 /* JSONDecoder+TopLevelDecoder.swift */; }; + 95FD4D7F2829533D00A7E295 /* UIViewExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CAA2829533D00A7E295 /* UIViewExtensions.swift */; }; + 95FD4D802829533D00A7E295 /* URL+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CAB2829533D00A7E295 /* URL+Extensions.swift */; }; + 95FD4D812829533D00A7E295 /* UIDeviceExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CAC2829533D00A7E295 /* UIDeviceExtensions.swift */; }; + 95FD4D822829533D00A7E295 /* UIColor+PropertyProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CAD2829533D00A7E295 /* UIColor+PropertyProviding.swift */; }; + 95FD4D832829533D00A7E295 /* Dictionary+Additions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CAE2829533D00A7E295 /* Dictionary+Additions.swift */; }; + 95FD4D842829533D00A7E295 /* UIResponderExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CAF2829533D00A7E295 /* UIResponderExtensions.swift */; }; + 95FD4D852829533D00A7E295 /* CheckoutAPIClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB02829533D00A7E295 /* CheckoutAPIClient.swift */; }; + 95FD4D862829533D00A7E295 /* PostCodeValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB22829533D00A7E295 /* PostCodeValidator.swift */; }; + 95FD4D872829533D00A7E295 /* CountryValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB32829533D00A7E295 /* CountryValidator.swift */; }; + 95FD4D882829533D00A7E295 /* PhoneNumberValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB42829533D00A7E295 /* PhoneNumberValidator.swift */; }; + 95FD4D892829533D00A7E295 /* AddressLine1Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB52829533D00A7E295 /* AddressLine1Validator.swift */; }; + 95FD4D8A2829533D00A7E295 /* Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB62829533D00A7E295 /* Validator.swift */; }; + 95FD4D8B2829533D00A7E295 /* CityValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB72829533D00A7E295 /* CityValidator.swift */; }; + 95FD4D8C2829533D00A7E295 /* AddressLine2Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB82829533D00A7E295 /* AddressLine2Validator.swift */; }; + 95FD4D8D2829533D00A7E295 /* StateValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CB92829533D00A7E295 /* StateValidator.swift */; }; + 95FD4D8E2829533D00A7E295 /* FullNameValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CBA2829533D00A7E295 /* FullNameValidator.swift */; }; + 95FD4D8F2829533D00A7E295 /* CardListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CBC2829533D00A7E295 /* CardListCell.swift */; }; + 95FD4D902829533D00A7E295 /* BillingFormViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CC02829533D00A7E295 /* BillingFormViewModel.swift */; }; + 95FD4D912829533D00A7E295 /* DefaultBillingFormViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CC12829533D00A7E295 /* DefaultBillingFormViewModel.swift */; }; + 95FD4D922829533D00A7E295 /* BillingFormCellType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CC22829533D00A7E295 /* BillingFormCellType.swift */; }; + 95FD4D932829533D00A7E295 /* DefaultHintInputLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CC72829533D00A7E295 /* DefaultHintInputLabelStyle.swift */; }; + 95FD4D942829533D00A7E295 /* DefaultTitleLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CC92829533D00A7E295 /* DefaultTitleLabelStyle.swift */; }; + 95FD4D952829533D00A7E295 /* DefaultTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CCB2829533D00A7E295 /* DefaultTextField.swift */; }; + 95FD4D962829533D00A7E295 /* DefaultErrorInputLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CCD2829533D00A7E295 /* DefaultErrorInputLabelStyle.swift */; }; + 95FD4D972829533D00A7E295 /* DefaultBillingFormPostCodeCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CD12829533D00A7E295 /* DefaultBillingFormPostCodeCellStyle.swift */; }; + 95FD4D982829533D00A7E295 /* DefaultBillingFormAddressLine2CellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CD32829533D00A7E295 /* DefaultBillingFormAddressLine2CellStyle.swift */; }; + 95FD4D992829533D00A7E295 /* DefaultBillingFormCityCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CD52829533D00A7E295 /* DefaultBillingFormCityCellStyle.swift */; }; + 95FD4D9A2829533D00A7E295 /* DefaultBillingFormFullNameCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CD72829533D00A7E295 /* DefaultBillingFormFullNameCellStyle.swift */; }; + 95FD4D9B2829533D00A7E295 /* DefaultBillingFormStateCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CD92829533D00A7E295 /* DefaultBillingFormStateCellStyle.swift */; }; + 95FD4D9C2829533D00A7E295 /* DefaultBillingFormPhoneNumberCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CDB2829533D00A7E295 /* DefaultBillingFormPhoneNumberCellStyle.swift */; }; + 95FD4D9D2829533D00A7E295 /* DefaultBillingFormAddressLine1CellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CDD2829533D00A7E295 /* DefaultBillingFormAddressLine1CellStyle.swift */; }; + 95FD4D9E2829533D00A7E295 /* DefaultBillingFormCountryCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CDF2829533D00A7E295 /* DefaultBillingFormCountryCellStyle.swift */; }; + 95FD4D9F2829533D00A7E295 /* DefaultBillingFormStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CE12829533D00A7E295 /* DefaultBillingFormStyle.swift */; }; + 95FD4DA02829533D00A7E295 /* DefaultCancelButtonFormStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CE42829533D00A7E295 /* DefaultCancelButtonFormStyle.swift */; }; + 95FD4DA12829533D00A7E295 /* DefaultHeaderLabelFormStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CE62829533D00A7E295 /* DefaultHeaderLabelFormStyle.swift */; }; + 95FD4DA22829533D00A7E295 /* DefaultDoneFormButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CE82829533D00A7E295 /* DefaultDoneFormButtonStyle.swift */; }; + 95FD4DA32829533D00A7E295 /* DefaultBillingFormHeaderCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CEA2829533D00A7E295 /* DefaultBillingFormHeaderCellStyle.swift */; }; + 95FD4DA42829533D00A7E295 /* BillingFormTextFieldCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CEC2829533D00A7E295 /* BillingFormTextFieldCellStyle.swift */; }; + 95FD4DA52829533D00A7E295 /* BillingFormHeaderCellStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CED2829533D00A7E295 /* BillingFormHeaderCellStyle.swift */; }; + 95FD4DA62829533D00A7E295 /* BillingFormStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CEF2829533D00A7E295 /* BillingFormStyle.swift */; }; + 95FD4DA72829533D00A7E295 /* FormButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CF02829533D00A7E295 /* FormButtonStyle.swift */; }; + 95FD4DA82829533D00A7E295 /* InputLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CF12829533D00A7E295 /* InputLabelStyle.swift */; }; + 95FD4DA92829533D00A7E295 /* FormTextFieldStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CF22829533D00A7E295 /* FormTextFieldStyle.swift */; }; + 95FD4DAA2829533D00A7E295 /* ErrorInputLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CF32829533D00A7E295 /* ErrorInputLabelStyle.swift */; }; + 95FD4DAB2829533D00A7E295 /* BillingFormTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CF62829533D00A7E295 /* BillingFormTextField.swift */; }; + 95FD4DAC2829533D00A7E295 /* BillingFormTextFieldView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CF72829533D00A7E295 /* BillingFormTextFieldView.swift */; }; + 95FD4DAD2829533D00A7E295 /* BillingFormPhoneNumberText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CF82829533D00A7E295 /* BillingFormPhoneNumberText.swift */; }; + 95FD4DAE2829533D00A7E295 /* BillingFormTextFieldCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CFB2829533D00A7E295 /* BillingFormTextFieldCell.swift */; }; + 95FD4DAF2829533D00A7E295 /* BillingFormHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CFD2829533D00A7E295 /* BillingFormHeaderCell.swift */; }; + 95FD4DB02829533D00A7E295 /* BillingFormTextFieldErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4CFF2829533D00A7E295 /* BillingFormTextFieldErrorView.swift */; }; + 95FD4DB12829533D00A7E295 /* BillingFormViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D012829533D00A7E295 /* BillingFormViewController.swift */; }; + 95FD4DB22829533D00A7E295 /* BillingFormFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D032829533D00A7E295 /* BillingFormFactory.swift */; }; + 95FD4DB32829533D00A7E295 /* ExpirationDatePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D042829533D00A7E295 /* ExpirationDatePicker.swift */; }; + 95FD4DB42829533D00A7E295 /* CardListCellName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D052829533D00A7E295 /* CardListCellName.swift */; }; + 95FD4DB52829533D00A7E295 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D062829533D00A7E295 /* UITableView.swift */; }; + 95FD4DB62829533D00A7E295 /* CardNumberInputViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D082829533D00A7E295 /* CardNumberInputViewDelegate.swift */; }; + 95FD4DB72829533D00A7E295 /* CvvConfirmationViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D092829533D00A7E295 /* CvvConfirmationViewControllerDelegate.swift */; }; + 95FD4DB82829533D00A7E295 /* ThreedsWebViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D0A2829533D00A7E295 /* ThreedsWebViewControllerDelegate.swift */; }; + 95FD4DB92829533D00A7E295 /* CountrySelectionViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D0B2829533D00A7E295 /* CountrySelectionViewControllerDelegate.swift */; }; + 95FD4DBA2829533D00A7E295 /* ExpirationDatePickerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D0C2829533D00A7E295 /* ExpirationDatePickerDelegate.swift */; }; + 95FD4DBB2829533D00A7E295 /* CardViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D0D2829533D00A7E295 /* CardViewControllerDelegate.swift */; }; + 95FD4DBC2829533D00A7E295 /* CvvInputViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D0E2829533D00A7E295 /* CvvInputViewDelegate.swift */; }; + 95FD4DBD2829533D00A7E295 /* AddressViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D0F2829533D00A7E295 /* AddressViewControllerDelegate.swift */; }; + 95FD4DBE2829533D00A7E295 /* CardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D112829533D00A7E295 /* CardViewController.swift */; }; + 95FD4DBF2829533D00A7E295 /* CvvConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D122829533D00A7E295 /* CvvConfirmationViewController.swift */; }; + 95FD4DC02829533D00A7E295 /* CountrySelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D132829533D00A7E295 /* CountrySelectionViewController.swift */; }; + 95FD4DC12829533D00A7E295 /* SimpleLoadingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D142829533D00A7E295 /* SimpleLoadingViewController.swift */; }; + 95FD4DC22829533D00A7E295 /* ThreedsWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D152829533D00A7E295 /* ThreedsWebViewController.swift */; }; + 95FD4DC32829533D00A7E295 /* AddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D162829533D00A7E295 /* AddressViewController.swift */; }; + 95FD4DC42829533D00A7E295 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D182829533D00A7E295 /* CardView.swift */; }; + 95FD4DC52829533D00A7E295 /* DetailsInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D192829533D00A7E295 /* DetailsInputView.swift */; }; + 95FD4DC62829533D00A7E295 /* SchemeIconsStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D1A2829533D00A7E295 /* SchemeIconsStackView.swift */; }; + 95FD4DC72829533D00A7E295 /* StandardInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D1B2829533D00A7E295 /* StandardInputView.swift */; }; + 95FD4DC82829533D00A7E295 /* PhoneNumberInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D1C2829533D00A7E295 /* PhoneNumberInputView.swift */; }; + 95FD4DC92829533D00A7E295 /* AddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D1D2829533D00A7E295 /* AddressView.swift */; }; + 95FD4DCA2829533D00A7E295 /* CardNumberInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D1E2829533D00A7E295 /* CardNumberInputView.swift */; }; + 95FD4DCB2829533D00A7E295 /* CvvInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D1F2829533D00A7E295 /* CvvInputView.swift */; }; + 95FD4DCC2829533D00A7E295 /* ExpirationDateInputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D202829533D00A7E295 /* ExpirationDateInputView.swift */; }; + 95FD4DCD2829533D00A7E295 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D222829533D00A7E295 /* Localizable.strings */; }; + 95FD4DCE2829533D00A7E295 /* icon-visa.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D252829533D00A7E295 /* icon-visa.png */; }; + 95FD4DCF2829533D00A7E295 /* icon-maestro.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D262829533D00A7E295 /* icon-maestro.png */; }; + 95FD4DD02829533D00A7E295 /* icon-visa@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D272829533D00A7E295 /* icon-visa@2x.png */; }; + 95FD4DD12829533D00A7E295 /* icon-mastercard@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D282829533D00A7E295 /* icon-mastercard@2x.png */; }; + 95FD4DD22829533D00A7E295 /* icon-mastercard@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D292829533D00A7E295 /* icon-mastercard@3x.png */; }; + 95FD4DD32829533D00A7E295 /* icon-visa@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D2A2829533D00A7E295 /* icon-visa@3x.png */; }; + 95FD4DD42829533D00A7E295 /* icon-dinersclub.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D2B2829533D00A7E295 /* icon-dinersclub.png */; }; + 95FD4DD52829533D00A7E295 /* icon-mastercard.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D2C2829533D00A7E295 /* icon-mastercard.png */; }; + 95FD4DD62829533D00A7E295 /* icon-jcb.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D2D2829533D00A7E295 /* icon-jcb.png */; }; + 95FD4DD72829533D00A7E295 /* icon-amex.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D2E2829533D00A7E295 /* icon-amex.png */; }; + 95FD4DD82829533D00A7E295 /* icon-maestro@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D2F2829533D00A7E295 /* icon-maestro@3x.png */; }; + 95FD4DD92829533D00A7E295 /* icon-jcb@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D302829533D00A7E295 /* icon-jcb@2x.png */; }; + 95FD4DDA2829533D00A7E295 /* icon-amex@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D312829533D00A7E295 /* icon-amex@2x.png */; }; + 95FD4DDB2829533D00A7E295 /* icon-amex@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D322829533D00A7E295 /* icon-amex@3x.png */; }; + 95FD4DDC2829533D00A7E295 /* icon-jcb@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D332829533D00A7E295 /* icon-jcb@3x.png */; }; + 95FD4DDD2829533D00A7E295 /* icon-maestro@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D342829533D00A7E295 /* icon-maestro@2x.png */; }; + 95FD4DDE2829533D00A7E295 /* icon-dinersclub@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D352829533D00A7E295 /* icon-dinersclub@3x.png */; }; + 95FD4DDF2829533D00A7E295 /* icon-discover@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D362829533D00A7E295 /* icon-discover@2x.png */; }; + 95FD4DE02829533D00A7E295 /* icon-discover@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D372829533D00A7E295 /* icon-discover@3x.png */; }; + 95FD4DE12829533D00A7E295 /* icon-discover.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D382829533D00A7E295 /* icon-discover.png */; }; + 95FD4DE22829533D00A7E295 /* icon-dinersclub@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D392829533D00A7E295 /* icon-dinersclub@2x.png */; }; + 95FD4DE32829533D00A7E295 /* checkmark.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D3D2829533D00A7E295 /* checkmark.png */; }; + 95FD4DE42829533D00A7E295 /* checkmark@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D3E2829533D00A7E295 /* checkmark@2x.png */; }; + 95FD4DE52829533D00A7E295 /* checkmark@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D3F2829533D00A7E295 /* checkmark@3x.png */; }; + 95FD4DE62829533D00A7E295 /* warning.pdf in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D422829533D00A7E295 /* warning.pdf */; }; + 95FD4DE72829533D00A7E295 /* keyboard-previous@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D442829533D00A7E295 /* keyboard-previous@2x.png */; }; + 95FD4DE82829533D00A7E295 /* keyboard-next@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D452829533D00A7E295 /* keyboard-next@3x.png */; }; + 95FD4DE92829533D00A7E295 /* keyboard-next@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D462829533D00A7E295 /* keyboard-next@2x.png */; }; + 95FD4DEA2829533D00A7E295 /* keyboard-previous@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D472829533D00A7E295 /* keyboard-previous@3x.png */; }; + 95FD4DEB2829533D00A7E295 /* keyboard-down.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D482829533D00A7E295 /* keyboard-down.png */; }; + 95FD4DEC2829533D00A7E295 /* keyboard-previous.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D492829533D00A7E295 /* keyboard-previous.png */; }; + 95FD4DED2829533D00A7E295 /* keyboard-next.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D4A2829533D00A7E295 /* keyboard-next.png */; }; + 95FD4DEE2829533D00A7E295 /* keyboard-down@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D4B2829533D00A7E295 /* keyboard-down@2x.png */; }; + 95FD4DEF2829533D00A7E295 /* keyboard-down@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 95FD4D4C2829533D00A7E295 /* keyboard-down@3x.png */; }; + 95FD4DF02829533D00A7E295 /* CheckoutTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D4F2829533D00A7E295 /* CheckoutTheme.swift */; }; + 95FD4DF12829533D00A7E295 /* CheckoutSdkIos.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D502829533D00A7E295 /* CheckoutSdkIos.swift */; }; + 95FD4DF22829533D00A7E295 /* CheckoutColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 95FD4D512829533D00A7E295 /* CheckoutColor.swift */; }; CB00CA6527ECBE8B000069BE /* StubJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA1327ECBE8B000069BE /* StubJSONDecoder.swift */; }; CB00CA6627ECBE8B000069BE /* StubRequestParameterProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA1427ECBE8B000069BE /* StubRequestParameterProvider.swift */; }; CB00CA6727ECBE8B000069BE /* StubFramesEventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB00CA1527ECBE8B000069BE /* StubFramesEventLogger.swift */; }; @@ -291,100 +338,9 @@ 4422774726163716009626A0 /* iOS Example Frame.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "iOS Example Frame.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 4422775D26163748009626A0 /* Frames.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Frames.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4422775F26163748009626A0 /* Frames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Frames.h; sourceTree = ""; }; - 4422777E2616376D009626A0 /* CheckoutTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckoutTheme.swift; path = ../../Source/CheckoutTheme.swift; sourceTree = ""; }; - 442277812616376D009626A0 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; - 442277832616376D009626A0 /* icon-visa.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-visa.png"; sourceTree = ""; }; - 442277842616376D009626A0 /* icon-maestro.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-maestro.png"; sourceTree = ""; }; - 442277852616376D009626A0 /* icon-visa@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-visa@2x.png"; sourceTree = ""; }; - 442277862616376D009626A0 /* icon-mastercard@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-mastercard@2x.png"; sourceTree = ""; }; - 442277872616376D009626A0 /* icon-mastercard@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-mastercard@3x.png"; sourceTree = ""; }; - 442277882616376D009626A0 /* icon-visa@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-visa@3x.png"; sourceTree = ""; }; - 442277892616376D009626A0 /* icon-dinersclub.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-dinersclub.png"; sourceTree = ""; }; - 4422778A2616376D009626A0 /* icon-mastercard.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-mastercard.png"; sourceTree = ""; }; - 4422778B2616376D009626A0 /* icon-jcb.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-jcb.png"; sourceTree = ""; }; - 4422778C2616376D009626A0 /* icon-amex.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-amex.png"; sourceTree = ""; }; - 4422778D2616376D009626A0 /* icon-maestro@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-maestro@3x.png"; sourceTree = ""; }; - 4422778E2616376D009626A0 /* icon-jcb@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-jcb@2x.png"; sourceTree = ""; }; - 4422778F2616376D009626A0 /* icon-amex@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-amex@2x.png"; sourceTree = ""; }; - 442277902616376D009626A0 /* icon-amex@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-amex@3x.png"; sourceTree = ""; }; - 442277912616376D009626A0 /* icon-jcb@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-jcb@3x.png"; sourceTree = ""; }; - 442277922616376D009626A0 /* icon-maestro@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-maestro@2x.png"; sourceTree = ""; }; - 442277932616376D009626A0 /* icon-dinersclub@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-dinersclub@3x.png"; sourceTree = ""; }; - 442277942616376D009626A0 /* icon-discover@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-discover@2x.png"; sourceTree = ""; }; - 442277952616376D009626A0 /* icon-discover@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-discover@3x.png"; sourceTree = ""; }; - 442277962616376D009626A0 /* icon-discover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-discover.png"; sourceTree = ""; }; - 442277972616376D009626A0 /* icon-dinersclub@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-dinersclub@2x.png"; sourceTree = ""; }; - 442277982616376D009626A0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - 442277992616376D009626A0 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; - 4422779B2616376D009626A0 /* checkmark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = checkmark.png; sourceTree = ""; }; - 4422779C2616376D009626A0 /* checkmark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "checkmark@2x.png"; sourceTree = ""; }; - 4422779D2616376D009626A0 /* checkmark@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "checkmark@3x.png"; sourceTree = ""; }; - 4422779E2616376D009626A0 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; - 442277A02616376D009626A0 /* keyboard-previous@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-previous@2x.png"; sourceTree = ""; }; - 442277A12616376D009626A0 /* keyboard-next@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-next@3x.png"; sourceTree = ""; }; - 442277A22616376D009626A0 /* keyboard-next@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-next@2x.png"; sourceTree = ""; }; - 442277A32616376D009626A0 /* keyboard-previous@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-previous@3x.png"; sourceTree = ""; }; - 442277A42616376D009626A0 /* keyboard-down.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-down.png"; sourceTree = ""; }; - 442277A52616376D009626A0 /* keyboard-previous.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-previous.png"; sourceTree = ""; }; - 442277A62616376D009626A0 /* keyboard-next.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-next.png"; sourceTree = ""; }; - 442277A72616376D009626A0 /* keyboard-down@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-down@2x.png"; sourceTree = ""; }; - 442277A82616376D009626A0 /* keyboard-down@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-down@3x.png"; sourceTree = ""; }; - 442277A92616376D009626A0 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; - 442277AA2616376D009626A0 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; - 442277AC2616376E009626A0 /* CardListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardListCell.swift; sourceTree = ""; }; - 442277AD2616376E009626A0 /* ExpirationDatePicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpirationDatePicker.swift; sourceTree = ""; }; - 442277AE2616376E009626A0 /* CardListCellName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardListCellName.swift; sourceTree = ""; }; - 442277B02616376E009626A0 /* CardNumberInputViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardNumberInputViewDelegate.swift; sourceTree = ""; }; - 442277B12616376E009626A0 /* CvvConfirmationViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvConfirmationViewControllerDelegate.swift; sourceTree = ""; }; - 442277B22616376E009626A0 /* ThreedsWebViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreedsWebViewControllerDelegate.swift; sourceTree = ""; }; - 442277B32616376E009626A0 /* CountrySelectionViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountrySelectionViewControllerDelegate.swift; sourceTree = ""; }; - 442277B42616376E009626A0 /* ExpirationDatePickerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpirationDatePickerDelegate.swift; sourceTree = ""; }; - 442277B52616376E009626A0 /* CardViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardViewControllerDelegate.swift; sourceTree = ""; }; - 442277B62616376E009626A0 /* CvvInputViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvInputViewDelegate.swift; sourceTree = ""; }; - 442277B72616376E009626A0 /* AddressViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressViewControllerDelegate.swift; sourceTree = ""; }; - 442277B92616376E009626A0 /* CardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardViewController.swift; sourceTree = ""; }; - 442277BA2616376E009626A0 /* CvvConfirmationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvConfirmationViewController.swift; sourceTree = ""; }; - 442277BB2616376E009626A0 /* CountrySelectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountrySelectionViewController.swift; sourceTree = ""; }; - 442277BC2616376E009626A0 /* SimpleLoadingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleLoadingViewController.swift; sourceTree = ""; }; - 442277BD2616376E009626A0 /* ThreedsWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreedsWebViewController.swift; sourceTree = ""; }; - 442277BE2616376E009626A0 /* AddressViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressViewController.swift; sourceTree = ""; }; - 442277C02616376E009626A0 /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = ""; }; - 442277C12616376E009626A0 /* DetailsInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailsInputView.swift; sourceTree = ""; }; - 442277C22616376E009626A0 /* SchemeIconsStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemeIconsStackView.swift; sourceTree = ""; }; - 442277C32616376E009626A0 /* StandardInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StandardInputView.swift; sourceTree = ""; }; - 442277C42616376E009626A0 /* PhoneNumberInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumberInputView.swift; sourceTree = ""; }; - 442277C52616376E009626A0 /* AddressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressView.swift; sourceTree = ""; }; - 442277C62616376E009626A0 /* CardNumberInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardNumberInputView.swift; sourceTree = ""; }; - 442277C72616376E009626A0 /* CvvInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvInputView.swift; sourceTree = ""; }; - 442277C82616376E009626A0 /* ExpirationDateInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpirationDateInputView.swift; sourceTree = ""; }; - 442277CA2616376E009626A0 /* CkoPhoneNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoPhoneNumber.swift; sourceTree = ""; }; - 442277CB2616376E009626A0 /* Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = ""; }; - 442277CC2616376E009626A0 /* CardScheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardScheme.swift; sourceTree = ""; }; - 442277CD2616376E009626A0 /* CardProviderResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardProviderResponse.swift; sourceTree = ""; }; - 442277CE2616376E009626A0 /* CkoCardTokenResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoCardTokenResponse.swift; sourceTree = ""; }; - 442277CF2616376E009626A0 /* Customer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Customer.swift; sourceTree = ""; }; - 442277D02616376E009626A0 /* CardProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardProvider.swift; sourceTree = ""; }; - 442277D12616376E009626A0 /* CkoAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoAddress.swift; sourceTree = ""; }; - 442277D22616376E009626A0 /* CardType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardType.swift; sourceTree = ""; }; - 442277D32616376E009626A0 /* CustomerCardList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomerCardList.swift; sourceTree = ""; }; - 442277D42616376E009626A0 /* InputState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputState.swift; sourceTree = ""; }; - 442277D52616376E009626A0 /* CkoCardTokenRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoCardTokenRequest.swift; sourceTree = ""; }; - 442277D62616376E009626A0 /* CheckoutTokenStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckoutTokenStatus.swift; sourceTree = ""; }; - 442277D72616376E009626A0 /* ErrorResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorResponse.swift; sourceTree = ""; }; - 442277D82616376E009626A0 /* ApplePayTokenRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplePayTokenRequest.swift; sourceTree = ""; }; - 442277D92616376E009626A0 /* NetworkError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; - 442277DA2616376E009626A0 /* CustomerCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomerCard.swift; sourceTree = ""; }; - 442277DC2616376E009626A0 /* CheckoutSdkIos.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckoutSdkIos.swift; path = ../../Source/CheckoutSdkIos.swift; sourceTree = ""; }; - 442277DF2616376E009626A0 /* StringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = ""; }; - 442277E02616376E009626A0 /* UIViewControllerExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtensions.swift; sourceTree = ""; }; - 442277E12616376E009626A0 /* UIViewExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewExtensions.swift; sourceTree = ""; }; - 442277E22616376E009626A0 /* UIResponderExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIResponderExtensions.swift; sourceTree = ""; }; - 442277E32616376E009626A0 /* CardUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CardUtils.swift; path = ../../Source/CardUtils.swift; sourceTree = ""; }; 442277E52616376E009626A0 /* CheckoutSdkIos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheckoutSdkIos.h; sourceTree = ""; }; 442277E62616376E009626A0 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 442277E72616376E009626A0 /* CheckoutAPIClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckoutAPIClient.swift; path = ../../Source/CheckoutAPIClient.swift; sourceTree = ""; }; 442278B526164770009626A0 /* PhoneNumberKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PhoneNumberKit.xcframework; path = Carthage/Build/PhoneNumberKit.xcframework; sourceTree = ""; }; - 4452A1AC26FB5874006AF798 /* URLHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLHelper.swift; sourceTree = ""; }; 446D0CFE261F48F200E0032E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Main.strings; sourceTree = ""; }; 446D0D00261F492000E0032E /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Main.strings; sourceTree = ""; }; 446D0D02261F494900E0032E /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Main.strings; sourceTree = ""; }; @@ -397,36 +353,174 @@ 44A4DFBE261CA91300E0C349 /* PhoneNumberKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PhoneNumberKit.xcframework; path = ../Carthage/Build/PhoneNumberKit.xcframework; sourceTree = ""; }; 44A4DFCF261CC17800E0C349 /* Cartfile */ = {isa = PBXFileReference; lastKnownFileType = text; name = Cartfile; path = ../Cartfile; sourceTree = ""; }; 44A4DFF5261CCA7700E0C349 /* PhoneNumberKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = PhoneNumberKit.xcframework; path = ../Carthage/Build/PhoneNumberKit.xcframework; sourceTree = ""; }; - 44F095162625F7E600CB287F /* FramesLogEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramesLogEvent.swift; sourceTree = ""; }; 44F095A12629DCB700CB287F /* CheckoutEventLoggerKit.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = CheckoutEventLoggerKit.xcframework; path = ../Carthage/Build/CheckoutEventLoggerKit.xcframework; sourceTree = ""; }; - 44F095A52629DCF100CB287F /* UIDeviceExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIDeviceExtensions.swift; sourceTree = ""; }; - 57256C41269F0F81001EC3D8 /* Request.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; - 57256C42269F0F81001EC3D8 /* RequestExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestExecutor.swift; sourceTree = ""; }; - 57256C43269F0F81001EC3D8 /* HTTPMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = ""; }; - 57256C49269F0F90001EC3D8 /* DateProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateProvider.swift; sourceTree = ""; }; - 57256C4A269F0F90001EC3D8 /* TokenType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenType.swift; sourceTree = ""; }; - 57256C4C269F0F90001EC3D8 /* CorrelationIDGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CorrelationIDGenerator.swift; sourceTree = ""; }; - 57256C4D269F0F90001EC3D8 /* NetworkFlowLoggerFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkFlowLoggerFactory.swift; sourceTree = ""; }; - 57256C4E269F0F90001EC3D8 /* FramesEventLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramesEventLogger.swift; sourceTree = ""; }; - 57256C4F269F0F90001EC3D8 /* NetworkFlowLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkFlowLogger.swift; sourceTree = ""; }; - 57256C59269F0FA0001EC3D8 /* TopLevelDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopLevelDecoder.swift; sourceTree = ""; }; - 57256C5A269F0FA0001EC3D8 /* Dispatching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dispatching.swift; sourceTree = ""; }; - 57256C5B269F0FA0001EC3D8 /* TopLevelEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopLevelEncoder.swift; sourceTree = ""; }; - 57256C5C269F0FA0001EC3D8 /* ContentTypeProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTypeProviding.swift; sourceTree = ""; }; - 57256C5D269F0FA0001EC3D8 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; - 57256C65269F0FB0001EC3D8 /* JSONEncoder+TopLevelEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONEncoder+TopLevelEncoder.swift"; sourceTree = ""; }; - 57256C66269F0FB0001EC3D8 /* URL+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = ""; }; - 57256C67269F0FB0001EC3D8 /* JSONEncoder+ContentTypeProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONEncoder+ContentTypeProviding.swift"; sourceTree = ""; }; - 57256C68269F0FB0001EC3D8 /* ErrorResponse+PropertyProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ErrorResponse+PropertyProviding.swift"; sourceTree = ""; }; - 57256C69269F0FB0001EC3D8 /* DispatchQueue+Dispatching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+Dispatching.swift"; sourceTree = ""; }; - 57256C6A269F0FB0001EC3D8 /* JSONDecoder+TopLevelDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+TopLevelDecoder.swift"; sourceTree = ""; }; 57256C79269F1181001EC3D8 /* FramesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FramesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 57256DEB269FA42E001EC3D8 /* Dictionary+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+Additions.swift"; sourceTree = ""; }; - CB00CA0327EB4B27000069BE /* UIColor+PropertyProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+PropertyProviding.swift"; sourceTree = ""; }; - CB00CA0527EB51B8000069BE /* UIFont+PropertyProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+PropertyProviding.swift"; sourceTree = ""; }; - CB00CA0727EB5836000069BE /* Theme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; - CB00CA0927EB5842000069BE /* PropertyProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyProviding.swift; sourceTree = ""; }; - CB00CA0B27ECA7A1000069BE /* UIBarStyle+stringValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIBarStyle+stringValue.swift"; sourceTree = ""; }; + 95FD4C792829533D00A7E295 /* CardUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CardUtils.swift; path = ../../Source/CardUtils.swift; sourceTree = ""; }; + 95FD4C7B2829533D00A7E295 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; }; + 95FD4C7C2829533D00A7E295 /* CkoPhoneNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoPhoneNumber.swift; sourceTree = ""; }; + 95FD4C7D2829533D00A7E295 /* URLHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = URLHelper.swift; sourceTree = ""; }; + 95FD4C7E2829533D00A7E295 /* Environment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Environment.swift; sourceTree = ""; }; + 95FD4C7F2829533D00A7E295 /* TopLevelEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopLevelEncoder.swift; sourceTree = ""; }; + 95FD4C802829533D00A7E295 /* CardScheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardScheme.swift; sourceTree = ""; }; + 95FD4C812829533D00A7E295 /* CardProviderResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardProviderResponse.swift; sourceTree = ""; }; + 95FD4C822829533D00A7E295 /* TopLevelDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TopLevelDecoder.swift; sourceTree = ""; }; + 95FD4C832829533D00A7E295 /* CkoCardTokenResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoCardTokenResponse.swift; sourceTree = ""; }; + 95FD4C852829533D00A7E295 /* HTTPMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = ""; }; + 95FD4C862829533D00A7E295 /* RequestExecutor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestExecutor.swift; sourceTree = ""; }; + 95FD4C872829533D00A7E295 /* Request.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + 95FD4C882829533D00A7E295 /* Customer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Customer.swift; sourceTree = ""; }; + 95FD4C892829533D00A7E295 /* CardProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardProvider.swift; sourceTree = ""; }; + 95FD4C8A2829533D00A7E295 /* Dispatching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Dispatching.swift; sourceTree = ""; }; + 95FD4C8B2829533D00A7E295 /* CkoAddress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoAddress.swift; sourceTree = ""; }; + 95FD4C8C2829533D00A7E295 /* CardType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardType.swift; sourceTree = ""; }; + 95FD4C8D2829533D00A7E295 /* CustomerCardList.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomerCardList.swift; sourceTree = ""; }; + 95FD4C8E2829533D00A7E295 /* InputState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputState.swift; sourceTree = ""; }; + 95FD4C8F2829533D00A7E295 /* CkoCardTokenRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CkoCardTokenRequest.swift; sourceTree = ""; }; + 95FD4C902829533D00A7E295 /* CheckoutTokenStatus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CheckoutTokenStatus.swift; sourceTree = ""; }; + 95FD4C912829533D00A7E295 /* ErrorResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorResponse.swift; sourceTree = ""; }; + 95FD4C922829533D00A7E295 /* ApplePayTokenRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplePayTokenRequest.swift; sourceTree = ""; }; + 95FD4C932829533D00A7E295 /* ContentTypeProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentTypeProviding.swift; sourceTree = ""; }; + 95FD4C942829533D00A7E295 /* NetworkError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkError.swift; sourceTree = ""; }; + 95FD4C962829533D00A7E295 /* NetworkFlowLoggerFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkFlowLoggerFactory.swift; sourceTree = ""; }; + 95FD4C972829533D00A7E295 /* FramesEventLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramesEventLogger.swift; sourceTree = ""; }; + 95FD4C982829533D00A7E295 /* FramesLogEvent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FramesLogEvent.swift; sourceTree = ""; }; + 95FD4C992829533D00A7E295 /* PropertyProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyProviding.swift; sourceTree = ""; }; + 95FD4C9A2829533D00A7E295 /* DateProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateProvider.swift; sourceTree = ""; }; + 95FD4C9B2829533D00A7E295 /* TokenType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenType.swift; sourceTree = ""; }; + 95FD4C9C2829533D00A7E295 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + 95FD4C9D2829533D00A7E295 /* CorrelationIDGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CorrelationIDGenerator.swift; sourceTree = ""; }; + 95FD4C9E2829533D00A7E295 /* NetworkFlowLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkFlowLogger.swift; sourceTree = ""; }; + 95FD4C9F2829533D00A7E295 /* CustomerCard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomerCard.swift; sourceTree = ""; }; + 95FD4CA12829533D00A7E295 /* UIFont+PropertyProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIFont+PropertyProviding.swift"; sourceTree = ""; }; + 95FD4CA22829533D00A7E295 /* UIBarStyle+stringValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIBarStyle+stringValue.swift"; sourceTree = ""; }; + 95FD4CA32829533D00A7E295 /* StringExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensions.swift; sourceTree = ""; }; + 95FD4CA42829533D00A7E295 /* ErrorResponse+PropertyProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ErrorResponse+PropertyProviding.swift"; sourceTree = ""; }; + 95FD4CA52829533D00A7E295 /* DispatchQueue+Dispatching.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DispatchQueue+Dispatching.swift"; sourceTree = ""; }; + 95FD4CA62829533D00A7E295 /* JSONEncoder+ContentTypeProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONEncoder+ContentTypeProviding.swift"; sourceTree = ""; }; + 95FD4CA72829533D00A7E295 /* JSONEncoder+TopLevelEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONEncoder+TopLevelEncoder.swift"; sourceTree = ""; }; + 95FD4CA82829533D00A7E295 /* UIViewControllerExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewControllerExtensions.swift; sourceTree = ""; }; + 95FD4CA92829533D00A7E295 /* JSONDecoder+TopLevelDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "JSONDecoder+TopLevelDecoder.swift"; sourceTree = ""; }; + 95FD4CAA2829533D00A7E295 /* UIViewExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewExtensions.swift; sourceTree = ""; }; + 95FD4CAB2829533D00A7E295 /* URL+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "URL+Extensions.swift"; sourceTree = ""; }; + 95FD4CAC2829533D00A7E295 /* UIDeviceExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIDeviceExtensions.swift; sourceTree = ""; }; + 95FD4CAD2829533D00A7E295 /* UIColor+PropertyProviding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIColor+PropertyProviding.swift"; sourceTree = ""; }; + 95FD4CAE2829533D00A7E295 /* Dictionary+Additions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Dictionary+Additions.swift"; sourceTree = ""; }; + 95FD4CAF2829533D00A7E295 /* UIResponderExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIResponderExtensions.swift; sourceTree = ""; }; + 95FD4CB02829533D00A7E295 /* CheckoutAPIClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckoutAPIClient.swift; path = ../../Source/CheckoutAPIClient.swift; sourceTree = ""; }; + 95FD4CB22829533D00A7E295 /* PostCodeValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostCodeValidator.swift; sourceTree = ""; }; + 95FD4CB32829533D00A7E295 /* CountryValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountryValidator.swift; sourceTree = ""; }; + 95FD4CB42829533D00A7E295 /* PhoneNumberValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumberValidator.swift; sourceTree = ""; }; + 95FD4CB52829533D00A7E295 /* AddressLine1Validator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressLine1Validator.swift; sourceTree = ""; }; + 95FD4CB62829533D00A7E295 /* Validator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Validator.swift; sourceTree = ""; }; + 95FD4CB72829533D00A7E295 /* CityValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CityValidator.swift; sourceTree = ""; }; + 95FD4CB82829533D00A7E295 /* AddressLine2Validator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressLine2Validator.swift; sourceTree = ""; }; + 95FD4CB92829533D00A7E295 /* StateValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateValidator.swift; sourceTree = ""; }; + 95FD4CBA2829533D00A7E295 /* FullNameValidator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullNameValidator.swift; sourceTree = ""; }; + 95FD4CBC2829533D00A7E295 /* CardListCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardListCell.swift; sourceTree = ""; }; + 95FD4CC02829533D00A7E295 /* BillingFormViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormViewModel.swift; sourceTree = ""; }; + 95FD4CC12829533D00A7E295 /* DefaultBillingFormViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormViewModel.swift; sourceTree = ""; }; + 95FD4CC22829533D00A7E295 /* BillingFormCellType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormCellType.swift; sourceTree = ""; }; + 95FD4CC72829533D00A7E295 /* DefaultHintInputLabelStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultHintInputLabelStyle.swift; sourceTree = ""; }; + 95FD4CC92829533D00A7E295 /* DefaultTitleLabelStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultTitleLabelStyle.swift; sourceTree = ""; }; + 95FD4CCB2829533D00A7E295 /* DefaultTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultTextField.swift; sourceTree = ""; }; + 95FD4CCD2829533D00A7E295 /* DefaultErrorInputLabelStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultErrorInputLabelStyle.swift; sourceTree = ""; }; + 95FD4CD12829533D00A7E295 /* DefaultBillingFormPostCodeCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormPostCodeCellStyle.swift; sourceTree = ""; }; + 95FD4CD32829533D00A7E295 /* DefaultBillingFormAddressLine2CellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormAddressLine2CellStyle.swift; sourceTree = ""; }; + 95FD4CD52829533D00A7E295 /* DefaultBillingFormCityCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormCityCellStyle.swift; sourceTree = ""; }; + 95FD4CD72829533D00A7E295 /* DefaultBillingFormFullNameCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormFullNameCellStyle.swift; sourceTree = ""; }; + 95FD4CD92829533D00A7E295 /* DefaultBillingFormStateCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormStateCellStyle.swift; sourceTree = ""; }; + 95FD4CDB2829533D00A7E295 /* DefaultBillingFormPhoneNumberCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormPhoneNumberCellStyle.swift; sourceTree = ""; }; + 95FD4CDD2829533D00A7E295 /* DefaultBillingFormAddressLine1CellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormAddressLine1CellStyle.swift; sourceTree = ""; }; + 95FD4CDF2829533D00A7E295 /* DefaultBillingFormCountryCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormCountryCellStyle.swift; sourceTree = ""; }; + 95FD4CE12829533D00A7E295 /* DefaultBillingFormStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormStyle.swift; sourceTree = ""; }; + 95FD4CE42829533D00A7E295 /* DefaultCancelButtonFormStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultCancelButtonFormStyle.swift; sourceTree = ""; }; + 95FD4CE62829533D00A7E295 /* DefaultHeaderLabelFormStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultHeaderLabelFormStyle.swift; sourceTree = ""; }; + 95FD4CE82829533D00A7E295 /* DefaultDoneFormButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultDoneFormButtonStyle.swift; sourceTree = ""; }; + 95FD4CEA2829533D00A7E295 /* DefaultBillingFormHeaderCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultBillingFormHeaderCellStyle.swift; sourceTree = ""; }; + 95FD4CEC2829533D00A7E295 /* BillingFormTextFieldCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormTextFieldCellStyle.swift; sourceTree = ""; }; + 95FD4CED2829533D00A7E295 /* BillingFormHeaderCellStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormHeaderCellStyle.swift; sourceTree = ""; }; + 95FD4CEF2829533D00A7E295 /* BillingFormStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormStyle.swift; sourceTree = ""; }; + 95FD4CF02829533D00A7E295 /* FormButtonStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormButtonStyle.swift; sourceTree = ""; }; + 95FD4CF12829533D00A7E295 /* InputLabelStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputLabelStyle.swift; sourceTree = ""; }; + 95FD4CF22829533D00A7E295 /* FormTextFieldStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FormTextFieldStyle.swift; sourceTree = ""; }; + 95FD4CF32829533D00A7E295 /* ErrorInputLabelStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorInputLabelStyle.swift; sourceTree = ""; }; + 95FD4CF62829533D00A7E295 /* BillingFormTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormTextField.swift; sourceTree = ""; }; + 95FD4CF72829533D00A7E295 /* BillingFormTextFieldView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormTextFieldView.swift; sourceTree = ""; }; + 95FD4CF82829533D00A7E295 /* BillingFormPhoneNumberText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormPhoneNumberText.swift; sourceTree = ""; }; + 95FD4CFB2829533D00A7E295 /* BillingFormTextFieldCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormTextFieldCell.swift; sourceTree = ""; }; + 95FD4CFD2829533D00A7E295 /* BillingFormHeaderCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormHeaderCell.swift; sourceTree = ""; }; + 95FD4CFF2829533D00A7E295 /* BillingFormTextFieldErrorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormTextFieldErrorView.swift; sourceTree = ""; }; + 95FD4D012829533D00A7E295 /* BillingFormViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormViewController.swift; sourceTree = ""; }; + 95FD4D032829533D00A7E295 /* BillingFormFactory.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BillingFormFactory.swift; sourceTree = ""; }; + 95FD4D042829533D00A7E295 /* ExpirationDatePicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpirationDatePicker.swift; sourceTree = ""; }; + 95FD4D052829533D00A7E295 /* CardListCellName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardListCellName.swift; sourceTree = ""; }; + 95FD4D062829533D00A7E295 /* UITableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITableView.swift; sourceTree = ""; }; + 95FD4D082829533D00A7E295 /* CardNumberInputViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardNumberInputViewDelegate.swift; sourceTree = ""; }; + 95FD4D092829533D00A7E295 /* CvvConfirmationViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvConfirmationViewControllerDelegate.swift; sourceTree = ""; }; + 95FD4D0A2829533D00A7E295 /* ThreedsWebViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreedsWebViewControllerDelegate.swift; sourceTree = ""; }; + 95FD4D0B2829533D00A7E295 /* CountrySelectionViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountrySelectionViewControllerDelegate.swift; sourceTree = ""; }; + 95FD4D0C2829533D00A7E295 /* ExpirationDatePickerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpirationDatePickerDelegate.swift; sourceTree = ""; }; + 95FD4D0D2829533D00A7E295 /* CardViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardViewControllerDelegate.swift; sourceTree = ""; }; + 95FD4D0E2829533D00A7E295 /* CvvInputViewDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvInputViewDelegate.swift; sourceTree = ""; }; + 95FD4D0F2829533D00A7E295 /* AddressViewControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressViewControllerDelegate.swift; sourceTree = ""; }; + 95FD4D112829533D00A7E295 /* CardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardViewController.swift; sourceTree = ""; }; + 95FD4D122829533D00A7E295 /* CvvConfirmationViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvConfirmationViewController.swift; sourceTree = ""; }; + 95FD4D132829533D00A7E295 /* CountrySelectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CountrySelectionViewController.swift; sourceTree = ""; }; + 95FD4D142829533D00A7E295 /* SimpleLoadingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SimpleLoadingViewController.swift; sourceTree = ""; }; + 95FD4D152829533D00A7E295 /* ThreedsWebViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThreedsWebViewController.swift; sourceTree = ""; }; + 95FD4D162829533D00A7E295 /* AddressViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressViewController.swift; sourceTree = ""; }; + 95FD4D182829533D00A7E295 /* CardView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardView.swift; sourceTree = ""; }; + 95FD4D192829533D00A7E295 /* DetailsInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DetailsInputView.swift; sourceTree = ""; }; + 95FD4D1A2829533D00A7E295 /* SchemeIconsStackView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SchemeIconsStackView.swift; sourceTree = ""; }; + 95FD4D1B2829533D00A7E295 /* StandardInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StandardInputView.swift; sourceTree = ""; }; + 95FD4D1C2829533D00A7E295 /* PhoneNumberInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumberInputView.swift; sourceTree = ""; }; + 95FD4D1D2829533D00A7E295 /* AddressView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressView.swift; sourceTree = ""; }; + 95FD4D1E2829533D00A7E295 /* CardNumberInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardNumberInputView.swift; sourceTree = ""; }; + 95FD4D1F2829533D00A7E295 /* CvvInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CvvInputView.swift; sourceTree = ""; }; + 95FD4D202829533D00A7E295 /* ExpirationDateInputView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExpirationDateInputView.swift; sourceTree = ""; }; + 95FD4D232829533D00A7E295 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; + 95FD4D252829533D00A7E295 /* icon-visa.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-visa.png"; sourceTree = ""; }; + 95FD4D262829533D00A7E295 /* icon-maestro.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-maestro.png"; sourceTree = ""; }; + 95FD4D272829533D00A7E295 /* icon-visa@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-visa@2x.png"; sourceTree = ""; }; + 95FD4D282829533D00A7E295 /* icon-mastercard@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-mastercard@2x.png"; sourceTree = ""; }; + 95FD4D292829533D00A7E295 /* icon-mastercard@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-mastercard@3x.png"; sourceTree = ""; }; + 95FD4D2A2829533D00A7E295 /* icon-visa@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-visa@3x.png"; sourceTree = ""; }; + 95FD4D2B2829533D00A7E295 /* icon-dinersclub.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-dinersclub.png"; sourceTree = ""; }; + 95FD4D2C2829533D00A7E295 /* icon-mastercard.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-mastercard.png"; sourceTree = ""; }; + 95FD4D2D2829533D00A7E295 /* icon-jcb.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-jcb.png"; sourceTree = ""; }; + 95FD4D2E2829533D00A7E295 /* icon-amex.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-amex.png"; sourceTree = ""; }; + 95FD4D2F2829533D00A7E295 /* icon-maestro@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-maestro@3x.png"; sourceTree = ""; }; + 95FD4D302829533D00A7E295 /* icon-jcb@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-jcb@2x.png"; sourceTree = ""; }; + 95FD4D312829533D00A7E295 /* icon-amex@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-amex@2x.png"; sourceTree = ""; }; + 95FD4D322829533D00A7E295 /* icon-amex@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-amex@3x.png"; sourceTree = ""; }; + 95FD4D332829533D00A7E295 /* icon-jcb@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-jcb@3x.png"; sourceTree = ""; }; + 95FD4D342829533D00A7E295 /* icon-maestro@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-maestro@2x.png"; sourceTree = ""; }; + 95FD4D352829533D00A7E295 /* icon-dinersclub@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-dinersclub@3x.png"; sourceTree = ""; }; + 95FD4D362829533D00A7E295 /* icon-discover@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-discover@2x.png"; sourceTree = ""; }; + 95FD4D372829533D00A7E295 /* icon-discover@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-discover@3x.png"; sourceTree = ""; }; + 95FD4D382829533D00A7E295 /* icon-discover.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-discover.png"; sourceTree = ""; }; + 95FD4D392829533D00A7E295 /* icon-dinersclub@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-dinersclub@2x.png"; sourceTree = ""; }; + 95FD4D3A2829533D00A7E295 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + 95FD4D3B2829533D00A7E295 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; + 95FD4D3D2829533D00A7E295 /* checkmark.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = checkmark.png; sourceTree = ""; }; + 95FD4D3E2829533D00A7E295 /* checkmark@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "checkmark@2x.png"; sourceTree = ""; }; + 95FD4D3F2829533D00A7E295 /* checkmark@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "checkmark@3x.png"; sourceTree = ""; }; + 95FD4D402829533D00A7E295 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = ""; }; + 95FD4D422829533D00A7E295 /* warning.pdf */ = {isa = PBXFileReference; lastKnownFileType = image.pdf; path = warning.pdf; sourceTree = ""; }; + 95FD4D442829533D00A7E295 /* keyboard-previous@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-previous@2x.png"; sourceTree = ""; }; + 95FD4D452829533D00A7E295 /* keyboard-next@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-next@3x.png"; sourceTree = ""; }; + 95FD4D462829533D00A7E295 /* keyboard-next@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-next@2x.png"; sourceTree = ""; }; + 95FD4D472829533D00A7E295 /* keyboard-previous@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-previous@3x.png"; sourceTree = ""; }; + 95FD4D482829533D00A7E295 /* keyboard-down.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-down.png"; sourceTree = ""; }; + 95FD4D492829533D00A7E295 /* keyboard-previous.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-previous.png"; sourceTree = ""; }; + 95FD4D4A2829533D00A7E295 /* keyboard-next.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-next.png"; sourceTree = ""; }; + 95FD4D4B2829533D00A7E295 /* keyboard-down@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-down@2x.png"; sourceTree = ""; }; + 95FD4D4C2829533D00A7E295 /* keyboard-down@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keyboard-down@3x.png"; sourceTree = ""; }; + 95FD4D4D2829533D00A7E295 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; + 95FD4D4E2829533D00A7E295 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; + 95FD4D4F2829533D00A7E295 /* CheckoutTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckoutTheme.swift; path = ../../Source/CheckoutTheme.swift; sourceTree = ""; }; + 95FD4D502829533D00A7E295 /* CheckoutSdkIos.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckoutSdkIos.swift; path = ../../Source/CheckoutSdkIos.swift; sourceTree = ""; }; + 95FD4D512829533D00A7E295 /* CheckoutColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CheckoutColor.swift; path = ../../Source/CheckoutColor.swift; sourceTree = ""; }; CB00CA1327ECBE8B000069BE /* StubJSONDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StubJSONDecoder.swift; sourceTree = ""; }; CB00CA1427ECBE8B000069BE /* StubRequestParameterProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StubRequestParameterProvider.swift; sourceTree = ""; }; CB00CA1527ECBE8B000069BE /* StubFramesEventLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StubFramesEventLogger.swift; sourceTree = ""; }; @@ -552,245 +646,597 @@ 4422775E26163748009626A0 /* Frames */ = { isa = PBXGroup; children = ( - 442277E32616376E009626A0 /* CardUtils.swift */, - 442277E72616376E009626A0 /* CheckoutAPIClient.swift */, - 442277DC2616376E009626A0 /* CheckoutSdkIos.swift */, - 4422777E2616376D009626A0 /* CheckoutTheme.swift */, - 442277C92616376E009626A0 /* Core */, - 442277DE2616376E009626A0 /* Extensions */, - 4422777F2616376D009626A0 /* Resources */, + 95FD4C792829533D00A7E295 /* CardUtils.swift */, + 95FD4CB02829533D00A7E295 /* CheckoutAPIClient.swift */, + 95FD4D512829533D00A7E295 /* CheckoutColor.swift */, + 95FD4D502829533D00A7E295 /* CheckoutSdkIos.swift */, + 95FD4D4F2829533D00A7E295 /* CheckoutTheme.swift */, + 95FD4C7A2829533D00A7E295 /* Core */, + 95FD4CA02829533D00A7E295 /* Extensions */, + 95FD4D212829533D00A7E295 /* Resources */, + 95FD4CBB2829533D00A7E295 /* UI */, + 95FD4CB12829533D00A7E295 /* Validator */, 442277E42616376E009626A0 /* Suppporting Files */, - 442277AB2616376E009626A0 /* UI */, 4422775F26163748009626A0 /* Frames.h */, ); path = Frames; sourceTree = ""; }; - 4422777F2616376D009626A0 /* Resources */ = { + 442277E42616376E009626A0 /* Suppporting Files */ = { isa = PBXGroup; children = ( - 442277802616376D009626A0 /* Localizable.strings */, - 442277822616376D009626A0 /* schemes */, - 4422779A2616376D009626A0 /* checkmarks */, - 4422779F2616376D009626A0 /* arrows */, + 442277E52616376E009626A0 /* CheckoutSdkIos.h */, + 442277E62616376E009626A0 /* Info.plist */, ); - name = Resources; - path = ../../Source/Resources; + name = "Suppporting Files"; + path = "../../Source/Suppporting Files"; sourceTree = ""; }; - 442277822616376D009626A0 /* schemes */ = { - isa = PBXGroup; - children = ( - 442277832616376D009626A0 /* icon-visa.png */, - 442277842616376D009626A0 /* icon-maestro.png */, - 442277852616376D009626A0 /* icon-visa@2x.png */, - 442277862616376D009626A0 /* icon-mastercard@2x.png */, - 442277872616376D009626A0 /* icon-mastercard@3x.png */, - 442277882616376D009626A0 /* icon-visa@3x.png */, - 442277892616376D009626A0 /* icon-dinersclub.png */, - 4422778A2616376D009626A0 /* icon-mastercard.png */, - 4422778B2616376D009626A0 /* icon-jcb.png */, - 4422778C2616376D009626A0 /* icon-amex.png */, - 4422778D2616376D009626A0 /* icon-maestro@3x.png */, - 4422778E2616376D009626A0 /* icon-jcb@2x.png */, - 4422778F2616376D009626A0 /* icon-amex@2x.png */, - 442277902616376D009626A0 /* icon-amex@3x.png */, - 442277912616376D009626A0 /* icon-jcb@3x.png */, - 442277922616376D009626A0 /* icon-maestro@2x.png */, - 442277932616376D009626A0 /* icon-dinersclub@3x.png */, - 442277942616376D009626A0 /* icon-discover@2x.png */, - 442277952616376D009626A0 /* icon-discover@3x.png */, - 442277962616376D009626A0 /* icon-discover.png */, - 442277972616376D009626A0 /* icon-dinersclub@2x.png */, + 443FCD9226137A4C009D6DE6 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 44F095A12629DCB700CB287F /* CheckoutEventLoggerKit.xcframework */, + 44796B4B262F2BC100F28C6E /* CheckoutEventLoggerKit.xcframework */, + 44A4DFBE261CA91300E0C349 /* PhoneNumberKit.xcframework */, + 442278B526164770009626A0 /* PhoneNumberKit.xcframework */, ); - path = schemes; + name = Frameworks; sourceTree = ""; }; - 4422779A2616376D009626A0 /* checkmarks */ = { + 95FD4C7A2829533D00A7E295 /* Core */ = { isa = PBXGroup; children = ( - 4422779B2616376D009626A0 /* checkmark.png */, - 4422779C2616376D009626A0 /* checkmark@2x.png */, - 4422779D2616376D009626A0 /* checkmark@3x.png */, + 95FD4C7B2829533D00A7E295 /* Constants.swift */, + 95FD4C7C2829533D00A7E295 /* CkoPhoneNumber.swift */, + 95FD4C7D2829533D00A7E295 /* URLHelper.swift */, + 95FD4C7E2829533D00A7E295 /* Environment.swift */, + 95FD4C7F2829533D00A7E295 /* TopLevelEncoder.swift */, + 95FD4C802829533D00A7E295 /* CardScheme.swift */, + 95FD4C812829533D00A7E295 /* CardProviderResponse.swift */, + 95FD4C822829533D00A7E295 /* TopLevelDecoder.swift */, + 95FD4C832829533D00A7E295 /* CkoCardTokenResponse.swift */, + 95FD4C842829533D00A7E295 /* Networking */, + 95FD4C882829533D00A7E295 /* Customer.swift */, + 95FD4C892829533D00A7E295 /* CardProvider.swift */, + 95FD4C8A2829533D00A7E295 /* Dispatching.swift */, + 95FD4C8B2829533D00A7E295 /* CkoAddress.swift */, + 95FD4C8C2829533D00A7E295 /* CardType.swift */, + 95FD4C8D2829533D00A7E295 /* CustomerCardList.swift */, + 95FD4C8E2829533D00A7E295 /* InputState.swift */, + 95FD4C8F2829533D00A7E295 /* CkoCardTokenRequest.swift */, + 95FD4C902829533D00A7E295 /* CheckoutTokenStatus.swift */, + 95FD4C912829533D00A7E295 /* ErrorResponse.swift */, + 95FD4C922829533D00A7E295 /* ApplePayTokenRequest.swift */, + 95FD4C932829533D00A7E295 /* ContentTypeProviding.swift */, + 95FD4C942829533D00A7E295 /* NetworkError.swift */, + 95FD4C952829533D00A7E295 /* Logging */, + 95FD4C9F2829533D00A7E295 /* CustomerCard.swift */, ); - path = checkmarks; + name = Core; + path = ../../Source/Core; sourceTree = ""; }; - 4422779F2616376D009626A0 /* arrows */ = { + 95FD4C842829533D00A7E295 /* Networking */ = { isa = PBXGroup; children = ( - 442277A02616376D009626A0 /* keyboard-previous@2x.png */, - 442277A12616376D009626A0 /* keyboard-next@3x.png */, - 442277A22616376D009626A0 /* keyboard-next@2x.png */, - 442277A32616376D009626A0 /* keyboard-previous@3x.png */, - 442277A42616376D009626A0 /* keyboard-down.png */, - 442277A52616376D009626A0 /* keyboard-previous.png */, - 442277A62616376D009626A0 /* keyboard-next.png */, - 442277A72616376D009626A0 /* keyboard-down@2x.png */, - 442277A82616376D009626A0 /* keyboard-down@3x.png */, + 95FD4C852829533D00A7E295 /* HTTPMethod.swift */, + 95FD4C862829533D00A7E295 /* RequestExecutor.swift */, + 95FD4C872829533D00A7E295 /* Request.swift */, ); - path = arrows; + path = Networking; sourceTree = ""; }; - 442277AB2616376E009626A0 /* UI */ = { + 95FD4C952829533D00A7E295 /* Logging */ = { isa = PBXGroup; children = ( - 442277AC2616376E009626A0 /* CardListCell.swift */, - 442277AD2616376E009626A0 /* ExpirationDatePicker.swift */, - 442277AE2616376E009626A0 /* CardListCellName.swift */, - 442277AF2616376E009626A0 /* Delegates */, - 442277B82616376E009626A0 /* Controllers */, - 442277BF2616376E009626A0 /* Views */, + 95FD4C962829533D00A7E295 /* NetworkFlowLoggerFactory.swift */, + 95FD4C972829533D00A7E295 /* FramesEventLogger.swift */, + 95FD4C982829533D00A7E295 /* FramesLogEvent.swift */, + 95FD4C992829533D00A7E295 /* PropertyProviding.swift */, + 95FD4C9A2829533D00A7E295 /* DateProvider.swift */, + 95FD4C9B2829533D00A7E295 /* TokenType.swift */, + 95FD4C9C2829533D00A7E295 /* Theme.swift */, + 95FD4C9D2829533D00A7E295 /* CorrelationIDGenerator.swift */, + 95FD4C9E2829533D00A7E295 /* NetworkFlowLogger.swift */, + ); + path = Logging; + sourceTree = ""; + }; + 95FD4CA02829533D00A7E295 /* Extensions */ = { + isa = PBXGroup; + children = ( + 95FD4CA12829533D00A7E295 /* UIFont+PropertyProviding.swift */, + 95FD4CA22829533D00A7E295 /* UIBarStyle+stringValue.swift */, + 95FD4CA32829533D00A7E295 /* StringExtensions.swift */, + 95FD4CA42829533D00A7E295 /* ErrorResponse+PropertyProviding.swift */, + 95FD4CA52829533D00A7E295 /* DispatchQueue+Dispatching.swift */, + 95FD4CA62829533D00A7E295 /* JSONEncoder+ContentTypeProviding.swift */, + 95FD4CA72829533D00A7E295 /* JSONEncoder+TopLevelEncoder.swift */, + 95FD4CA82829533D00A7E295 /* UIViewControllerExtensions.swift */, + 95FD4CA92829533D00A7E295 /* JSONDecoder+TopLevelDecoder.swift */, + 95FD4CAA2829533D00A7E295 /* UIViewExtensions.swift */, + 95FD4CAB2829533D00A7E295 /* URL+Extensions.swift */, + 95FD4CAC2829533D00A7E295 /* UIDeviceExtensions.swift */, + 95FD4CAD2829533D00A7E295 /* UIColor+PropertyProviding.swift */, + 95FD4CAE2829533D00A7E295 /* Dictionary+Additions.swift */, + 95FD4CAF2829533D00A7E295 /* UIResponderExtensions.swift */, + ); + name = Extensions; + path = ../../Source/Extensions; + sourceTree = ""; + }; + 95FD4CB12829533D00A7E295 /* Validator */ = { + isa = PBXGroup; + children = ( + 95FD4CB22829533D00A7E295 /* PostCodeValidator.swift */, + 95FD4CB32829533D00A7E295 /* CountryValidator.swift */, + 95FD4CB42829533D00A7E295 /* PhoneNumberValidator.swift */, + 95FD4CB52829533D00A7E295 /* AddressLine1Validator.swift */, + 95FD4CB62829533D00A7E295 /* Validator.swift */, + 95FD4CB72829533D00A7E295 /* CityValidator.swift */, + 95FD4CB82829533D00A7E295 /* AddressLine2Validator.swift */, + 95FD4CB92829533D00A7E295 /* StateValidator.swift */, + 95FD4CBA2829533D00A7E295 /* FullNameValidator.swift */, + ); + name = Validator; + path = ../../Source/Validator; + sourceTree = ""; + }; + 95FD4CBB2829533D00A7E295 /* UI */ = { + isa = PBXGroup; + children = ( + 95FD4CBC2829533D00A7E295 /* CardListCell.swift */, + 95FD4CBD2829533D00A7E295 /* NewUI */, + 95FD4D042829533D00A7E295 /* ExpirationDatePicker.swift */, + 95FD4D052829533D00A7E295 /* CardListCellName.swift */, + 95FD4D062829533D00A7E295 /* UITableView.swift */, + 95FD4D072829533D00A7E295 /* Delegates */, + 95FD4D102829533D00A7E295 /* Controllers */, + 95FD4D172829533D00A7E295 /* Views */, ); name = UI; path = ../../Source/UI; sourceTree = ""; }; - 442277AF2616376E009626A0 /* Delegates */ = { + 95FD4CBD2829533D00A7E295 /* NewUI */ = { isa = PBXGroup; children = ( - 442277B02616376E009626A0 /* CardNumberInputViewDelegate.swift */, - 442277B12616376E009626A0 /* CvvConfirmationViewControllerDelegate.swift */, - 442277B22616376E009626A0 /* ThreedsWebViewControllerDelegate.swift */, - 442277B32616376E009626A0 /* CountrySelectionViewControllerDelegate.swift */, - 442277B42616376E009626A0 /* ExpirationDatePickerDelegate.swift */, - 442277B52616376E009626A0 /* CardViewControllerDelegate.swift */, - 442277B62616376E009626A0 /* CvvInputViewDelegate.swift */, - 442277B72616376E009626A0 /* AddressViewControllerDelegate.swift */, + 95FD4CBE2829533D00A7E295 /* BillingForm */, ); - path = Delegates; + path = NewUI; sourceTree = ""; }; - 442277B82616376E009626A0 /* Controllers */ = { + 95FD4CBE2829533D00A7E295 /* BillingForm */ = { isa = PBXGroup; children = ( - 442277B92616376E009626A0 /* CardViewController.swift */, - 442277BA2616376E009626A0 /* CvvConfirmationViewController.swift */, - 442277BB2616376E009626A0 /* CountrySelectionViewController.swift */, - 442277BC2616376E009626A0 /* SimpleLoadingViewController.swift */, - 442277BD2616376E009626A0 /* ThreedsWebViewController.swift */, - 442277BE2616376E009626A0 /* AddressViewController.swift */, + 95FD4CBF2829533D00A7E295 /* ViewModel */, + 95FD4CC32829533D00A7E295 /* Style */, + 95FD4CF42829533D00A7E295 /* View */, + 95FD4D002829533D00A7E295 /* ViewController */, + 95FD4D022829533D00A7E295 /* Factory */, ); - path = Controllers; + path = BillingForm; sourceTree = ""; }; - 442277BF2616376E009626A0 /* Views */ = { + 95FD4CBF2829533D00A7E295 /* ViewModel */ = { isa = PBXGroup; children = ( - 442277C02616376E009626A0 /* CardView.swift */, - 442277C12616376E009626A0 /* DetailsInputView.swift */, - 442277C22616376E009626A0 /* SchemeIconsStackView.swift */, - 442277C32616376E009626A0 /* StandardInputView.swift */, - 442277C42616376E009626A0 /* PhoneNumberInputView.swift */, - 442277C52616376E009626A0 /* AddressView.swift */, - 442277C62616376E009626A0 /* CardNumberInputView.swift */, - 442277C72616376E009626A0 /* CvvInputView.swift */, - 442277C82616376E009626A0 /* ExpirationDateInputView.swift */, + 95FD4CC02829533D00A7E295 /* BillingFormViewModel.swift */, + 95FD4CC12829533D00A7E295 /* DefaultBillingFormViewModel.swift */, + 95FD4CC22829533D00A7E295 /* BillingFormCellType.swift */, ); - path = Views; + path = ViewModel; sourceTree = ""; }; - 442277C92616376E009626A0 /* Core */ = { - isa = PBXGroup; - children = ( - 57256C40269F0F6C001EC3D8 /* Networking */, - 44F095152625F7E600CB287F /* Logging */, - 442277CA2616376E009626A0 /* CkoPhoneNumber.swift */, - 442277CB2616376E009626A0 /* Environment.swift */, - 442277CC2616376E009626A0 /* CardScheme.swift */, - 442277CD2616376E009626A0 /* CardProviderResponse.swift */, - 57256C5D269F0FA0001EC3D8 /* Constants.swift */, - 4452A1AC26FB5874006AF798 /* URLHelper.swift */, - 57256C5C269F0FA0001EC3D8 /* ContentTypeProviding.swift */, - 57256C5A269F0FA0001EC3D8 /* Dispatching.swift */, - 57256C59269F0FA0001EC3D8 /* TopLevelDecoder.swift */, - 57256C5B269F0FA0001EC3D8 /* TopLevelEncoder.swift */, - 442277CE2616376E009626A0 /* CkoCardTokenResponse.swift */, - 442277CF2616376E009626A0 /* Customer.swift */, - 442277D02616376E009626A0 /* CardProvider.swift */, - 442277D12616376E009626A0 /* CkoAddress.swift */, - 442277D22616376E009626A0 /* CardType.swift */, - 442277D32616376E009626A0 /* CustomerCardList.swift */, - 442277D42616376E009626A0 /* InputState.swift */, - 442277D52616376E009626A0 /* CkoCardTokenRequest.swift */, - 442277D62616376E009626A0 /* CheckoutTokenStatus.swift */, - 442277D72616376E009626A0 /* ErrorResponse.swift */, - 442277D82616376E009626A0 /* ApplePayTokenRequest.swift */, - 442277D92616376E009626A0 /* NetworkError.swift */, - 442277DA2616376E009626A0 /* CustomerCard.swift */, + 95FD4CC32829533D00A7E295 /* Style */ = { + isa = PBXGroup; + children = ( + 95FD4CC42829533D00A7E295 /* Default Implementation */, + 95FD4CEB2829533D00A7E295 /* Cell */, + 95FD4CEE2829533D00A7E295 /* Protocols */, ); - name = Core; - path = ../../Source/Core; + path = Style; sourceTree = ""; }; - 442277DE2616376E009626A0 /* Extensions */ = { + 95FD4CC42829533D00A7E295 /* Default Implementation */ = { isa = PBXGroup; children = ( - 57256DEB269FA42E001EC3D8 /* Dictionary+Additions.swift */, - 57256C69269F0FB0001EC3D8 /* DispatchQueue+Dispatching.swift */, - 57256C68269F0FB0001EC3D8 /* ErrorResponse+PropertyProviding.swift */, - 57256C6A269F0FB0001EC3D8 /* JSONDecoder+TopLevelDecoder.swift */, - 57256C67269F0FB0001EC3D8 /* JSONEncoder+ContentTypeProviding.swift */, - 57256C65269F0FB0001EC3D8 /* JSONEncoder+TopLevelEncoder.swift */, - 57256C66269F0FB0001EC3D8 /* URL+Extensions.swift */, - 44F095A52629DCF100CB287F /* UIDeviceExtensions.swift */, - 442277DF2616376E009626A0 /* StringExtensions.swift */, - 442277E02616376E009626A0 /* UIViewControllerExtensions.swift */, - 442277E12616376E009626A0 /* UIViewExtensions.swift */, - 442277E22616376E009626A0 /* UIResponderExtensions.swift */, - CB00CA0327EB4B27000069BE /* UIColor+PropertyProviding.swift */, - CB00CA0527EB51B8000069BE /* UIFont+PropertyProviding.swift */, - CB00CA0B27ECA7A1000069BE /* UIBarStyle+stringValue.swift */, + 95FD4CC52829533D00A7E295 /* Elements */, + 95FD4CCE2829533D00A7E295 /* BillingForm */, ); - name = Extensions; - path = ../../Source/Extensions; + path = "Default Implementation"; sourceTree = ""; }; - 442277E42616376E009626A0 /* Suppporting Files */ = { + 95FD4CC52829533D00A7E295 /* Elements */ = { isa = PBXGroup; children = ( - 442277E52616376E009626A0 /* CheckoutSdkIos.h */, - 442277E62616376E009626A0 /* Info.plist */, + 95FD4CC62829533D00A7E295 /* Hint */, + 95FD4CC82829533D00A7E295 /* Title */, + 95FD4CCA2829533D00A7E295 /* TextField */, + 95FD4CCC2829533D00A7E295 /* Error */, ); - name = "Suppporting Files"; - path = "../../Source/Suppporting Files"; + path = Elements; sourceTree = ""; }; - 443FCD9226137A4C009D6DE6 /* Frameworks */ = { + 95FD4CC62829533D00A7E295 /* Hint */ = { isa = PBXGroup; children = ( - 44F095A12629DCB700CB287F /* CheckoutEventLoggerKit.xcframework */, - 44796B4B262F2BC100F28C6E /* CheckoutEventLoggerKit.xcframework */, - 44A4DFBE261CA91300E0C349 /* PhoneNumberKit.xcframework */, - 442278B526164770009626A0 /* PhoneNumberKit.xcframework */, + 95FD4CC72829533D00A7E295 /* DefaultHintInputLabelStyle.swift */, ); - name = Frameworks; + path = Hint; sourceTree = ""; }; - 44F095152625F7E600CB287F /* Logging */ = { + 95FD4CC82829533D00A7E295 /* Title */ = { isa = PBXGroup; children = ( - 57256C4C269F0F90001EC3D8 /* CorrelationIDGenerator.swift */, - 57256C49269F0F90001EC3D8 /* DateProvider.swift */, - 57256C4E269F0F90001EC3D8 /* FramesEventLogger.swift */, - 57256C4F269F0F90001EC3D8 /* NetworkFlowLogger.swift */, - 57256C4D269F0F90001EC3D8 /* NetworkFlowLoggerFactory.swift */, - 57256C4A269F0F90001EC3D8 /* TokenType.swift */, - 44F095162625F7E600CB287F /* FramesLogEvent.swift */, - CB00CA0727EB5836000069BE /* Theme.swift */, - CB00CA0927EB5842000069BE /* PropertyProviding.swift */, + 95FD4CC92829533D00A7E295 /* DefaultTitleLabelStyle.swift */, ); - path = Logging; + path = Title; sourceTree = ""; }; - 57256C40269F0F6C001EC3D8 /* Networking */ = { + 95FD4CCA2829533D00A7E295 /* TextField */ = { isa = PBXGroup; children = ( - 57256C43269F0F81001EC3D8 /* HTTPMethod.swift */, - 57256C41269F0F81001EC3D8 /* Request.swift */, - 57256C42269F0F81001EC3D8 /* RequestExecutor.swift */, + 95FD4CCB2829533D00A7E295 /* DefaultTextField.swift */, ); - path = Networking; + path = TextField; + sourceTree = ""; + }; + 95FD4CCC2829533D00A7E295 /* Error */ = { + isa = PBXGroup; + children = ( + 95FD4CCD2829533D00A7E295 /* DefaultErrorInputLabelStyle.swift */, + ); + path = Error; + sourceTree = ""; + }; + 95FD4CCE2829533D00A7E295 /* BillingForm */ = { + isa = PBXGroup; + children = ( + 95FD4CCF2829533D00A7E295 /* Fields */, + 95FD4CE02829533D00A7E295 /* Main */, + 95FD4CE22829533D00A7E295 /* Header */, + ); + path = BillingForm; + sourceTree = ""; + }; + 95FD4CCF2829533D00A7E295 /* Fields */ = { + isa = PBXGroup; + children = ( + 95FD4CD02829533D00A7E295 /* Postcode */, + 95FD4CD22829533D00A7E295 /* AddressLine2 */, + 95FD4CD42829533D00A7E295 /* City */, + 95FD4CD62829533D00A7E295 /* FullName */, + 95FD4CD82829533D00A7E295 /* State */, + 95FD4CDA2829533D00A7E295 /* PhoneNumber */, + 95FD4CDC2829533D00A7E295 /* AddressLine1 */, + 95FD4CDE2829533D00A7E295 /* Country */, + ); + path = Fields; + sourceTree = ""; + }; + 95FD4CD02829533D00A7E295 /* Postcode */ = { + isa = PBXGroup; + children = ( + 95FD4CD12829533D00A7E295 /* DefaultBillingFormPostCodeCellStyle.swift */, + ); + path = Postcode; + sourceTree = ""; + }; + 95FD4CD22829533D00A7E295 /* AddressLine2 */ = { + isa = PBXGroup; + children = ( + 95FD4CD32829533D00A7E295 /* DefaultBillingFormAddressLine2CellStyle.swift */, + ); + path = AddressLine2; + sourceTree = ""; + }; + 95FD4CD42829533D00A7E295 /* City */ = { + isa = PBXGroup; + children = ( + 95FD4CD52829533D00A7E295 /* DefaultBillingFormCityCellStyle.swift */, + ); + path = City; + sourceTree = ""; + }; + 95FD4CD62829533D00A7E295 /* FullName */ = { + isa = PBXGroup; + children = ( + 95FD4CD72829533D00A7E295 /* DefaultBillingFormFullNameCellStyle.swift */, + ); + path = FullName; + sourceTree = ""; + }; + 95FD4CD82829533D00A7E295 /* State */ = { + isa = PBXGroup; + children = ( + 95FD4CD92829533D00A7E295 /* DefaultBillingFormStateCellStyle.swift */, + ); + path = State; + sourceTree = ""; + }; + 95FD4CDA2829533D00A7E295 /* PhoneNumber */ = { + isa = PBXGroup; + children = ( + 95FD4CDB2829533D00A7E295 /* DefaultBillingFormPhoneNumberCellStyle.swift */, + ); + path = PhoneNumber; + sourceTree = ""; + }; + 95FD4CDC2829533D00A7E295 /* AddressLine1 */ = { + isa = PBXGroup; + children = ( + 95FD4CDD2829533D00A7E295 /* DefaultBillingFormAddressLine1CellStyle.swift */, + ); + path = AddressLine1; + sourceTree = ""; + }; + 95FD4CDE2829533D00A7E295 /* Country */ = { + isa = PBXGroup; + children = ( + 95FD4CDF2829533D00A7E295 /* DefaultBillingFormCountryCellStyle.swift */, + ); + path = Country; + sourceTree = ""; + }; + 95FD4CE02829533D00A7E295 /* Main */ = { + isa = PBXGroup; + children = ( + 95FD4CE12829533D00A7E295 /* DefaultBillingFormStyle.swift */, + ); + path = Main; + sourceTree = ""; + }; + 95FD4CE22829533D00A7E295 /* Header */ = { + isa = PBXGroup; + children = ( + 95FD4CE32829533D00A7E295 /* Cancel */, + 95FD4CE52829533D00A7E295 /* Title */, + 95FD4CE72829533D00A7E295 /* Done */, + 95FD4CE92829533D00A7E295 /* Main */, + ); + path = Header; + sourceTree = ""; + }; + 95FD4CE32829533D00A7E295 /* Cancel */ = { + isa = PBXGroup; + children = ( + 95FD4CE42829533D00A7E295 /* DefaultCancelButtonFormStyle.swift */, + ); + path = Cancel; + sourceTree = ""; + }; + 95FD4CE52829533D00A7E295 /* Title */ = { + isa = PBXGroup; + children = ( + 95FD4CE62829533D00A7E295 /* DefaultHeaderLabelFormStyle.swift */, + ); + path = Title; + sourceTree = ""; + }; + 95FD4CE72829533D00A7E295 /* Done */ = { + isa = PBXGroup; + children = ( + 95FD4CE82829533D00A7E295 /* DefaultDoneFormButtonStyle.swift */, + ); + path = Done; + sourceTree = ""; + }; + 95FD4CE92829533D00A7E295 /* Main */ = { + isa = PBXGroup; + children = ( + 95FD4CEA2829533D00A7E295 /* DefaultBillingFormHeaderCellStyle.swift */, + ); + path = Main; + sourceTree = ""; + }; + 95FD4CEB2829533D00A7E295 /* Cell */ = { + isa = PBXGroup; + children = ( + 95FD4CEC2829533D00A7E295 /* BillingFormTextFieldCellStyle.swift */, + 95FD4CED2829533D00A7E295 /* BillingFormHeaderCellStyle.swift */, + ); + path = Cell; + sourceTree = ""; + }; + 95FD4CEE2829533D00A7E295 /* Protocols */ = { + isa = PBXGroup; + children = ( + 95FD4CEF2829533D00A7E295 /* BillingFormStyle.swift */, + 95FD4CF02829533D00A7E295 /* FormButtonStyle.swift */, + 95FD4CF12829533D00A7E295 /* InputLabelStyle.swift */, + 95FD4CF22829533D00A7E295 /* FormTextFieldStyle.swift */, + 95FD4CF32829533D00A7E295 /* ErrorInputLabelStyle.swift */, + ); + path = Protocols; + sourceTree = ""; + }; + 95FD4CF42829533D00A7E295 /* View */ = { + isa = PBXGroup; + children = ( + 95FD4CF52829533D00A7E295 /* Field */, + 95FD4CF92829533D00A7E295 /* TableViewCell */, + 95FD4CFE2829533D00A7E295 /* Error */, + ); + path = View; + sourceTree = ""; + }; + 95FD4CF52829533D00A7E295 /* Field */ = { + isa = PBXGroup; + children = ( + 95FD4CF62829533D00A7E295 /* BillingFormTextField.swift */, + 95FD4CF72829533D00A7E295 /* BillingFormTextFieldView.swift */, + 95FD4CF82829533D00A7E295 /* BillingFormPhoneNumberText.swift */, + ); + path = Field; + sourceTree = ""; + }; + 95FD4CF92829533D00A7E295 /* TableViewCell */ = { + isa = PBXGroup; + children = ( + 95FD4CFA2829533D00A7E295 /* Fields */, + 95FD4CFC2829533D00A7E295 /* Header */, + ); + path = TableViewCell; + sourceTree = ""; + }; + 95FD4CFA2829533D00A7E295 /* Fields */ = { + isa = PBXGroup; + children = ( + 95FD4CFB2829533D00A7E295 /* BillingFormTextFieldCell.swift */, + ); + path = Fields; + sourceTree = ""; + }; + 95FD4CFC2829533D00A7E295 /* Header */ = { + isa = PBXGroup; + children = ( + 95FD4CFD2829533D00A7E295 /* BillingFormHeaderCell.swift */, + ); + path = Header; + sourceTree = ""; + }; + 95FD4CFE2829533D00A7E295 /* Error */ = { + isa = PBXGroup; + children = ( + 95FD4CFF2829533D00A7E295 /* BillingFormTextFieldErrorView.swift */, + ); + path = Error; + sourceTree = ""; + }; + 95FD4D002829533D00A7E295 /* ViewController */ = { + isa = PBXGroup; + children = ( + 95FD4D012829533D00A7E295 /* BillingFormViewController.swift */, + ); + path = ViewController; + sourceTree = ""; + }; + 95FD4D022829533D00A7E295 /* Factory */ = { + isa = PBXGroup; + children = ( + 95FD4D032829533D00A7E295 /* BillingFormFactory.swift */, + ); + path = Factory; + sourceTree = ""; + }; + 95FD4D072829533D00A7E295 /* Delegates */ = { + isa = PBXGroup; + children = ( + 95FD4D082829533D00A7E295 /* CardNumberInputViewDelegate.swift */, + 95FD4D092829533D00A7E295 /* CvvConfirmationViewControllerDelegate.swift */, + 95FD4D0A2829533D00A7E295 /* ThreedsWebViewControllerDelegate.swift */, + 95FD4D0B2829533D00A7E295 /* CountrySelectionViewControllerDelegate.swift */, + 95FD4D0C2829533D00A7E295 /* ExpirationDatePickerDelegate.swift */, + 95FD4D0D2829533D00A7E295 /* CardViewControllerDelegate.swift */, + 95FD4D0E2829533D00A7E295 /* CvvInputViewDelegate.swift */, + 95FD4D0F2829533D00A7E295 /* AddressViewControllerDelegate.swift */, + ); + path = Delegates; + sourceTree = ""; + }; + 95FD4D102829533D00A7E295 /* Controllers */ = { + isa = PBXGroup; + children = ( + 95FD4D112829533D00A7E295 /* CardViewController.swift */, + 95FD4D122829533D00A7E295 /* CvvConfirmationViewController.swift */, + 95FD4D132829533D00A7E295 /* CountrySelectionViewController.swift */, + 95FD4D142829533D00A7E295 /* SimpleLoadingViewController.swift */, + 95FD4D152829533D00A7E295 /* ThreedsWebViewController.swift */, + 95FD4D162829533D00A7E295 /* AddressViewController.swift */, + ); + path = Controllers; + sourceTree = ""; + }; + 95FD4D172829533D00A7E295 /* Views */ = { + isa = PBXGroup; + children = ( + 95FD4D182829533D00A7E295 /* CardView.swift */, + 95FD4D192829533D00A7E295 /* DetailsInputView.swift */, + 95FD4D1A2829533D00A7E295 /* SchemeIconsStackView.swift */, + 95FD4D1B2829533D00A7E295 /* StandardInputView.swift */, + 95FD4D1C2829533D00A7E295 /* PhoneNumberInputView.swift */, + 95FD4D1D2829533D00A7E295 /* AddressView.swift */, + 95FD4D1E2829533D00A7E295 /* CardNumberInputView.swift */, + 95FD4D1F2829533D00A7E295 /* CvvInputView.swift */, + 95FD4D202829533D00A7E295 /* ExpirationDateInputView.swift */, + ); + path = Views; + sourceTree = ""; + }; + 95FD4D212829533D00A7E295 /* Resources */ = { + isa = PBXGroup; + children = ( + 95FD4D222829533D00A7E295 /* Localizable.strings */, + 95FD4D242829533D00A7E295 /* schemes */, + 95FD4D3C2829533D00A7E295 /* checkmarks */, + 95FD4D412829533D00A7E295 /* warning */, + 95FD4D432829533D00A7E295 /* arrows */, + ); + name = Resources; + path = ../../Source/Resources; + sourceTree = ""; + }; + 95FD4D242829533D00A7E295 /* schemes */ = { + isa = PBXGroup; + children = ( + 95FD4D252829533D00A7E295 /* icon-visa.png */, + 95FD4D262829533D00A7E295 /* icon-maestro.png */, + 95FD4D272829533D00A7E295 /* icon-visa@2x.png */, + 95FD4D282829533D00A7E295 /* icon-mastercard@2x.png */, + 95FD4D292829533D00A7E295 /* icon-mastercard@3x.png */, + 95FD4D2A2829533D00A7E295 /* icon-visa@3x.png */, + 95FD4D2B2829533D00A7E295 /* icon-dinersclub.png */, + 95FD4D2C2829533D00A7E295 /* icon-mastercard.png */, + 95FD4D2D2829533D00A7E295 /* icon-jcb.png */, + 95FD4D2E2829533D00A7E295 /* icon-amex.png */, + 95FD4D2F2829533D00A7E295 /* icon-maestro@3x.png */, + 95FD4D302829533D00A7E295 /* icon-jcb@2x.png */, + 95FD4D312829533D00A7E295 /* icon-amex@2x.png */, + 95FD4D322829533D00A7E295 /* icon-amex@3x.png */, + 95FD4D332829533D00A7E295 /* icon-jcb@3x.png */, + 95FD4D342829533D00A7E295 /* icon-maestro@2x.png */, + 95FD4D352829533D00A7E295 /* icon-dinersclub@3x.png */, + 95FD4D362829533D00A7E295 /* icon-discover@2x.png */, + 95FD4D372829533D00A7E295 /* icon-discover@3x.png */, + 95FD4D382829533D00A7E295 /* icon-discover.png */, + 95FD4D392829533D00A7E295 /* icon-dinersclub@2x.png */, + ); + path = schemes; + sourceTree = ""; + }; + 95FD4D3C2829533D00A7E295 /* checkmarks */ = { + isa = PBXGroup; + children = ( + 95FD4D3D2829533D00A7E295 /* checkmark.png */, + 95FD4D3E2829533D00A7E295 /* checkmark@2x.png */, + 95FD4D3F2829533D00A7E295 /* checkmark@3x.png */, + ); + path = checkmarks; + sourceTree = ""; + }; + 95FD4D412829533D00A7E295 /* warning */ = { + isa = PBXGroup; + children = ( + 95FD4D422829533D00A7E295 /* warning.pdf */, + ); + path = warning; + sourceTree = ""; + }; + 95FD4D432829533D00A7E295 /* arrows */ = { + isa = PBXGroup; + children = ( + 95FD4D442829533D00A7E295 /* keyboard-previous@2x.png */, + 95FD4D452829533D00A7E295 /* keyboard-next@3x.png */, + 95FD4D462829533D00A7E295 /* keyboard-next@2x.png */, + 95FD4D472829533D00A7E295 /* keyboard-previous@3x.png */, + 95FD4D482829533D00A7E295 /* keyboard-down.png */, + 95FD4D492829533D00A7E295 /* keyboard-previous.png */, + 95FD4D4A2829533D00A7E295 /* keyboard-next.png */, + 95FD4D4B2829533D00A7E295 /* keyboard-down@2x.png */, + 95FD4D4C2829533D00A7E295 /* keyboard-down@3x.png */, + ); + path = arrows; sourceTree = ""; }; CB00CA1127ECBE8B000069BE /* Tests */ = { @@ -1100,7 +1546,7 @@ TargetAttributes = { 4422775C26163748009626A0 = { CreatedOnToolsVersion = 12.3; - LastSwiftMigration = 1230; + LastSwiftMigration = 1330; }; 449AE407262F1CDB0001C835 = { CreatedOnToolsVersion = 12.3; @@ -1154,40 +1600,41 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 442277F72616376E009626A0 /* icon-amex@3x.png in Resources */, - 442278082616376E009626A0 /* keyboard-next.png in Resources */, - 442277F12616376E009626A0 /* icon-mastercard.png in Resources */, - 442277F82616376E009626A0 /* icon-jcb@3x.png in Resources */, - 442277ED2616376E009626A0 /* icon-mastercard@2x.png in Resources */, - 442277F62616376E009626A0 /* icon-amex@2x.png in Resources */, - 442277E92616376E009626A0 /* Localizable.strings in Resources */, - 442277EE2616376E009626A0 /* icon-mastercard@3x.png in Resources */, - 442277FC2616376E009626A0 /* icon-discover@3x.png in Resources */, - 442277F22616376E009626A0 /* icon-jcb.png in Resources */, - 442277F32616376E009626A0 /* icon-amex.png in Resources */, - 442278092616376E009626A0 /* keyboard-down@2x.png in Resources */, - 442278042616376E009626A0 /* keyboard-next@2x.png in Resources */, - 442277EF2616376E009626A0 /* icon-visa@3x.png in Resources */, - 442277F92616376E009626A0 /* icon-maestro@2x.png in Resources */, - 442277EA2616376E009626A0 /* icon-visa.png in Resources */, - 442278062616376E009626A0 /* keyboard-down.png in Resources */, - 442277FF2616376E009626A0 /* checkmark.png in Resources */, - 442278012616376E009626A0 /* checkmark@3x.png in Resources */, - 442277EC2616376E009626A0 /* icon-visa@2x.png in Resources */, - 442278022616376E009626A0 /* keyboard-previous@2x.png in Resources */, - 442277FE2616376E009626A0 /* icon-dinersclub@2x.png in Resources */, - 442277FD2616376E009626A0 /* icon-discover.png in Resources */, - 442277FA2616376E009626A0 /* icon-dinersclub@3x.png in Resources */, - 442278032616376E009626A0 /* keyboard-next@3x.png in Resources */, - 442277EB2616376E009626A0 /* icon-maestro.png in Resources */, - 4422780A2616376E009626A0 /* keyboard-down@3x.png in Resources */, - 442277F42616376E009626A0 /* icon-maestro@3x.png in Resources */, - 442277F52616376E009626A0 /* icon-jcb@2x.png in Resources */, - 442277FB2616376E009626A0 /* icon-discover@2x.png in Resources */, - 442278072616376E009626A0 /* keyboard-previous.png in Resources */, - 442278002616376E009626A0 /* checkmark@2x.png in Resources */, - 442278052616376E009626A0 /* keyboard-previous@3x.png in Resources */, - 442277F02616376E009626A0 /* icon-dinersclub.png in Resources */, + 95FD4DDB2829533D00A7E295 /* icon-amex@3x.png in Resources */, + 95FD4DD52829533D00A7E295 /* icon-mastercard.png in Resources */, + 95FD4DDC2829533D00A7E295 /* icon-jcb@3x.png in Resources */, + 95FD4DEC2829533D00A7E295 /* keyboard-previous.png in Resources */, + 95FD4DD12829533D00A7E295 /* icon-mastercard@2x.png in Resources */, + 95FD4DDA2829533D00A7E295 /* icon-amex@2x.png in Resources */, + 95FD4DCD2829533D00A7E295 /* Localizable.strings in Resources */, + 95FD4DD22829533D00A7E295 /* icon-mastercard@3x.png in Resources */, + 95FD4DE62829533D00A7E295 /* warning.pdf in Resources */, + 95FD4DEE2829533D00A7E295 /* keyboard-down@2x.png in Resources */, + 95FD4DE02829533D00A7E295 /* icon-discover@3x.png in Resources */, + 95FD4DEB2829533D00A7E295 /* keyboard-down.png in Resources */, + 95FD4DEA2829533D00A7E295 /* keyboard-previous@3x.png in Resources */, + 95FD4DD62829533D00A7E295 /* icon-jcb.png in Resources */, + 95FD4DD72829533D00A7E295 /* icon-amex.png in Resources */, + 95FD4DED2829533D00A7E295 /* keyboard-next.png in Resources */, + 95FD4DD32829533D00A7E295 /* icon-visa@3x.png in Resources */, + 95FD4DDD2829533D00A7E295 /* icon-maestro@2x.png in Resources */, + 95FD4DCE2829533D00A7E295 /* icon-visa.png in Resources */, + 95FD4DE32829533D00A7E295 /* checkmark.png in Resources */, + 95FD4DE72829533D00A7E295 /* keyboard-previous@2x.png in Resources */, + 95FD4DE52829533D00A7E295 /* checkmark@3x.png in Resources */, + 95FD4DD02829533D00A7E295 /* icon-visa@2x.png in Resources */, + 95FD4DE22829533D00A7E295 /* icon-dinersclub@2x.png in Resources */, + 95FD4DE12829533D00A7E295 /* icon-discover.png in Resources */, + 95FD4DDE2829533D00A7E295 /* icon-dinersclub@3x.png in Resources */, + 95FD4DCF2829533D00A7E295 /* icon-maestro.png in Resources */, + 95FD4DD82829533D00A7E295 /* icon-maestro@3x.png in Resources */, + 95FD4DE82829533D00A7E295 /* keyboard-next@3x.png in Resources */, + 95FD4DD92829533D00A7E295 /* icon-jcb@2x.png in Resources */, + 95FD4DEF2829533D00A7E295 /* keyboard-down@3x.png in Resources */, + 95FD4DDF2829533D00A7E295 /* icon-discover@2x.png in Resources */, + 95FD4DE42829533D00A7E295 /* checkmark@2x.png in Resources */, + 95FD4DE92829533D00A7E295 /* keyboard-next@2x.png in Resources */, + 95FD4DD42829533D00A7E295 /* icon-dinersclub.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1249,86 +1696,132 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 57256C71269F0FB0001EC3D8 /* JSONDecoder+TopLevelDecoder.swift in Sources */, - 442278322616376E009626A0 /* ErrorResponse.swift in Sources */, - 442278332616376E009626A0 /* ApplePayTokenRequest.swift in Sources */, - 4422781F2616376E009626A0 /* StandardInputView.swift in Sources */, - 442278132616376E009626A0 /* CardViewControllerDelegate.swift in Sources */, - 57256C6C269F0FB0001EC3D8 /* JSONEncoder+TopLevelEncoder.swift in Sources */, - 4422782F2616376E009626A0 /* InputState.swift in Sources */, - 442278262616376E009626A0 /* Environment.swift in Sources */, - 4422783A2616376E009626A0 /* UIViewControllerExtensions.swift in Sources */, - 4422780F2616376E009626A0 /* CvvConfirmationViewControllerDelegate.swift in Sources */, - 442278402616376E009626A0 /* CheckoutAPIClient.swift in Sources */, - 442278252616376E009626A0 /* CkoPhoneNumber.swift in Sources */, - 4422781E2616376E009626A0 /* SchemeIconsStackView.swift in Sources */, - 4422781A2616376E009626A0 /* ThreedsWebViewController.swift in Sources */, - CB00CA0C27ECA7A1000069BE /* UIBarStyle+stringValue.swift in Sources */, - 442278212616376E009626A0 /* AddressView.swift in Sources */, - 57256C51269F0F90001EC3D8 /* TokenType.swift in Sources */, - 4422780D2616376E009626A0 /* CardListCellName.swift in Sources */, - 57256C70269F0FB0001EC3D8 /* DispatchQueue+Dispatching.swift in Sources */, - 442277E82616376E009626A0 /* CheckoutTheme.swift in Sources */, - 442278272616376E009626A0 /* CardScheme.swift in Sources */, - 4422782C2616376E009626A0 /* CkoAddress.swift in Sources */, - 442278222616376E009626A0 /* CardNumberInputView.swift in Sources */, - 442278112616376E009626A0 /* CountrySelectionViewControllerDelegate.swift in Sources */, - 442278352616376E009626A0 /* CustomerCard.swift in Sources */, - 57256C53269F0F90001EC3D8 /* CorrelationIDGenerator.swift in Sources */, - 4422781D2616376E009626A0 /* DetailsInputView.swift in Sources */, - CB00CA0427EB4B27000069BE /* UIColor+PropertyProviding.swift in Sources */, - 442278232616376E009626A0 /* CvvInputView.swift in Sources */, - 57256C62269F0FA0001EC3D8 /* Constants.swift in Sources */, - 57256C46269F0F81001EC3D8 /* HTTPMethod.swift in Sources */, - 442278102616376E009626A0 /* ThreedsWebViewControllerDelegate.swift in Sources */, - 57256C60269F0FA0001EC3D8 /* TopLevelEncoder.swift in Sources */, - 4422782D2616376E009626A0 /* CardType.swift in Sources */, - 442278242616376E009626A0 /* ExpirationDateInputView.swift in Sources */, - 4452A1AD26FB5875006AF798 /* URLHelper.swift in Sources */, - 57256C55269F0F90001EC3D8 /* FramesEventLogger.swift in Sources */, - CB00CA0A27EB5842000069BE /* PropertyProviding.swift in Sources */, - 442278392616376E009626A0 /* StringExtensions.swift in Sources */, - 4422781C2616376E009626A0 /* CardView.swift in Sources */, - 442278302616376E009626A0 /* CkoCardTokenRequest.swift in Sources */, - 44F095A72629DCF200CB287F /* UIDeviceExtensions.swift in Sources */, - 57256C44269F0F81001EC3D8 /* Request.swift in Sources */, - 44F095202625F7E700CB287F /* FramesLogEvent.swift in Sources */, - 57256C5F269F0FA0001EC3D8 /* Dispatching.swift in Sources */, - 4422782A2616376E009626A0 /* Customer.swift in Sources */, - 57256C56269F0F90001EC3D8 /* NetworkFlowLogger.swift in Sources */, - CB00CA0627EB51B8000069BE /* UIFont+PropertyProviding.swift in Sources */, - 442278282616376E009626A0 /* CardProviderResponse.swift in Sources */, - 4422780C2616376E009626A0 /* ExpirationDatePicker.swift in Sources */, - 57256C6D269F0FB0001EC3D8 /* URL+Extensions.swift in Sources */, - 442278122616376E009626A0 /* ExpirationDatePickerDelegate.swift in Sources */, - 57256C6E269F0FB0001EC3D8 /* JSONEncoder+ContentTypeProviding.swift in Sources */, - 4422781B2616376E009626A0 /* AddressViewController.swift in Sources */, - CB00CA0827EB5836000069BE /* Theme.swift in Sources */, - 442278202616376E009626A0 /* PhoneNumberInputView.swift in Sources */, - 4422780B2616376E009626A0 /* CardListCell.swift in Sources */, - 57256C6F269F0FB0001EC3D8 /* ErrorResponse+PropertyProviding.swift in Sources */, - 4422783C2616376E009626A0 /* UIResponderExtensions.swift in Sources */, - 442278192616376E009626A0 /* SimpleLoadingViewController.swift in Sources */, - 57256C61269F0FA0001EC3D8 /* ContentTypeProviding.swift in Sources */, - 442278372616376E009626A0 /* CheckoutSdkIos.swift in Sources */, - 442278342616376E009626A0 /* NetworkError.swift in Sources */, - 57256C45269F0F81001EC3D8 /* RequestExecutor.swift in Sources */, - 57256C50269F0F90001EC3D8 /* DateProvider.swift in Sources */, - 57256C54269F0F90001EC3D8 /* NetworkFlowLoggerFactory.swift in Sources */, - 442278172616376E009626A0 /* CvvConfirmationViewController.swift in Sources */, - 4422783D2616376E009626A0 /* CardUtils.swift in Sources */, - 442278142616376E009626A0 /* CvvInputViewDelegate.swift in Sources */, - 442278182616376E009626A0 /* CountrySelectionViewController.swift in Sources */, - 442278292616376E009626A0 /* CkoCardTokenResponse.swift in Sources */, - 442278162616376E009626A0 /* CardViewController.swift in Sources */, - 442278152616376E009626A0 /* AddressViewControllerDelegate.swift in Sources */, - 4422782B2616376E009626A0 /* CardProvider.swift in Sources */, - 4422783B2616376E009626A0 /* UIViewExtensions.swift in Sources */, - 4422780E2616376E009626A0 /* CardNumberInputViewDelegate.swift in Sources */, - 57256C5E269F0FA0001EC3D8 /* TopLevelDecoder.swift in Sources */, - 57256DEC269FA42E001EC3D8 /* Dictionary+Additions.swift in Sources */, - 4422782E2616376E009626A0 /* CustomerCardList.swift in Sources */, - 442278312616376E009626A0 /* CheckoutTokenStatus.swift in Sources */, + 95FD4DAD2829533D00A7E295 /* BillingFormPhoneNumberText.swift in Sources */, + 95FD4DB62829533D00A7E295 /* CardNumberInputViewDelegate.swift in Sources */, + 95FD4D882829533D00A7E295 /* PhoneNumberValidator.swift in Sources */, + 95FD4D5D2829533D00A7E295 /* RequestExecutor.swift in Sources */, + 95FD4DCA2829533D00A7E295 /* CardNumberInputView.swift in Sources */, + 95FD4DA82829533D00A7E295 /* InputLabelStyle.swift in Sources */, + 95FD4D852829533D00A7E295 /* CheckoutAPIClient.swift in Sources */, + 95FD4DBE2829533D00A7E295 /* CardViewController.swift in Sources */, + 95FD4D812829533D00A7E295 /* UIDeviceExtensions.swift in Sources */, + 95FD4DA52829533D00A7E295 /* BillingFormHeaderCellStyle.swift in Sources */, + 95FD4D5F2829533D00A7E295 /* Customer.swift in Sources */, + 95FD4D7A2829533D00A7E295 /* DispatchQueue+Dispatching.swift in Sources */, + 95FD4D7B2829533D00A7E295 /* JSONEncoder+ContentTypeProviding.swift in Sources */, + 95FD4DA92829533D00A7E295 /* FormTextFieldStyle.swift in Sources */, + 95FD4DAC2829533D00A7E295 /* BillingFormTextFieldView.swift in Sources */, + 95FD4DC52829533D00A7E295 /* DetailsInputView.swift in Sources */, + 95FD4D7F2829533D00A7E295 /* UIViewExtensions.swift in Sources */, + 95FD4D972829533D00A7E295 /* DefaultBillingFormPostCodeCellStyle.swift in Sources */, + 95FD4DB12829533D00A7E295 /* BillingFormViewController.swift in Sources */, + 95FD4D7C2829533D00A7E295 /* JSONEncoder+TopLevelEncoder.swift in Sources */, + 95FD4DB32829533D00A7E295 /* ExpirationDatePicker.swift in Sources */, + 95FD4DB22829533D00A7E295 /* BillingFormFactory.swift in Sources */, + 95FD4D5E2829533D00A7E295 /* Request.swift in Sources */, + 95FD4D9B2829533D00A7E295 /* DefaultBillingFormStateCellStyle.swift in Sources */, + 95FD4D942829533D00A7E295 /* DefaultTitleLabelStyle.swift in Sources */, + 95FD4DBD2829533D00A7E295 /* AddressViewControllerDelegate.swift in Sources */, + 95FD4D802829533D00A7E295 /* URL+Extensions.swift in Sources */, + 95FD4DA72829533D00A7E295 /* FormButtonStyle.swift in Sources */, + 95FD4D542829533D00A7E295 /* CkoPhoneNumber.swift in Sources */, + 95FD4DAB2829533D00A7E295 /* BillingFormTextField.swift in Sources */, + 95FD4DC92829533D00A7E295 /* AddressView.swift in Sources */, + 95FD4D592829533D00A7E295 /* CardProviderResponse.swift in Sources */, + 95FD4D582829533D00A7E295 /* CardScheme.swift in Sources */, + 95FD4D5C2829533D00A7E295 /* HTTPMethod.swift in Sources */, + 95FD4DB42829533D00A7E295 /* CardListCellName.swift in Sources */, + 95FD4D642829533D00A7E295 /* CustomerCardList.swift in Sources */, + 95FD4D6C2829533D00A7E295 /* NetworkFlowLoggerFactory.swift in Sources */, + 95FD4DC22829533D00A7E295 /* ThreedsWebViewController.swift in Sources */, + 95FD4D7D2829533D00A7E295 /* UIViewControllerExtensions.swift in Sources */, + 95FD4D992829533D00A7E295 /* DefaultBillingFormCityCellStyle.swift in Sources */, + 95FD4DA32829533D00A7E295 /* DefaultBillingFormHeaderCellStyle.swift in Sources */, + 95FD4D572829533D00A7E295 /* TopLevelEncoder.swift in Sources */, + 95FD4D892829533D00A7E295 /* AddressLine1Validator.swift in Sources */, + 95FD4D772829533D00A7E295 /* UIBarStyle+stringValue.swift in Sources */, + 95FD4DB52829533D00A7E295 /* UITableView.swift in Sources */, + 95FD4DC02829533D00A7E295 /* CountrySelectionViewController.swift in Sources */, + 95FD4DB82829533D00A7E295 /* ThreedsWebViewControllerDelegate.swift in Sources */, + 95FD4D662829533D00A7E295 /* CkoCardTokenRequest.swift in Sources */, + 95FD4D8C2829533D00A7E295 /* AddressLine2Validator.swift in Sources */, + 95FD4D552829533D00A7E295 /* URLHelper.swift in Sources */, + 95FD4DB72829533D00A7E295 /* CvvConfirmationViewControllerDelegate.swift in Sources */, + 95FD4D742829533D00A7E295 /* NetworkFlowLogger.swift in Sources */, + 95FD4DA12829533D00A7E295 /* DefaultHeaderLabelFormStyle.swift in Sources */, + 95FD4D6E2829533D00A7E295 /* FramesLogEvent.swift in Sources */, + 95FD4D8B2829533D00A7E295 /* CityValidator.swift in Sources */, + 95FD4D712829533D00A7E295 /* TokenType.swift in Sources */, + 95FD4D622829533D00A7E295 /* CkoAddress.swift in Sources */, + 95FD4DBB2829533D00A7E295 /* CardViewControllerDelegate.swift in Sources */, + 95FD4DBC2829533D00A7E295 /* CvvInputViewDelegate.swift in Sources */, + 95FD4DA62829533D00A7E295 /* BillingFormStyle.swift in Sources */, + 95FD4DC72829533D00A7E295 /* StandardInputView.swift in Sources */, + 95FD4DBF2829533D00A7E295 /* CvvConfirmationViewController.swift in Sources */, + 95FD4DC12829533D00A7E295 /* SimpleLoadingViewController.swift in Sources */, + 95FD4D732829533D00A7E295 /* CorrelationIDGenerator.swift in Sources */, + 95FD4D722829533D00A7E295 /* Theme.swift in Sources */, + 95FD4D792829533D00A7E295 /* ErrorResponse+PropertyProviding.swift in Sources */, + 95FD4D522829533D00A7E295 /* CardUtils.swift in Sources */, + 95FD4DA02829533D00A7E295 /* DefaultCancelButtonFormStyle.swift in Sources */, + 95FD4DC42829533D00A7E295 /* CardView.swift in Sources */, + 95FD4D8A2829533D00A7E295 /* Validator.swift in Sources */, + 95FD4D9D2829533D00A7E295 /* DefaultBillingFormAddressLine1CellStyle.swift in Sources */, + 95FD4D6A2829533D00A7E295 /* ContentTypeProviding.swift in Sources */, + 95FD4D9A2829533D00A7E295 /* DefaultBillingFormFullNameCellStyle.swift in Sources */, + 95FD4D832829533D00A7E295 /* Dictionary+Additions.swift in Sources */, + 95FD4DC82829533D00A7E295 /* PhoneNumberInputView.swift in Sources */, + 95FD4D652829533D00A7E295 /* InputState.swift in Sources */, + 95FD4D612829533D00A7E295 /* Dispatching.swift in Sources */, + 95FD4DCB2829533D00A7E295 /* CvvInputView.swift in Sources */, + 95FD4D982829533D00A7E295 /* DefaultBillingFormAddressLine2CellStyle.swift in Sources */, + 95FD4DF22829533D00A7E295 /* CheckoutColor.swift in Sources */, + 95FD4D912829533D00A7E295 /* DefaultBillingFormViewModel.swift in Sources */, + 95FD4D602829533D00A7E295 /* CardProvider.swift in Sources */, + 95FD4D782829533D00A7E295 /* StringExtensions.swift in Sources */, + 95FD4D962829533D00A7E295 /* DefaultErrorInputLabelStyle.swift in Sources */, + 95FD4D7E2829533D00A7E295 /* JSONDecoder+TopLevelDecoder.swift in Sources */, + 95FD4D842829533D00A7E295 /* UIResponderExtensions.swift in Sources */, + 95FD4D922829533D00A7E295 /* BillingFormCellType.swift in Sources */, + 95FD4DAE2829533D00A7E295 /* BillingFormTextFieldCell.swift in Sources */, + 95FD4D5B2829533D00A7E295 /* CkoCardTokenResponse.swift in Sources */, + 95FD4D9C2829533D00A7E295 /* DefaultBillingFormPhoneNumberCellStyle.swift in Sources */, + 95FD4D682829533D00A7E295 /* ErrorResponse.swift in Sources */, + 95FD4DB92829533D00A7E295 /* CountrySelectionViewControllerDelegate.swift in Sources */, + 95FD4D762829533D00A7E295 /* UIFont+PropertyProviding.swift in Sources */, + 95FD4D902829533D00A7E295 /* BillingFormViewModel.swift in Sources */, + 95FD4D5A2829533D00A7E295 /* TopLevelDecoder.swift in Sources */, + 95FD4D8D2829533D00A7E295 /* StateValidator.swift in Sources */, + 95FD4D952829533D00A7E295 /* DefaultTextField.swift in Sources */, + 95FD4D692829533D00A7E295 /* ApplePayTokenRequest.swift in Sources */, + 95FD4DCC2829533D00A7E295 /* ExpirationDateInputView.swift in Sources */, + 95FD4D532829533D00A7E295 /* Constants.swift in Sources */, + 95FD4DB02829533D00A7E295 /* BillingFormTextFieldErrorView.swift in Sources */, + 95FD4D672829533D00A7E295 /* CheckoutTokenStatus.swift in Sources */, + 95FD4DF12829533D00A7E295 /* CheckoutSdkIos.swift in Sources */, + 95FD4D752829533D00A7E295 /* CustomerCard.swift in Sources */, + 95FD4DAA2829533D00A7E295 /* ErrorInputLabelStyle.swift in Sources */, + 95FD4D8F2829533D00A7E295 /* CardListCell.swift in Sources */, + 95FD4DC62829533D00A7E295 /* SchemeIconsStackView.swift in Sources */, + 95FD4D822829533D00A7E295 /* UIColor+PropertyProviding.swift in Sources */, + 95FD4D932829533D00A7E295 /* DefaultHintInputLabelStyle.swift in Sources */, + 95FD4DA22829533D00A7E295 /* DefaultDoneFormButtonStyle.swift in Sources */, + 95FD4D6B2829533D00A7E295 /* NetworkError.swift in Sources */, + 95FD4D562829533D00A7E295 /* Environment.swift in Sources */, + 95FD4D9E2829533D00A7E295 /* DefaultBillingFormCountryCellStyle.swift in Sources */, + 95FD4DF02829533D00A7E295 /* CheckoutTheme.swift in Sources */, + 95FD4D6D2829533D00A7E295 /* FramesEventLogger.swift in Sources */, + 95FD4D702829533D00A7E295 /* DateProvider.swift in Sources */, + 95FD4DA42829533D00A7E295 /* BillingFormTextFieldCellStyle.swift in Sources */, + 95FD4DC32829533D00A7E295 /* AddressViewController.swift in Sources */, + 95FD4D862829533D00A7E295 /* PostCodeValidator.swift in Sources */, + 95FD4D872829533D00A7E295 /* CountryValidator.swift in Sources */, + 95FD4DBA2829533D00A7E295 /* ExpirationDatePickerDelegate.swift in Sources */, + 95FD4D632829533D00A7E295 /* CardType.swift in Sources */, + 95FD4DAF2829533D00A7E295 /* BillingFormHeaderCell.swift in Sources */, + 95FD4D8E2829533D00A7E295 /* FullNameValidator.swift in Sources */, + 95FD4D6F2829533D00A7E295 /* PropertyProviding.swift in Sources */, + 95FD4D9F2829533D00A7E295 /* DefaultBillingFormStyle.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1454,15 +1947,15 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ - 442277802616376D009626A0 /* Localizable.strings */ = { + 95FD4D222829533D00A7E295 /* Localizable.strings */ = { isa = PBXVariantGroup; children = ( - 442277812616376D009626A0 /* de */, - 442277982616376D009626A0 /* en */, - 442277992616376D009626A0 /* es */, - 4422779E2616376D009626A0 /* it */, - 442277A92616376D009626A0 /* fr */, - 442277AA2616376D009626A0 /* nl */, + 95FD4D232829533D00A7E295 /* de */, + 95FD4D3A2829533D00A7E295 /* en */, + 95FD4D3B2829533D00A7E295 /* es */, + 95FD4D402829533D00A7E295 /* it */, + 95FD4D4D2829533D00A7E295 /* fr */, + 95FD4D4E2829533D00A7E295 /* nl */, ); name = Localizable.strings; sourceTree = ""; @@ -1583,6 +2076,7 @@ 57256C82269F1181001EC3D8 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ../Tests/Info.plist; @@ -1605,6 +2099,7 @@ 57256C83269F1181001EC3D8 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = ../Tests/Info.plist; diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000000000000000000000000000000000000..7a799cd64629cc072c0f07b919a7864c944ed585 GIT binary patch literal 3730 zcmeH`dpMNq7Qo-^o^~#qkV0-7MPxQ3*GVcOQtpOLoLok(qj8JLWmj@bE;~sEh1{7f z%wWdM>68>PZjC)L%?`N?Gn4DcV9wb4>1qG5&vX7c|DCtQq(x_WcvbMnyyk*1XzT?-zmE;c)?<2n&tgIcrCDA{Gk>cXbw6cY!K^ zNZRcdU%mO7CQR`UxqP8+`D>oA{ zbrY7jc5x_OdKy(V9;gn@!C59!%e#?MK5SNHFONgqx|S691ART~kfQGBQQ`J#gT6jMdfU`_4mNjl4ComVHY}Fm}tNthnEknttGdgCn+T&E%5Hu z#ZYPwL?&HqN_u(r0%KLHR+JG_e!}25wWpDHAdJ&DbDPUpxIsh6SU)kCY>D^DZN6Fp z=|3XfBzDVP)dbf7fg`dmEMI$zL8#`M93-+z7!;osw2vN+70`_RbOdX>v9N@s=XI>Q zWX|Mdq@B_&i_IiQhvbEMw?44YnmE@bCEmbb-r)=aLjK8 ziZL;tXAqjJ+p~+xQTdYRUqB~ky%cZ^25Axh(c9^E}kVRbM zLs>oq$B`3${rKJlD}{h}eZQK-9^|AFOp}@>jZ95djB3vLUsRtz+nsPp!wrZ0?3R+@ za3!&JI*Z$Jv7Xi5=aM2VgJ`)vPv1_uGs0f)Y#i3K@mI~2c)!pqesyrH5m6x3<0@qm zanL+wpEGPeVA)CXx?YVtefe;65FSZ_UjMCfhJtfcN7ctrw4HD(*9JqOk|N)BFJagA zj7y=Xrbl8+9OFuT3nLdp4f}>E@n(&(PdYILX^Dh&YkZ{#&n**ntL#kI;9O5rkj}e~ z=XJJE)3_oqRi~yaOpS09HBr7|EF@Ej!zg`6o|$%xF{8LBdMv`g!TVQdz`jKoLG^x@i^`y3-FI@^WpJaqNr zvHNPR@Rm}JoNc})(I1CSFef3&qcY|1yuasR(wHNg#m_p8JpJbbh<3xWEAuNIWiy*F z#$((4kcojcSB<1n{@`5VS<78-?;8(9_r4B-P&Xbkl=1H;KG-S$O0yqjgeuL1#Oh~q zfAK2bNJy;JkQiU66BqQ5B=7Cg&v4`>GwTZG-m)T!@0$AULiTHUBd$S4`m^IWo+~=h zT%#p!l5{ae^P$$Bu0A<=qi_#w6ROmc6#X)$o$SkC#4N*+E2!?&X{}_o$P#^EIE5C) zoae@Gt`uW*4>l`XcfCv;>mzfLi3?$Fy^W{KtuDdpin-i094sl|Qu+S&y%l=lI#;`3 zbQW(l)f=yKBnZ+7c_hrU);m+hfh@ncuLOB>MB0F9SC2_3^`x>1NHI1k?wAEFq1>{^ zNqm&T+~ln^pXPhwN^6rVwK`Z!=5+POr1`VXRjR7@3yqODUV=F}h>R>y8}ruVIXrz_ z@zgl3KYN|j85G6qPYO!<`NRPVv3^41W;Zfp%S+j;KrY?VvcHUp! z&wrRvZ?As*yiRXtmN7afp%|K* z`j6ukzPxcCJZFPG(FKdE(MbIWl}UeNsp`X=eS0^}8HEdD7fos8T3V*U71t9=tK*hQ zR0hr!i?v2U`-|X(hVKGU5k++vZEH3xpdxOE#InJ6DzX=C|jf$SA9a zqBzK2$i9v@FK9>tgFC5j{Y~s*DO*0qB6@?Pn%%b)wFaYD=HL6hf0qqM7sjx#HgsSC zWo|RI2iBS#YR*?~X56kEj_W17_esFZK4c3ujM=qTTjZ9yjIk*_2vG@!oLF1eD;)d{ zDcNBb#b`GRG^dx&X&bRoAN7sGH@h6saU))pGKW#MAN@o%e29yJ|1&2XtBuf)*40?U zE%Vt7?9reY8Z-#P?QB8UrK#7FjyB{PUvKPRKWT=D=U*T*BM9TE76l;zqpRNd#rPCD zWyrlEwb9dGwMs7ge4pgI%vD{pzHm4-Q+|5c{;kV=UOm1om6O<+vhC+?YEPQ9jnv9c zZ#l48Kn*dHuP2mL2?-V6=yFQBX3b+=@-m)9@3VEWKW^z=Elrq?i6&rZQse literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000000000000000000000000000000000000..a68fe1ec047a3b50c559f180ef90c4fd9c7e99b1 GIT binary patch literal 122426 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000000000000000000000000000000000000..d5b97e0936158d6205dc0846d0a3121c07649951 GIT binary patch literal 4426 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 LqP1FUcM0I%9TA&= literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000000000000000000000000000000000000..55bfd61ee09644aceb4c7ffde2f37d95af5c574e GIT binary patch literal 4706 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 Qw|U`Nfy#nVAXL%%2aJujPXGV_ literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000000000000000000000000000000000000..763d6430197cc42d962027ff08ad46fe4016a902 GIT binary patch literal 6668 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000000000000000000000000000000000000..71255c59723f15fad9a7d3f28c375c9188e514f7 GIT binary patch literal 7022 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000000000000000000000000000000000000..870abebc982ee65de85cc42eee2ea69a149a3b3e GIT binary patch literal 946 zcmWIYbaPw9%)k)t>J$(bU=hK^z`&pY#4=#y>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@yTIiV9=LgU}va5v>;c-ee%iL^%nE& z_b-3ApjXA+Z`;N51s}2r?U!FTL!Voh`-8-tf_gdK+{S5t3%e9{bTO>s5KKN? zb)TW2bYI@OTScblPHwu#pOC{K$S@IT*2D%62L^}jxwk8lw|nN^-ZpiK{I9d$>*xHM zvS0bv`UAPrsXfQPbHV}zjsB$KIZ5SYQcTU+GBaCiOH<>`ANTBOm>Vwr`r9`1@78Wh z<~yflrRKFC4_c~W*Dor*cHQjvJnK#={k-S=Z2J0J$$KuVpMHN@cljreeZPNbdh3|k zyuNTE`tPPamoC?Q({T#1OG2oOSt#h~UnB0|$;1A47%B}16TKTP}e&X!Pj5YQ* jZri?+s^2#=;8#jUO+`sg%GaN-oYy~`eeYuZUtR_PfQR*` literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000000000000000000000000000000000000..d3412d3f2100eefc701122fcadaf19e137c2ad40 GIT binary patch literal 1134 zcmWIYbaP8%VPFV%bqWXzu!!JdU|>)HVs$X`baoDqU;=U(m?S_Xiva^eZeB@Ikh_yY zL}Zi#NDKxNlZy*rY%DY*1H-p#3_y~B;j%6kc|t;*DXGQDKt&&bxTFYZIRgV@3Xm<5 z4q;b-*hvs}4~Sh9666e2vjE7}NJnBPA+gI#3QB-#PJq-W7ZicmcYti0+?-O7T_6B* zF;8keKg93vmLmopigC3A +W+$Y2IcF+S?R^r5eQfRo|;V}(g7uB%pA)~Nl@ zif=h=Hc7-X;;QZO^9&m&s<;NZ>B`theg3!m+vof3Ke&ZAubqDAZPj5FueqswQgfFq zP!Q^2%24rW+BrwR^<{#PiXjJEXApyd&;q4|mX|uk75nURU#H&XyM5=3y=1CYY0)&x zj8}?=B2%2sz5mZ`JaeYAV*pTbfLpUqdbD2u^Y)jH#SN<_rejl-S#4IbG`4Q*M_{wk*rD+36-f@A=<*?|=N1KXf^4w&36J z2itlteeC-v2n#_XX)VQL63IOqXQ};s|0m?4l9HT~KVQwSvYeb|UK(Rt{qN7r z;`Uq1QtJC3+?*(J`ynnuplXbbg=JFG( z*Loj(aBpkPrfSpE!nZ`e^=P=d&wDK=6m-kRPOt%`YQ$~Biz|x$bm~4f^)q^Gef`w2?fOrX zcXw~?oAl$4v-a*b(K!`S@3o%pt9kL~-=hgmihE-J@2rat>Rb2x$-$k=H1F)1c;m_O zwr|)HVnZGB z4}|FqISi=`3JjhMc?`)6dO(&Dg8?v!m;qCa&jn!m&^L78VYtq+aiWTAP}()aU+>@C zZ5HOcZC3PT!IGJK&oeqndrn$XaP8f_^N)TQ+uZ&0ouTgV0e%J!7R8@Zj>hcGB3=`V zZ!FemV__EQWJ*x+OHt`~k}c#qkwJpF zU-6Xh|8IYsGfT>~X{Dyff&jj1zUMh^D?JUmHn9aW%#vbU%&0Qsze&SCW`&pAwr%x` z`M~uqAiuD@{JWEEdHM1kpC?Xuw&{OvZoy^=!>$+mnYQOnk?rZr|G*9lVXDv*{`D== z=mMg;VXEL)|USK(UIe-`Z8Tx93fG$HF&Xe}7*rDJzdH&bmt*X1(3&e`It&_C4dx0&y zJHEXC{pd69{1U=myYjDxxs0sJO83tLi)@bpPrQ-Zoi{bbv5#**?mQ2xrKkae&h>9mH)oC zA-`auj?VKBZ}Ly-r)&KdGCw7^ygnsi?)>F);(OO-NpCvGD{bub+z? zG@IFUvgYYBJNJ$(bU=hK^z`&pY#1>%W>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6U;1OF=n1M>ugSkg=ehV88k3=+2xVk!$5 z82DQl7`B}+NGwVOJB9^FGNq+4Fnn6hz`z^Hz#x2qfq^R;=1_!QL|owTs{&Au4A7tX zK$y;u!;s3Lz~IS{$B@jR2V@yB7%&(zm;qCaPaZP^gT4g=AH(^l3X@b^U%i=`{y$IB z#Uk&v+l1mp#?|YKFSt!o-dg=kdD`>yZ{J=1lV0WfM>~k~Z%_A;yAN-~9yu*vpPL$= zySFB@WBK~bgO}Y`Pq!D`xVvNi#<;q&?E9zczD=94-a(>xsZs~W)Q%4Ot1^3o&I&Rn z-J7B9cwir6>|67``>hKtYP6LM!`rt%({ef^S|S=Kv#<2G{ab05aKY-u>>cZ@l%BOE zt^2lCPJ}U5u+x&kN@(w^2Biz}N{>FcEm|#C@F!MgpQ{Rov%sMjT22!UL>yQS%@B3z z;Amx(U3Az>aN>)Gr2QN716n#5TwR(xG?aw8I4(@fjov!<$X^xpcR$tanv2-A1>)Vc{4xNo(fri>HOw(;=x}}-&wuo_m1<6owoh6 zJ|6G4^uf`2?LoIT{@8Bx^iguH{L1&&_PXENab&jby;rApJ$W%h2>Z`Uh#Z>ipXe)3j^r>Ez=_}druo&U#|eu=vlkC$srH(PGB?q*2a z>Ew3;Q(j(LvAZbEy~^(Su9Np$1447(z5SkgO2Z}m{C(>eEBD)dJ7gPsY5Lh~bLUx> zJw0ihety1v{l6RP1}4k$4vd(oqJQC&YBbzSG!Q7YY_;| ct6#tEd3X~)r>tU&fD?z}mg)a@x708I0PRcfCIA2c literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000000000000000000000000000000000000..0fea73fcb82c23e784e320a64989dbc1caa0902e GIT binary patch literal 1512 zcmWIYbaQ*a%D@or>J$(bU=hK^z`&pY#Fk*>>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@ma*oz@TsGz{gG^lBy3E?M>Q~fO57Fi77Z*L+#B(5r6Zb7v_3-^I``i3lc*DyI z=Zh+)p2ww^s7+F^oXOy6U}`#X0fUi;P(p)Bi{)zuCeC(ylkr1(x8t!R&o1un?#D0t?<=V6_ub@Tdt~k8{J34KCiXtw{9dbS*Uxi- z?bk~GYgh-a4DpMwtjgv&`AdE6d8^Wsu2XGJ)m-~EXI;pay8hGWZKvM6@n@CZPVH%P z&jd>bP2cJ(|LV*glTv@1T<6QbkJcIq{eE^wWAgEQcH0$2DIZNgl^F2z{CtYIPfMs@1Z-B~9$9?E<5v~Kr(*3adC1TQ((UHn&J zcy;E{g{|g)ED}n;PA+-7Ptg9Tl}rDZKX(rA-S3&=Uh1|X`_bD{u^)d=RF}xjsje;c zV*gb2*)1~dX-n?MDL}7?drV?oWV8RvA+NOH)7_^2r}eG>hdj(&xi0(uz9&~ceO|RM zGI>#@Z_otmV{-Q|yxse&LnwdlhRqx9r%aQtm)!qq&TXli76woMEm80{<&FD$YF5$C z7`^>}u1&4A)74nQY+3bnN#WsketEl^A0Hk%r}t{ER`Jnwultev`Ptdo=K1&bRDM3c c|C#6IoAxJKJTH55D7FYVaVY+||2diy06!7-9smFU literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000000000000000000000000000000000000..3447c5af16e7fb22a94773c9fe3006cb36709a65 GIT binary patch literal 1492 zcmWIYbaOky%D@or>J$(bU=hK^z`&pY#MWTs>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@#$q|V9>Wdz{eoZws4|~dyw1rU60Ry zzh}?ZmV4Wcuk+nrzFTgSmh7m`6F>bi{rmZP{#QFSy5g^1@LwphwWXq3uys<-^zG&X zRwpD{T^Y{&xN*Lt@6Uw098y0w_iRmXaD7~qcz%rMT#2(IMBeTd|UTyRMW-zC*@bS^FN6Md%h)1U;eb&F|K&G zyO{3Ex5xU8uX#2H&bqfM`t{8)-=fS}&+c6PDBIfbQTeZ(*QT$f+b><2`{vMszm6}P z^Nv5=bNi`YCF|~Ecg|dD*s$^4Z4=!a<{vI6oy*SkXV?9lGQ0ih(wk>DTK^H#pY^wR z7VGWall;cvX`UM|{S3~HzjWo<&jlZUTki>cl^XiKe%96>ub%KuN|>_4q#{4F!F2Pt zkn^n0_w`OTY}mYR&m7a_^JUxj?e<|z{CwrTSNpQEd*8O~S|8$l;_~;%`_1)1J?UQxhM_m8@=hf3~youd=Za$T>l>cVGL}6pcQl9?x!CXl>2@A`D1NdPN|z-_Q|C7-!(B=iYXI|-_DQNx1lUG z&;O>>8=cViD?|^wo77kSJ=QC2o)`1~S;~8HuXPh1Ubp%#BkCF`;(BpIM#=2drB4>* npGxMRQ}g0Tr?9%;9E+b9PO{I_wGD8*zv=%K>0k9v{lysoVk7ip literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png new file mode 100644 index 0000000000000000000000000000000000000000..c3804a3def5f1dc905300ff8a9d6e6a70a43482a GIT binary patch literal 2500 zcmeH_X;f3!7Jv_kwy>%QVhd}5ML-~BE-rM)=y}!HfKI`ng z&qerodpBzW5aQ(?6ddGqTnhkT45`n@<>%oMq^}OW0(E_r)z}LF2AhIM__!M%N1ZTM z#XiX?baLV+{u{3bz`_84EC4*Kzxn>3LYmPr$!I8P2GSHfbT|NN(Gcs!{mI{{IOXe4yhqX z1_)?8?hyZ1Wo@1~1^`a;0IbVhi$xUz(2xay{@_~7j1GWyCIIz4iKp0C(*YX^+Zjr=_}+S>{L-3M8Zu5tP>+EY4AuG33mh6=ibANRg#m=III>fM zsbj(-qEXrQ&pnsxF~#|})7-xmXAMp(l?Il%ME1oiIa|IMs=ta%k>ht_6So8Qog4vK!jPC}V^Ka0O+aen{Foee`t#Vg26?v2w3)22g=nfAgbCbBfLqTTha54FHi$N+?*Dtq%>0r=7A1Cv4`1PE7 z2+{m9W)C4b$kd)SoRNx_7@>YSvTwcfXk@Z=+Sv88lIhSuy35bnfx;ROQgG@?WG5pH{@@-HJLeq-Ey1Rbw-N7lDlTUTj2{F%{kx#cUWTv#uJ)-HtYh!O- zv!x7UeqCn;lij!=ZECNWJ8?10M0as$#J9st0H=SYd1KZx8mK1-W2L=>-np3+*ZIKzn{g;-VPF1`AeqUXO-@+5H?-KryT8=vB`|CyJHRD_( zZz&~Viok~IWs6H;?33~-!year7?IccJM{0#FC}T^who(C-+Q#tIA)C`x9){ag5O{* z_g)<_+Yq}#YFb+5msxfF^!@uqtKr4Tb7za)#M`Co86|eb?Zj6?pH5uT@g95{7sj3t zL?j2-$o#8JitJnqaKZ(@?%2WMZ4a+7ekGl=AWjq;RFbNBsaVqB9g^q~8rI_4V_mv= zYodhm?p7lUUr=6gmsF=#rdxg{J)V^mj%gUJlFoM2y+Ma0-`?YSQS0=xKlpPv*(3?!9h6d66DMY2S9!-dt> z!3?FpOE`{Jb$Bisb8FS6(#D0If_0^rq#lJ-gVHincBo2t_m; zziP@3vwHG87)Eko$O8p6t0Yv;vuuRZvUP-_$dzc192l<~RoI`v4frz7JJ@tRaeMe< ze0nEqab^RRd0At#=B(+3cT#-5!BpfAo-SwjJiPLSeM_p`$hv^I?cm)LKHXZPEn8=B#WIxiLrhMk# zAG+PHkjunLAG;K#Mv2+iGrKIFG%vj-vt5=2teH|=Na_w7t*bNn+;&p^>*acJfU;3P z&yzvvq}&LViins48|(_lr#m!w@RhBR6W5v5{PZPVEnA!$k!EvPN$mMfTP9J(gmP~qoAh+^1DiCT zc}6qYrG!Q%?5uY4~-!WCsVC*(mm?1fA|9drJ4Z7pH)+p9~>wF}Y=AIn$%;qL1#`YMga zmkyE>1n=eIyDU);9KPknB6W^O2pgjtDT$@m9uPFQ-jL7EH;Tzgb1*FRmVPGJ+bjF# zhz^Gn0mDxEK82f&7R2Z>Wfb^$7MIdi(SN0&oVoFSS(YW7WLudo+t+Sk7h9wZg!@I` QXMC_JDc~rZB<*Vd0+-`i>u5;=j_=(JNKKJ-<><( z`DW&R`vU_4zBB{ipugYVu)WxD7y%O2pkG(uu3dX=7sIb$vF(CgvJrrU#1#5|ydN^0 z^aXMu_Fkf>j3e*)5BwqkrW63S0LamQ@cqAqmc_&}sBqFtSX1cm;Q%a(f!Uh&8y{WZ z=->G40@Dxd-v#Fs!|X!)9Y_C;p_C&ja8Bn!KJ^HFf%{FpGF!=!d-@{>6Xj6$$ULgZoT^9~y`Uu>c7IK_Z|63{0M2 zBk%xQ;Tsd|Uw z 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 Zg|^eTNwM2XT@Jx#_QACk_3!i7{Ts=oz3>14 literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000000000000000000000000000000000000..1debb946616c95ee6a17594f9cf838689d71f24d GIT binary patch literal 3174 zcmeH_XIPV27J#p!BMJst#K=;mh=WK3ks6$pBA^bvLi&H%9s0H7pPm*0l9nVH@Gt->kTx_{GdI|@KxP#E69(o_j?&P{1E_Ek_m zp}}AIPy7}Dc<+JG0`Tt0pZx!Cp`E_yP#ayMAKzC$3)3L-}jlr5@x3pZ_5d8j`A^$36Y zzdG>$)&YD59ci9JG&i#=Y=msj=oLx-ho5g(>Gp(Kpa9|=B?iKOi#5n`$@-M zvU`N^sz%dNYpLwycrqN*MPOK$$U4J_2d9fvtkrK>QKD8!O47;V%k4=MuD4seh`H1x znfXA>Cy$54P_ko640h!XCU&)2fnx}LA|8P0Xd7jXpWP=}D;jmg zc&96KPNaLLKjeJJvB`;%M{Dbu`Zt%#Hl)#bWq)m*kFe%$Pd4j{WSHiCj;^2)q??$jn(Sp#IthcEdt^M_mFSRE{7sVCxjmn<2J^FJ3rdUTHQ3Y&Vr@Z@3K(oEz@r}yfV}1z2Rmq8gDVRXcG6KPvOgq@P6e> z)pVpoKa$=Nqz?|z!uu}-9c=bFFDbBMF-*w%ykc}tzw{ecY3qq| zgbTJ4-OUjWnHcT>d4MxQpjHG+@^(vFE-g|pr*L|mUdNp%m9layGv35KqETstttY?1 zq~oo1{S;c(EkWV==<$}0I)kI1($FVUq6*swzK?^fLllt#m)2*Ubz69TEQGYy&x1|# zU56nBIdP4{*r0tA9?zY~XpO-E?%Iu^j$CF>+x!bRU2OWoUFzkGsYR?_=jckvXfLfQlbnBu@$`fKh;D919b0klMtrA3X|Fk} znN!W`Yz-)lp3<*h;Ja&zvBND5Gd|7G186PRa1nzm5%r`MWEE^6D=;*>Vlg`DyEYhv zPV7tHL5Xfwz-7|>eW>;f+ozp*l~XB4=DktF@^vr?`a(Q&T{f+gfQryA*)PX>g^9BJ z@k-1Jx7WBI+82GN(WzMBDs#QigM4k+*o z`dWMG{kVmpUN`gXEXnptF1tCd9>?Xk>8LlRns!`cyOKTgZE2krp>-Z*4)&|t*CyF6 z?eVdZ%Y7&C?Fg4-)fhrrC||R&-!P6q_RuJ_JCiAB;Z5apa^9^o*8|eD2$$bn?wIQ& zM4QWaomYwoRtXb%~&-O8Dy9f0FQ3={OSqvAr-_b{qQ;f4o7d0ThoZdr`mY1|(kX`}?+7o1654aJO|g+=d(cc*2$Y4$*=tuiDOEA`cPb#psYKBX1b3 zUcgzXymzCCUSgMbbRr?rR8s^>(zTztLsmPrHzqy%q^7-0l0_PJ+X>{a8hhy*>ad+6 F;9ve>BRc>9 literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json index d8db8d65..65b74d7e 100644 --- a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,98 +1 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/Contents.json b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/Contents.json index da4a164c..73c00596 100644 --- a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/Contents.json +++ b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json new file mode 100644 index 00000000..5b130017 --- /dev/null +++ b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "playstore.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png b/iOS Example Frame Carthage/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..460881f92669088e15815b329ab814ac2462dc79 GIT binary patch literal 33636 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/LaunchScreen.storyboard b/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/LaunchScreen.storyboard index f83f6fd5..f3aeef58 100644 --- a/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/LaunchScreen.storyboard +++ b/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,9 @@ - - + + + - + + @@ -11,15 +13,32 @@ - + - + + + + + + + + + + + + + + + - + + + + diff --git a/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/Main.storyboard b/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/Main.storyboard index a153749b..2a09e621 100644 --- a/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/Main.storyboard +++ b/iOS Example Frame Carthage/iOS Example Frame/Base.lproj/Main.storyboard @@ -1,12 +1,9 @@ - - - - + + - - + @@ -19,25 +16,77 @@ - + + + + + + + + - + + - - + + + + + + + + + - - - - @@ -52,7 +101,7 @@ - + @@ -74,7 +123,7 @@ - + @@ -92,14 +141,14 @@ - + + - @@ -112,7 +161,7 @@ - + @@ -125,4 +174,10 @@ + + + + + + diff --git a/iOS Example Frame Carthage/iOS Example Frame/MainViewController.swift b/iOS Example Frame Carthage/iOS Example Frame/MainViewController.swift index 0514308e..524c8c80 100644 --- a/iOS Example Frame Carthage/iOS Example Frame/MainViewController.swift +++ b/iOS Example Frame Carthage/iOS Example Frame/MainViewController.swift @@ -14,6 +14,12 @@ class MainViewController: UIViewController, CardViewControllerDelegate { @IBOutlet weak var goToPaymentPageButton: UIButton! @IBAction func goToPaymentPage(_ sender: Any) { + cardViewController.isNewUI = false + navigationController?.pushViewController(cardViewController, animated: true) + } + + @IBAction func goToNewPaymentPage(_ sender: Any) { + cardViewController.isNewUI = true navigationController?.pushViewController(cardViewController, animated: true) } @@ -25,31 +31,23 @@ class MainViewController: UIViewController, CardViewControllerDelegate { lazy var cardViewController: CardViewController = { let checkoutAPIClient = CheckoutAPIClient(publicKey: "pk_test_6e40a700-d563-43cd-89d0-f9bb17d35e73", environment: .sandbox) - let b = CardViewController(checkoutApiClient: checkoutAPIClient, cardHolderNameState: .normal, billingDetailsState: .normal, defaultRegionCode: "GB") - b.billingDetailsAddress = CkoAddress(addressLine1: "Test line1", addressLine2: "Test line2", city: "London", state: "London", zip: "N12345", country: "GB") - b.billingDetailsPhone = CkoPhoneNumber(countryCode: "44", number: "77 1234 1234") - b.delegate = self - b.addressViewController.setFields(address: b.billingDetailsAddress!, phone: b.billingDetailsPhone!) - return b + let view = CardViewController(checkoutApiClient: checkoutAPIClient, cardHolderNameState: .normal, billingDetailsState: .normal, defaultRegionCode: "GB") + view.billingDetailsAddress = CkoAddress(addressLine1: "Test line1", addressLine2: "Test line2", city: "London", state: "London", zip: "N12345", country: "GB") + view.billingDetailsPhone = CkoPhoneNumber(countryCode: "44", number: "77 1234 1234") + view.delegate = self + view.addressViewController.setFields(address: view.billingDetailsAddress!, phone: view.billingDetailsPhone!) + view.delegate = self + view.rightBarButtonItem = UIBarButtonItem(title: "Pay", style: .done, target: nil, action: nil) + view.availableSchemes = [.visa, .mastercard, .maestro] + view.setDefault(regionCode: "GB") + view.addressViewController.setCountrySelected(country: "GB", regionCode: "GB") + return view }() @IBAction func onClickGoToPaymentPage(_ sender: Any) { navigationController?.pushViewController(cardViewController, animated: true) } - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - cardViewController.delegate = self - cardViewController.rightBarButtonItem = UIBarButtonItem(title: "Pay", style: .done, target: nil, action: nil) - cardViewController.availableSchemes = [.visa, .mastercard, .maestro] - cardViewController.setDefault(regionCode: "GB") - } - - override func viewDidAppear(_ animated: Bool) { - cardViewController.addressViewController.setCountrySelected(country: "GB", regionCode: "GB") - } - func onTapDone(controller: CardViewController, cardToken: CkoCardTokenResponse?, status: CheckoutTokenStatus) { UIApplication.shared.isNetworkActivityIndicatorVisible = false switch status { diff --git a/iOS Example Frame Carthage/iOS Example Frame/de.lproj/LaunchScreen.strings b/iOS Example Frame Carthage/iOS Example Frame/de.lproj/LaunchScreen.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/iOS Example Frame Carthage/iOS Example Frame/de.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/iOS Example Frame Carthage/iOS Example Frame/fr.lproj/LaunchScreen.strings b/iOS Example Frame Carthage/iOS Example Frame/fr.lproj/LaunchScreen.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/iOS Example Frame Carthage/iOS Example Frame/fr.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/iOS Example Frame Carthage/iOS Example Frame/it.lproj/LaunchScreen.strings b/iOS Example Frame Carthage/iOS Example Frame/it.lproj/LaunchScreen.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/iOS Example Frame Carthage/iOS Example Frame/it.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/iOS Example Frame Carthage/iOS Example Frame/nl.lproj/LaunchScreen.strings b/iOS Example Frame Carthage/iOS Example Frame/nl.lproj/LaunchScreen.strings new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/iOS Example Frame Carthage/iOS Example Frame/nl.lproj/LaunchScreen.strings @@ -0,0 +1 @@ + diff --git a/iOS Example Frame Carthage/iOS Example FrameUITests/iOS_Example_FrameUITests.swift b/iOS Example Frame Carthage/iOS Example FrameUITests/iOS_Example_FrameUITests.swift index 4552f1a1..ad8f1a41 100644 --- a/iOS Example Frame Carthage/iOS Example FrameUITests/iOS_Example_FrameUITests.swift +++ b/iOS Example Frame Carthage/iOS Example FrameUITests/iOS_Example_FrameUITests.swift @@ -33,7 +33,7 @@ class iOS_Example_FrameUITests: XCTestCase { // Use XCTAssert and related functions to verify your tests produce the correct results. let app = XCUIApplication() - app.buttons["Go to payment page"].tap() + app.buttons["OLD"].tap() let elementsQuery = app.scrollViews.otherElements elementsQuery.textFields["4242"].tap() elementsQuery.textFields["4242"].typeText("424242424242424242") From d554c26456e563c6f07a1e9203420bdbc245f69c Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 15:03:11 +0100 Subject: [PATCH 36/55] Support Pods --- iOS Example Frame/Podfile.lock | 8 +- .../AppIcon.appiconset/100.png | Bin 0 -> 3730 bytes .../AppIcon.appiconset/1024.png | Bin 0 -> 122426 bytes .../AppIcon.appiconset/114.png | Bin 0 -> 4426 bytes .../AppIcon.appiconset/120.png | Bin 0 -> 4706 bytes .../AppIcon.appiconset/144.png | Bin 0 -> 5964 bytes .../AppIcon.appiconset/152.png | Bin 0 -> 6668 bytes .../AppIcon.appiconset/167.png | Bin 0 -> 7022 bytes .../AppIcon.appiconset/180.png | Bin 0 -> 7758 bytes .../Assets.xcassets/AppIcon.appiconset/20.png | Bin 0 -> 840 bytes .../Assets.xcassets/AppIcon.appiconset/29.png | Bin 0 -> 946 bytes .../Assets.xcassets/AppIcon.appiconset/40.png | Bin 0 -> 1134 bytes .../Assets.xcassets/AppIcon.appiconset/50.png | Bin 0 -> 1302 bytes .../Assets.xcassets/AppIcon.appiconset/57.png | Bin 0 -> 1460 bytes .../Assets.xcassets/AppIcon.appiconset/58.png | Bin 0 -> 1512 bytes .../Assets.xcassets/AppIcon.appiconset/60.png | Bin 0 -> 1492 bytes .../Assets.xcassets/AppIcon.appiconset/72.png | Bin 0 -> 2500 bytes .../Assets.xcassets/AppIcon.appiconset/76.png | Bin 0 -> 2662 bytes .../Assets.xcassets/AppIcon.appiconset/80.png | Bin 0 -> 2852 bytes .../Assets.xcassets/AppIcon.appiconset/87.png | Bin 0 -> 3174 bytes .../AppIcon.appiconset/App Icon Square.png | Bin 14440 -> 0 bytes .../AppIcon.appiconset/Contents.json | 103 +-------------- .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 4363 -> 0 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 5300 -> 0 bytes .../Icon-App-83.5x83.5@2x.png | Bin 5918 -> 0 bytes .../logo.imageset/Contents.json | 21 +++ .../logo.imageset/playstore.png | Bin 0 -> 33636 bytes .../Base.lproj/LaunchScreen.storyboard | 31 ++++- .../Base.lproj/Main.storyboard | 98 ++++++++------ .../MainViewController.swift | 122 ++++-------------- .../iOS_Example_FrameUITests.swift | 2 +- 31 files changed, 137 insertions(+), 248 deletions(-) create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/144.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/180.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/20.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/50.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/57.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/76.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/80.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png delete mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/App Icon Square.png delete mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png delete mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png delete mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json create mode 100644 iOS Example Frame/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png diff --git a/iOS Example Frame/Podfile.lock b/iOS Example Frame/Podfile.lock index f074c1be..4bf4cda0 100644 --- a/iOS Example Frame/Podfile.lock +++ b/iOS Example Frame/Podfile.lock @@ -1,9 +1,9 @@ PODS: - CheckoutEventLoggerKit (1.2.0) - - Frames (3.5.2): + - Frames (3.5.3): - CheckoutEventLoggerKit (= 1.2.0) - PhoneNumberKit (= 3.3.3) - - Frames/Tests (3.5.2): + - Frames/Tests (3.5.3): - CheckoutEventLoggerKit (= 1.2.0) - PhoneNumberKit (= 3.3.3) - PhoneNumberKit (3.3.3): @@ -28,9 +28,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: CheckoutEventLoggerKit: 03d0076e2aa412df966517a36a3e4e3805b56ecb - Frames: 72b4acd332a7df69872508104e8adf6a3cffe0dd + Frames: bb22a5b0ff4d2c2b163b468eb7ac43411486c8e3 PhoneNumberKit: 4ce83273551c4d2ae10b7361162f4283dd02835f PODFILE CHECKSUM: 0935f6adf6dbf24cd1aebd515551bbce53bef8e5 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/100.png new file mode 100644 index 0000000000000000000000000000000000000000..7a799cd64629cc072c0f07b919a7864c944ed585 GIT binary patch literal 3730 zcmeH`dpMNq7Qo-^o^~#qkV0-7MPxQ3*GVcOQtpOLoLok(qj8JLWmj@bE;~sEh1{7f z%wWdM>68>PZjC)L%?`N?Gn4DcV9wb4>1qG5&vX7c|DCtQq(x_WcvbMnyyk*1XzT?-zmE;c)?<2n&tgIcrCDA{Gk>cXbw6cY!K^ zNZRcdU%mO7CQR`UxqP8+`D>oA{ zbrY7jc5x_OdKy(V9;gn@!C59!%e#?MK5SNHFONgqx|S691ART~kfQGBQQ`J#gT6jMdfU`_4mNjl4ComVHY}Fm}tNthnEknttGdgCn+T&E%5Hu z#ZYPwL?&HqN_u(r0%KLHR+JG_e!}25wWpDHAdJ&DbDPUpxIsh6SU)kCY>D^DZN6Fp z=|3XfBzDVP)dbf7fg`dmEMI$zL8#`M93-+z7!;osw2vN+70`_RbOdX>v9N@s=XI>Q zWX|Mdq@B_&i_IiQhvbEMw?44YnmE@bCEmbb-r)=aLjK8 ziZL;tXAqjJ+p~+xQTdYRUqB~ky%cZ^25Axh(c9^E}kVRbM zLs>oq$B`3${rKJlD}{h}eZQK-9^|AFOp}@>jZ95djB3vLUsRtz+nsPp!wrZ0?3R+@ za3!&JI*Z$Jv7Xi5=aM2VgJ`)vPv1_uGs0f)Y#i3K@mI~2c)!pqesyrH5m6x3<0@qm zanL+wpEGPeVA)CXx?YVtefe;65FSZ_UjMCfhJtfcN7ctrw4HD(*9JqOk|N)BFJagA zj7y=Xrbl8+9OFuT3nLdp4f}>E@n(&(PdYILX^Dh&YkZ{#&n**ntL#kI;9O5rkj}e~ z=XJJE)3_oqRi~yaOpS09HBr7|EF@Ej!zg`6o|$%xF{8LBdMv`g!TVQdz`jKoLG^x@i^`y3-FI@^WpJaqNr zvHNPR@Rm}JoNc})(I1CSFef3&qcY|1yuasR(wHNg#m_p8JpJbbh<3xWEAuNIWiy*F z#$((4kcojcSB<1n{@`5VS<78-?;8(9_r4B-P&Xbkl=1H;KG-S$O0yqjgeuL1#Oh~q zfAK2bNJy;JkQiU66BqQ5B=7Cg&v4`>GwTZG-m)T!@0$AULiTHUBd$S4`m^IWo+~=h zT%#p!l5{ae^P$$Bu0A<=qi_#w6ROmc6#X)$o$SkC#4N*+E2!?&X{}_o$P#^EIE5C) zoae@Gt`uW*4>l`XcfCv;>mzfLi3?$Fy^W{KtuDdpin-i094sl|Qu+S&y%l=lI#;`3 zbQW(l)f=yKBnZ+7c_hrU);m+hfh@ncuLOB>MB0F9SC2_3^`x>1NHI1k?wAEFq1>{^ zNqm&T+~ln^pXPhwN^6rVwK`Z!=5+POr1`VXRjR7@3yqODUV=F}h>R>y8}ruVIXrz_ z@zgl3KYN|j85G6qPYO!<`NRPVv3^41W;Zfp%S+j;KrY?VvcHUp! z&wrRvZ?As*yiRXtmN7afp%|K* z`j6ukzPxcCJZFPG(FKdE(MbIWl}UeNsp`X=eS0^}8HEdD7fos8T3V*U71t9=tK*hQ zR0hr!i?v2U`-|X(hVKGU5k++vZEH3xpdxOE#InJ6DzX=C|jf$SA9a zqBzK2$i9v@FK9>tgFC5j{Y~s*DO*0qB6@?Pn%%b)wFaYD=HL6hf0qqM7sjx#HgsSC zWo|RI2iBS#YR*?~X56kEj_W17_esFZK4c3ujM=qTTjZ9yjIk*_2vG@!oLF1eD;)d{ zDcNBb#b`GRG^dx&X&bRoAN7sGH@h6saU))pGKW#MAN@o%e29yJ|1&2XtBuf)*40?U zE%Vt7?9reY8Z-#P?QB8UrK#7FjyB{PUvKPRKWT=D=U*T*BM9TE76l;zqpRNd#rPCD zWyrlEwb9dGwMs7ge4pgI%vD{pzHm4-Q+|5c{;kV=UOm1om6O<+vhC+?YEPQ9jnv9c zZ#l48Kn*dHuP2mL2?-V6=yFQBX3b+=@-m)9@3VEWKW^z=Elrq?i6&rZQse literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/1024.png new file mode 100644 index 0000000000000000000000000000000000000000..a68fe1ec047a3b50c559f180ef90c4fd9c7e99b1 GIT binary patch literal 122426 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/114.png new file mode 100644 index 0000000000000000000000000000000000000000..d5b97e0936158d6205dc0846d0a3121c07649951 GIT binary patch literal 4426 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 LqP1FUcM0I%9TA&= literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/120.png new file mode 100644 index 0000000000000000000000000000000000000000..55bfd61ee09644aceb4c7ffde2f37d95af5c574e GIT binary patch literal 4706 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 Qw|U`Nfy#nVAXL%%2aJujPXGV_ literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/152.png new file mode 100644 index 0000000000000000000000000000000000000000..763d6430197cc42d962027ff08ad46fe4016a902 GIT binary patch literal 6668 zcmeI1X;_k5yT_m0&8238Ii%*0)-E;8p(1TNmZ_MMCYib&z#M>bfP}&<+g4hRi9@Jq zPMMNJXrj_&=7456q$pG>q#~p!sE8hV-)mp{{cz58zMS)|`+3&7f9rnkb*;7jYpqX@ zn}famS``2|Z)bhhV%Gl@`LkUI!bSvr013CLp8qvtD}`01(K?aJN&|dp)5S z_Wq3hZGHg}m;dJf#;*YYVLu?P0f4Um-+ceyLYo3%5dqSqAJP&TE*%^I)&xpQDCnHz)q&@N;f9(wuxL?+^M9_WuvYL|%@R=6v{>A8c1R^Zz=U6}O=Zv?) zknRwv_mq}BKm_0hoC2(+{C{fy=!q%-fTQyO@LTdfG5;(8sJjgSN<;s|bn*c}J`MoL z-Ix8s{r)wXwbEJ!4hMkQ5&)2e0>F-s0I=EX?}`4?_n*D^AJ)28+Gme+oha!O1cU)F zU@zbRAb|kDKuX5IVZaD5lb#r-mfZkgNO-jmkd4wTSY3l#Sj|h(X-dsTyGOauxP$M9 z$Oy)*meK(adEBW`hO|L`KUt~cqS9w7a^iJ^?jlq-rP`inaq{^5bAyF15Z#}`7-TNT zq3Tb=8xuz3&77EY zzZCeTz%K=UDey~y|1Sk@crFK#L&A-3>1(F1W^vO$_-t7yeG9@q+VaxmG9nIm(3<24;y-pnHleHFh0Cg z%$hKt@>jSaXB4KGz^Sl-AUbVz5?O5<{*s+cBvYDN=Vw#pI-Fi)o@Fu$bFiuBzr9;F zGp)AQH^+xjMo)O;F-9zw-sO9s@5Ms?qHVpq5k{^&>KO42f9K$n!YUsh=Jb!yTkm@v zdCLz#%&^>cttSm%>+`Qn`q1dL`%gNp>a0?2`%^pvV{3+nHjejUgyEPiWdg?X5c{Tx zM9u+sUi}hv#h(ji*Oj^KlY!E9Sw}l``%e0}W>rXn25?kL+>OL0p+kHj=7L@u_(G7d zCNfV6`9rc|Ps%@mSpAl};oZ43=-!hPUpmzWYISwC;sm~ocX7s$q~8t)8=f5ClRCpF z!e?l_yh6+m(etdN;qKDVTpYnyWx2h0^CcabuEsV!Ww}e{-l)DtUUs}^V27^p*o>+- zv!-$AfQnmE&MN9$hn6C)OX49O%~IV3VOE2p4H?W;cX~>U{Z|ve2CND z8W_j~fiZPtJTk7Bj;*<98sopzc6#SSKPZ>XDztANDZ;FTUP8sDJkDNaH=c1RrS(8r!#WvU=?k<__3Ln}n zk3~aVcrV`;7`q4rkrk+nm)lsi1NhNL>EFkaF=9p--Jb`4?HVJ{r}}O&Y01E0Bl&7b z6T_)flOqUrR=BXj+oQ$96ZS5?hT2ie^z;;QSd z`Uh%igN7rKg_>CzXIeVD7zvzd!VsYLSYIh6Nq+ z#1@U}#ouo=&PK``Py{#TrZ?+9Gc-QRF;KlQYWr>lb?lG2Qk!Vj2l@dpYa)>>i8?tk zeOO+Vy-)Emx2@ZV+J>I>e(*iWwVaGua^FDhG`s&1cjDd^(BefZG;0v8Pr|VcG)uM* z-khcIzmwH>r!V^F^GdVU8SCZ~E}#CaFFH7qx0`D|Wodj=Y#;+YP{W~M#)+n-u%7f! zOXeh(_uB?%vx?MkJI2N?BBpZmbE86VTe455yCL~A>MRksrx)8pr1mz!1R2@tSqiW# zL-@?H0~5`8D{C^Q*!vznR;IgihFc;=P#!^{8MElCio0&(!1r5dk}Stl7cBoN?AHM&ZR4&Fe;JJzwSYu#yRsk&9Pn zg!OGhhMK0LBbI^S>9Ojm24|cWbR$e;jWvO)4{aShZgAm>euPOv(8w;W0O12rLz&(> zSSQ4aQyyKdabybQY7e?zz*irzfm$yc)L{8i>N#{qnoF+!qiU-+{=O?Dd5?>tr7XpiK(7*Y2E16 zB~V*kx}D9G0?I=hvcG$0AbX6keh11;&lR~Rqotc}SKvRjZgR0#72D7)dI3p8z5H(A zGsW8uB`DX>H9j4Dk<*V(!cgHJRUckGwb7Udg;B3D@ebzRl%;3rt4UR*_UqPal}*n+ zpYmZ{Yo#5aGjgw-UsE^TW+9j3#SXy}X{F}fZJCJ*vviC4T26FP+FxTv5fD=GR*0;n zj>4xUc+N7uYrw2b#O%3^xiUyRrIj90GJ@l+@+>M3SGOF7N%u&gVh3wLlV19Udh~r( z$HJ9SIGQ92WKjI>+Z~Bg3W`_=ZJc_{H?z_TsGb}Gy{tRsTqZD~z6d5p?+2&^0*^HC$Izmin#DsQEI(2GPXN42Ag-5m> z=48uqV3cSlJ>g(>*|*eODy*&-iOzX3i+y!yx6HQS?ZPYyf~t`;zn5fNkc{ok>Fb!2 zBpR_~6mDed4kkNgp)|LbBV=Xn*dansX6-drl);VhL=tfY-ZI)H$)Kr5!Zz4Po(!@w zKYD#mPNnbkTpFun08O{^e09#dE~XRy#`(dJ{Nrp$33I$|>12)b$W!ltoZ^Azv}8bM zryIZNZ4R~(k!!5&hn@OrRWtluJbz7euU&Nngfj$RGj~5JpIN<|#6%jI%A}OKYWFnL zvxaVN54Da;X?A~oMYcVK4<|GkBot=|_}^~x^z-U!RiECvD}TK4Ibps{=eS90Qx1c_ zV28V%A-(lI-g_(~Le~3C+AtAE4aG6Oq)BL*^mYbdHW#!PP0yGwYDr=ToavQE%KNjt zDJ5cNUEGCZFhi>GLJ?xgjeK#*)QfdZ!0OhR%Z|bb7nVSSe(Hs`V2_&YrK|GD@4+)? z;`jev@p9AWSqp?vf-M%?%?pHj+^fT4jTECDcVnRP__|hJd~)U$5V41xnSD;fy4b6> zn_fE|>5-#2k~E=_Jl-Id#C+7gn5+v)I3sDU4ElK z%D*+%sr06*A*CiBd-gPuv}jisPm@`*X^Im~m7wQ|W+k1MKyba3jj#rA>L$Ww$ZN%s zJ6U`ROM9}jw6A4y@v7ee6CE|9ihW zDyP+x{UN=r&69gLiNQ}|@akjQcTXn`PTc1E-uT>wJ9I=CLN0bK z9y$Bf{GO>o39Ik?di{ywsftn9lxR=FALs#mXE&V~!-;1OWWGNb6txT$Q)y-q49j?$ zf0{%B6}M#QAtT3$Y9<|L4k-nP&-SPfV_Tz(YI=IZdnsiQh-A2MA)tzJf;&fPX8G03 zy2g*9RFdsK^xOH*P{Irv1dmx9+c`%vf2>e$CDR$pugC-0ik%hjD2}*H@QIWc)n}~A zIr%!OeJQJojFrlc0*99?VBZPeCn!eYD*4i7!Z2yxL!M<7F&VE6Zgc>kYmShpbTRLF zeplZLIVS~`yV2DO`ivKqaKgK?LyIlw7Oi+z*Dj0DhV480zt-%Za69@m6RNeo zY5Xs-n5f2nxck1rXMqAL7wmgPDC93owb!O5Z5;1yT7KNLW}<GuX~IsH5kOUZ7lU69fr|q@!4P{vRm~yBE?A*EL=9Mwk4UvczctWn18*j3w3+D}neCD-- za7`e`F^lbM1S$c@<1X}PVuu(Kv@*Fa^Ne=69@g!4XxUh71bRh%8MCWRyyx8c-nXV<~HlEi%0P7Jt$9&4YPB4U#s7P?mt{Rou40j@P zqjt(_mv~0}cv@HT&^QQf>`f{S?7V&Y=)wqcR)R02IJbMD?YV>!3hVN|O3$tMj)F?a zlPRb>ZMS?(LR1Wu#ebe}StllN2fw0H_9=27d#vAI$h=17hw6lk-N!siXc!BdW(#T^ zd9K>!$BzuU6g&aV@Zo&E*P*FY$Z>oLX!VD>o^@6gft=NNmaWq;(zkwbwGm*3+@uOO%#a_2ounx5`Mp-WHSCi&yV>qx%`-MhcpP u6jGomTf(Qd&b+o9Bs@#(bJw^q8HGO_kd|nt^J0}aW4LuywCXGUzw=+h03~4n literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/167.png new file mode 100644 index 0000000000000000000000000000000000000000..71255c59723f15fad9a7d3f28c375c9188e514f7 GIT binary patch literal 7022 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/29.png new file mode 100644 index 0000000000000000000000000000000000000000..870abebc982ee65de85cc42eee2ea69a149a3b3e GIT binary patch literal 946 zcmWIYbaPw9%)k)t>J$(bU=hK^z`&pY#4=#y>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@yTIiV9=LgU}va5v>;c-ee%iL^%nE& z_b-3ApjXA+Z`;N51s}2r?U!FTL!Voh`-8-tf_gdK+{S5t3%e9{bTO>s5KKN? zb)TW2bYI@OTScblPHwu#pOC{K$S@IT*2D%62L^}jxwk8lw|nN^-ZpiK{I9d$>*xHM zvS0bv`UAPrsXfQPbHV}zjsB$KIZ5SYQcTU+GBaCiOH<>`ANTBOm>Vwr`r9`1@78Wh z<~yflrRKFC4_c~W*Dor*cHQjvJnK#={k-S=Z2J0J$$KuVpMHN@cljreeZPNbdh3|k zyuNTE`tPPamoC?Q({T#1OG2oOSt#h~UnB0|$;1A47%B}16TKTP}e&X!Pj5YQ* jZri?+s^2#=;8#jUO+`sg%GaN-oYy~`eeYuZUtR_PfQR*` literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/40.png new file mode 100644 index 0000000000000000000000000000000000000000..d3412d3f2100eefc701122fcadaf19e137c2ad40 GIT binary patch literal 1134 zcmWIYbaP8%VPFV%bqWXzu!!JdU|>)HVs$X`baoDqU;=U(m?S_Xiva^eZeB@Ikh_yY zL}Zi#NDKxNlZy*rY%DY*1H-p#3_y~B;j%6kc|t;*DXGQDKt&&bxTFYZIRgV@3Xm<5 z4q;b-*hvs}4~Sh9666e2vjE7}NJnBPA+gI#3QB-#PJq-W7ZicmcYti0+?-O7T_6B* zF;8keKg93vmLmopigC3A +W+$Y2IcF+S?R^r5eQfRo|;V}(g7uB%pA)~Nl@ zif=h=Hc7-X;;QZO^9&m&s<;NZ>B`theg3!m+vof3Ke&ZAubqDAZPj5FueqswQgfFq zP!Q^2%24rW+BrwR^<{#PiXjJEXApyd&;q4|mX|uk75nURU#H&XyM5=3y=1CYY0)&x zj8}?=B2%2sz5mZ`JaeYAV*pTbfLpUqdbD2u^Y)jH#SN<_rejl-S#4IbG`4Q*M_{wk*rD+36-f@A=<*?|=N1KXf^4w&36J z2itlteeC-v2n#_XX)VQL63IOqXQ};s|0m?4l9HT~KVQwSvYeb|UK(Rt{qN7r z;`Uq1QtJC3+?*(J`ynnuplXbbg=JFG( z*Loj(aBpkPrfSpE!nZ`e^=P=d&wDK=6m-kRPOt%`YQ$~Biz|x$bm~4f^)q^Gef`w2?fOrX zcXw~?oAl$4v-a*b(K!`S@3o%pt9kL~-=hgmihE-J@2rat>Rb2x$-$k=H1F)1c;m_O zwr|)HVnZGB z4}|FqISi=`3JjhMc?`)6dO(&Dg8?v!m;qCa&jn!m&^L78VYtq+aiWTAP}()aU+>@C zZ5HOcZC3PT!IGJK&oeqndrn$XaP8f_^N)TQ+uZ&0ouTgV0e%J!7R8@Zj>hcGB3=`V zZ!FemV__EQWJ*x+OHt`~k}c#qkwJpF zU-6Xh|8IYsGfT>~X{Dyff&jj1zUMh^D?JUmHn9aW%#vbU%&0Qsze&SCW`&pAwr%x` z`M~uqAiuD@{JWEEdHM1kpC?Xuw&{OvZoy^=!>$+mnYQOnk?rZr|G*9lVXDv*{`D== z=mMg;VXEL)|USK(UIe-`Z8Tx93fG$HF&Xe}7*rDJzdH&bmt*X1(3&e`It&_C4dx0&y zJHEXC{pd69{1U=myYjDxxs0sJO83tLi)@bpPrQ-Zoi{bbv5#**?mQ2xrKkae&h>9mH)oC zA-`auj?VKBZ}Ly-r)&KdGCw7^ygnsi?)>F);(OO-NpCvGD{bub+z? zG@IFUvgYYBJNJ$(bU=hK^z`&pY#1>%W>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6U;1OF=n1M>ugSkg=ehV88k3=+2xVk!$5 z82DQl7`B}+NGwVOJB9^FGNq+4Fnn6hz`z^Hz#x2qfq^R;=1_!QL|owTs{&Au4A7tX zK$y;u!;s3Lz~IS{$B@jR2V@yB7%&(zm;qCaPaZP^gT4g=AH(^l3X@b^U%i=`{y$IB z#Uk&v+l1mp#?|YKFSt!o-dg=kdD`>yZ{J=1lV0WfM>~k~Z%_A;yAN-~9yu*vpPL$= zySFB@WBK~bgO}Y`Pq!D`xVvNi#<;q&?E9zczD=94-a(>xsZs~W)Q%4Ot1^3o&I&Rn z-J7B9cwir6>|67``>hKtYP6LM!`rt%({ef^S|S=Kv#<2G{ab05aKY-u>>cZ@l%BOE zt^2lCPJ}U5u+x&kN@(w^2Biz}N{>FcEm|#C@F!MgpQ{Rov%sMjT22!UL>yQS%@B3z z;Amx(U3Az>aN>)Gr2QN716n#5TwR(xG?aw8I4(@fjov!<$X^xpcR$tanv2-A1>)Vc{4xNo(fri>HOw(;=x}}-&wuo_m1<6owoh6 zJ|6G4^uf`2?LoIT{@8Bx^iguH{L1&&_PXENab&jby;rApJ$W%h2>Z`Uh#Z>ipXe)3j^r>Ez=_}druo&U#|eu=vlkC$srH(PGB?q*2a z>Ew3;Q(j(LvAZbEy~^(Su9Np$1447(z5SkgO2Z}m{C(>eEBD)dJ7gPsY5Lh~bLUx> zJw0ihety1v{l6RP1}4k$4vd(oqJQC&YBbzSG!Q7YY_;| ct6#tEd3X~)r>tU&fD?z}mg)a@x708I0PRcfCIA2c literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/58.png new file mode 100644 index 0000000000000000000000000000000000000000..0fea73fcb82c23e784e320a64989dbc1caa0902e GIT binary patch literal 1512 zcmWIYbaQ*a%D@or>J$(bU=hK^z`&pY#Fk*>>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@ma*oz@TsGz{gG^lBy3E?M>Q~fO57Fi77Z*L+#B(5r6Zb7v_3-^I``i3lc*DyI z=Zh+)p2ww^s7+F^oXOy6U}`#X0fUi;P(p)Bi{)zuCeC(ylkr1(x8t!R&o1un?#D0t?<=V6_ub@Tdt~k8{J34KCiXtw{9dbS*Uxi- z?bk~GYgh-a4DpMwtjgv&`AdE6d8^Wsu2XGJ)m-~EXI;pay8hGWZKvM6@n@CZPVH%P z&jd>bP2cJ(|LV*glTv@1T<6QbkJcIq{eE^wWAgEQcH0$2DIZNgl^F2z{CtYIPfMs@1Z-B~9$9?E<5v~Kr(*3adC1TQ((UHn&J zcy;E{g{|g)ED}n;PA+-7Ptg9Tl}rDZKX(rA-S3&=Uh1|X`_bD{u^)d=RF}xjsje;c zV*gb2*)1~dX-n?MDL}7?drV?oWV8RvA+NOH)7_^2r}eG>hdj(&xi0(uz9&~ceO|RM zGI>#@Z_otmV{-Q|yxse&LnwdlhRqx9r%aQtm)!qq&TXli76woMEm80{<&FD$YF5$C z7`^>}u1&4A)74nQY+3bnN#WsketEl^A0Hk%r}t{ER`Jnwultev`Ptdo=K1&bRDM3c c|C#6IoAxJKJTH55D7FYVaVY+||2diy06!7-9smFU literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/60.png new file mode 100644 index 0000000000000000000000000000000000000000..3447c5af16e7fb22a94773c9fe3006cb36709a65 GIT binary patch literal 1492 zcmWIYbaOky%D@or>J$(bU=hK^z`&pY#MWTs>FgXJ!35+oFiC(&76S%`+`N*aAa^H) zh{z}fkQfXkCKngL*jQ*r28M6f7=R=L!)0A8@`QvqQ&NkQfr>r=aY+%-as~#*6d+q9 z9m1{vv6CR|9uT`IB*+=4W&x0`k&eVpLSmPf6qEqfoB*j$E+_)A?*Q30xjCgEyFdWs zVxH8z&|n}P0mL#4#SB3V?hH;qHdO&4Jo6VZFj#zLU|^nr5KEfLz_7iQfkEOHLQG`= z0|S2x1H-oS1&Kw8V8^fkNv56c{`i@)(jC^nffQ1_K5|1~Xua@#$q|V9>Wdz{eoZws4|~dyw1rU60Ry zzh}?ZmV4Wcuk+nrzFTgSmh7m`6F>bi{rmZP{#QFSy5g^1@LwphwWXq3uys<-^zG&X zRwpD{T^Y{&xN*Lt@6Uw098y0w_iRmXaD7~qcz%rMT#2(IMBeTd|UTyRMW-zC*@bS^FN6Md%h)1U;eb&F|K&G zyO{3Ex5xU8uX#2H&bqfM`t{8)-=fS}&+c6PDBIfbQTeZ(*QT$f+b><2`{vMszm6}P z^Nv5=bNi`YCF|~Ecg|dD*s$^4Z4=!a<{vI6oy*SkXV?9lGQ0ih(wk>DTK^H#pY^wR z7VGWall;cvX`UM|{S3~HzjWo<&jlZUTki>cl^XiKe%96>ub%KuN|>_4q#{4F!F2Pt zkn^n0_w`OTY}mYR&m7a_^JUxj?e<|z{CwrTSNpQEd*8O~S|8$l;_~;%`_1)1J?UQxhM_m8@=hf3~youd=Za$T>l>cVGL}6pcQl9?x!CXl>2@A`D1NdPN|z-_Q|C7-!(B=iYXI|-_DQNx1lUG z&;O>>8=cViD?|^wo77kSJ=QC2o)`1~S;~8HuXPh1Ubp%#BkCF`;(BpIM#=2drB4>* npGxMRQ}g0Tr?9%;9E+b9PO{I_wGD8*zv=%K>0k9v{lysoVk7ip literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/72.png new file mode 100644 index 0000000000000000000000000000000000000000..c3804a3def5f1dc905300ff8a9d6e6a70a43482a GIT binary patch literal 2500 zcmeH_X;f3!7Jv_kwy>%QVhd}5ML-~BE-rM)=y}!HfKI`ng z&qerodpBzW5aQ(?6ddGqTnhkT45`n@<>%oMq^}OW0(E_r)z}LF2AhIM__!M%N1ZTM z#XiX?baLV+{u{3bz`_84EC4*Kzxn>3LYmPr$!I8P2GSHfbT|NN(Gcs!{mI{{IOXe4yhqX z1_)?8?hyZ1Wo@1~1^`a;0IbVhi$xUz(2xay{@_~7j1GWyCIIz4iKp0C(*YX^+Zjr=_}+S>{L-3M8Zu5tP>+EY4AuG33mh6=ibANRg#m=III>fM zsbj(-qEXrQ&pnsxF~#|})7-xmXAMp(l?Il%ME1oiIa|IMs=ta%k>ht_6So8Qog4vK!jPC}V^Ka0O+aen{Foee`t#Vg26?v2w3)22g=nfAgbCbBfLqTTha54FHi$N+?*Dtq%>0r=7A1Cv4`1PE7 z2+{m9W)C4b$kd)SoRNx_7@>YSvTwcfXk@Z=+Sv88lIhSuy35bnfx;ROQgG@?WG5pH{@@-HJLeq-Ey1Rbw-N7lDlTUTj2{F%{kx#cUWTv#uJ)-HtYh!O- zv!x7UeqCn;lij!=ZECNWJ8?10M0as$#J9st0H=SYd1KZx8mK1-W2L=>-np3+*ZIKzn{g;-VPF1`AeqUXO-@+5H?-KryT8=vB`|CyJHRD_( zZz&~Viok~IWs6H;?33~-!year7?IccJM{0#FC}T^who(C-+Q#tIA)C`x9){ag5O{* z_g)<_+Yq}#YFb+5msxfF^!@uqtKr4Tb7za)#M`Co86|eb?Zj6?pH5uT@g95{7sj3t zL?j2-$o#8JitJnqaKZ(@?%2WMZ4a+7ekGl=AWjq;RFbNBsaVqB9g^q~8rI_4V_mv= zYodhm?p7lUUr=6gmsF=#rdxg{J)V^mj%gUJlFoM2y+Ma0-`?YSQS0=xKlpPv*(3?!9h6d66DMY2S9!-dt> z!3?FpOE`{Jb$Bisb8FS6(#D0If_0^rq#lJ-gVHincBo2t_m; zziP@3vwHG87)Eko$O8p6t0Yv;vuuRZvUP-_$dzc192l<~RoI`v4frz7JJ@tRaeMe< ze0nEqab^RRd0At#=B(+3cT#-5!BpfAo-SwjJiPLSeM_p`$hv^I?cm)LKHXZPEn8=B#WIxiLrhMk# zAG+PHkjunLAG;K#Mv2+iGrKIFG%vj-vt5=2teH|=Na_w7t*bNn+;&p^>*acJfU;3P z&yzvvq}&LViins48|(_lr#m!w@RhBR6W5v5{PZPVEnA!$k!EvPN$mMfTP9J(gmP~qoAh+^1DiCT zc}6qYrG!Q%?5uY4~-!WCsVC*(mm?1fA|9drJ4Z7pH)+p9~>wF}Y=AIn$%;qL1#`YMga zmkyE>1n=eIyDU);9KPknB6W^O2pgjtDT$@m9uPFQ-jL7EH;Tzgb1*FRmVPGJ+bjF# zhz^Gn0mDxEK82f&7R2Z>Wfb^$7MIdi(SN0&oVoFSS(YW7WLudo+t+Sk7h9wZg!@I` QXMC_JDc~rZB<*Vd0+-`i>u5;=j_=(JNKKJ-<><( z`DW&R`vU_4zBB{ipugYVu)WxD7y%O2pkG(uu3dX=7sIb$vF(CgvJrrU#1#5|ydN^0 z^aXMu_Fkf>j3e*)5BwqkrW63S0LamQ@cqAqmc_&}sBqFtSX1cm;Q%a(f!Uh&8y{WZ z=->G40@Dxd-v#Fs!|X!)9Y_C;p_C&ja8Bn!KJ^HFf%{FpGF!=!d-@{>6Xj6$$ULgZoT^9~y`Uu>c7IK_Z|63{0M2 zBk%xQ;Tsd|Uw z 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 Zg|^eTNwM2XT@Jx#_QACk_3!i7{Ts=oz3>14 literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/87.png new file mode 100644 index 0000000000000000000000000000000000000000..1debb946616c95ee6a17594f9cf838689d71f24d GIT binary patch literal 3174 zcmeH_XIPV27J#p!BMJst#K=;mh=WK3ks6$pBA^bvLi&H%9s0H7pPm*0l9nVH@Gt->kTx_{GdI|@KxP#E69(o_j?&P{1E_Ek_m zp}}AIPy7}Dc<+JG0`Tt0pZx!Cp`E_yP#ayMAKzC$3)3L-}jlr5@x3pZ_5d8j`A^$36Y zzdG>$)&YD59ci9JG&i#=Y=msj=oLx-ho5g(>Gp(Kpa9|=B?iKOi#5n`$@-M zvU`N^sz%dNYpLwycrqN*MPOK$$U4J_2d9fvtkrK>QKD8!O47;V%k4=MuD4seh`H1x znfXA>Cy$54P_ko640h!XCU&)2fnx}LA|8P0Xd7jXpWP=}D;jmg zc&96KPNaLLKjeJJvB`;%M{Dbu`Zt%#Hl)#bWq)m*kFe%$Pd4j{WSHiCj;^2)q??$jn(Sp#IthcEdt^M_mFSRE{7sVCxjmn<2J^FJ3rdUTHQ3Y&Vr@Z@3K(oEz@r}yfV}1z2Rmq8gDVRXcG6KPvOgq@P6e> z)pVpoKa$=Nqz?|z!uu}-9c=bFFDbBMF-*w%ykc}tzw{ecY3qq| zgbTJ4-OUjWnHcT>d4MxQpjHG+@^(vFE-g|pr*L|mUdNp%m9layGv35KqETstttY?1 zq~oo1{S;c(EkWV==<$}0I)kI1($FVUq6*swzK?^fLllt#m)2*Ubz69TEQGYy&x1|# zU56nBIdP4{*r0tA9?zY~XpO-E?%Iu^j$CF>+x!bRU2OWoUFzkGsYR?_=jckvXfLfQlbnBu@$`fKh;D919b0klMtrA3X|Fk} znN!W`Yz-)lp3<*h;Ja&zvBND5Gd|7G186PRa1nzm5%r`MWEE^6D=;*>Vlg`DyEYhv zPV7tHL5Xfwz-7|>eW>;f+ozp*l~XB4=DktF@^vr?`a(Q&T{f+gfQryA*)PX>g^9BJ z@k-1Jx7WBI+82GN(WzMBDs#QigM4k+*o z`dWMG{kVmpUN`gXEXnptF1tCd9>?Xk>8LlRns!`cyOKTgZE2krp>-Z*4)&|t*CyF6 z?eVdZ%Y7&C?Fg4-)fhrrC||R&-!P6q_RuJ_JCiAB;Z5apa^9^o*8|eD2$$bn?wIQ& zM4QWaomYwoRtXb%~&-O8Dy9f0FQ3={OSqvAr-_b{qQ;f4o7d0ThoZdr`mY1|(kX`}?+7o1654aJO|g+=d(cc*2$Y4$*=tuiDOEA`cPb#psYKBX1b3 zUcgzXymzCCUSgMbbRr?rR8s^>(zTztLsmPrHzqy%q^7-0l0_PJ+X>{a8hhy*>ad+6 F;9ve>BRc>9 literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/App Icon Square.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/App Icon Square.png deleted file mode 100644 index c072e7ce1d754bd11250f4aef91deae0e38f4bc9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14440 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 O0LS%=kEZL|-THs5y1`8V diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json index 9176d1e7..65b74d7e 100644 --- a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,102 +1 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "Icon-App-60x60@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "Icon-App-76x76@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "Icon-App-83.5x83.5@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "App Icon Square.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} +{"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"72x72","expected-size":"72","filename":"72.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"76x76","expected-size":"152","filename":"152.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"50x50","expected-size":"100","filename":"100.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"76x76","expected-size":"76","filename":"76.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"50x50","expected-size":"50","filename":"50.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"72x72","expected-size":"144","filename":"144.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"40x40","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"83.5x83.5","expected-size":"167","filename":"167.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"},{"size":"20x20","expected-size":"20","filename":"20.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"1x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"ipad","scale":"2x"}]} \ No newline at end of file diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index 9aa026a81bdc6caf065e09bdad118b03ed505d23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4363 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 diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index 94cb1cf49e4af7e16707733e091db61e617bea56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5918 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 Ra_|27Lgis{)iUOx{{o!o<5d6v diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json b/iOS Example Frame/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json new file mode 100644 index 00000000..5b130017 --- /dev/null +++ b/iOS Example Frame/iOS Example Frame/Assets.xcassets/logo.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "playstore.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS Example Frame/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png b/iOS Example Frame/iOS Example Frame/Assets.xcassets/logo.imageset/playstore.png new file mode 100644 index 0000000000000000000000000000000000000000..460881f92669088e15815b329ab814ac2462dc79 GIT binary patch literal 33636 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 literal 0 HcmV?d00001 diff --git a/iOS Example Frame/iOS Example Frame/Base.lproj/LaunchScreen.storyboard b/iOS Example Frame/iOS Example Frame/Base.lproj/LaunchScreen.storyboard index f83f6fd5..f3aeef58 100644 --- a/iOS Example Frame/iOS Example Frame/Base.lproj/LaunchScreen.storyboard +++ b/iOS Example Frame/iOS Example Frame/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,9 @@ - - + + + - + + @@ -11,15 +13,32 @@ - + - + + + + + + + + + + + + + + + - + + + + diff --git a/iOS Example Frame/iOS Example Frame/Base.lproj/Main.storyboard b/iOS Example Frame/iOS Example Frame/Base.lproj/Main.storyboard index f766de00..2a09e621 100644 --- a/iOS Example Frame/iOS Example Frame/Base.lproj/Main.storyboard +++ b/iOS Example Frame/iOS Example Frame/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -16,54 +16,77 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - @@ -152,6 +175,7 @@ + diff --git a/iOS Example Frame/iOS Example Frame/MainViewController.swift b/iOS Example Frame/iOS Example Frame/MainViewController.swift index fef76834..524c8c80 100644 --- a/iOS Example Frame/iOS Example Frame/MainViewController.swift +++ b/iOS Example Frame/iOS Example Frame/MainViewController.swift @@ -9,101 +9,50 @@ import UIKit import Frames -class MainViewController: UIViewController, CardViewControllerDelegate, ThreedsWebViewControllerDelegate { - +class MainViewController: UIViewController, CardViewControllerDelegate { + @IBOutlet weak var goToPaymentPageButton: UIButton! - @IBOutlet weak var createTokenWithApplePay: UIButton! - @IBOutlet weak var threeDSURLTextField: UITextField! - - private static let successURL = URL(string: "https://httpstat.us/200")! - private static let failureURL = URL(string: "https://httpstat.us/403")! - // Step1 : create instance of CheckoutAPIClient - let checkoutAPIClient = CheckoutAPIClient(publicKey: "pk_test_6e40a700-d563-43cd-89d0-f9bb17d35e73", - environment: .sandbox) - @IBAction func goToPaymentPage(_ sender: Any) { + cardViewController.isNewUI = false navigationController?.pushViewController(cardViewController, animated: true) } - - + + @IBAction func goToNewPaymentPage(_ sender: Any) { + cardViewController.isNewUI = true + navigationController?.pushViewController(cardViewController, animated: true) + } + + func onSubmit(controller: CardViewController) { UIApplication.shared.isNetworkActivityIndicatorVisible = true } lazy var cardViewController: CardViewController = { - let b = CardViewController(checkoutApiClient: checkoutAPIClient, cardHolderNameState: .normal, billingDetailsState: .required, defaultRegionCode: "GB") - b.billingDetailsAddress = CkoAddress(addressLine1: "Test line1", addressLine2: "Test line2", city: "London", state: "London", zip: "N12345", country: "GB") - b.billingDetailsPhone = CkoPhoneNumber(countryCode: "44", number: "77 1234 1234") - b.delegate = self - b.addressViewController.setFields(address: b.billingDetailsAddress!, phone: b.billingDetailsPhone!) - return b + let checkoutAPIClient = CheckoutAPIClient(publicKey: "pk_test_6e40a700-d563-43cd-89d0-f9bb17d35e73", + environment: .sandbox) + let view = CardViewController(checkoutApiClient: checkoutAPIClient, cardHolderNameState: .normal, billingDetailsState: .normal, defaultRegionCode: "GB") + view.billingDetailsAddress = CkoAddress(addressLine1: "Test line1", addressLine2: "Test line2", city: "London", state: "London", zip: "N12345", country: "GB") + view.billingDetailsPhone = CkoPhoneNumber(countryCode: "44", number: "77 1234 1234") + view.delegate = self + view.addressViewController.setFields(address: view.billingDetailsAddress!, phone: view.billingDetailsPhone!) + view.delegate = self + view.rightBarButtonItem = UIBarButtonItem(title: "Pay", style: .done, target: nil, action: nil) + view.availableSchemes = [.visa, .mastercard, .maestro] + view.setDefault(regionCode: "GB") + view.addressViewController.setCountrySelected(country: "GB", regionCode: "GB") + return view }() @IBAction func onClickGoToPaymentPage(_ sender: Any) { navigationController?.pushViewController(cardViewController, animated: true) } - @IBAction func onClickGoTokenWithApplePay(_ sender: Any) { - - // Use example Apple Pay payment data. - guard let paymentDataURL = Bundle.main.url( - forResource: "example_apple_pay_payment_data", - withExtension: "json") else { - print("Unable to get URL of Apple Pay payment data.") - return - } - - let paymentData: Data - do { - paymentData = try Data(contentsOf: paymentDataURL) - } catch { - print(error.localizedDescription) - return - } - - checkoutAPIClient.createApplePayToken(paymentData: paymentData) { status in - switch status { - case .failure(let error): - self.showAlert(with: error.localizedDescription) - case .success(let CkoCardTokenResponse): - self.showAlert(with: CkoCardTokenResponse.token) - } - } - - } - - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - cardViewController.delegate = self - cardViewController.rightBarButtonItem = UIBarButtonItem(title: "Pay", style: .done, target: nil, action: nil) - cardViewController.availableSchemes = [.visa, .mastercard, .maestro] - cardViewController.setDefault(regionCode: "GB") - } - - override func viewDidAppear(_ animated: Bool) { - cardViewController.addressViewController.setCountrySelected(country: "GB", regionCode: "GB") - } - func onTapDone(controller: CardViewController, cardToken: CkoCardTokenResponse?, status: CheckoutTokenStatus) { UIApplication.shared.isNetworkActivityIndicatorVisible = false switch status { case .success: - - // **** For testing only. **** - print("addressLine1 : \(cardToken?.billingAddress?.addressLine1 ?? "")") - print("addressLine2 : \(cardToken?.billingAddress?.addressLine2 ?? "")") - print("countryCode \(cardToken?.phone?.countryCode ?? "")") - print("phone number \(cardToken?.phone?.number ?? "")") - // **** For testing only. **** - - guard let cardToken = cardToken else { - self.showAlert(with: "Token object is nil") - return - } - self.showAlert(with: cardToken.token) - + self.showAlert(with: cardToken!.token) case .failure: print("failure") } @@ -118,27 +67,4 @@ class MainViewController: UIViewController, CardViewControllerDelegate, ThreedsW alert.addAction(action) self.present(alert, animated: true, completion: nil) } - - - @IBAction func onStart3DS(_ sender: Any) { - guard let threeDSURLString = threeDSURLTextField.text?.trimmingCharacters(in: .whitespacesAndNewlines), - let threeDSURL = URL(string: threeDSURLString) else { - showAlert(with: "3DS URL could not be parsed") - return - } - - let threedsWebViewController = ThreedsWebViewController(successUrl: Self.successURL, failUrl: Self.failureURL) - threedsWebViewController.delegate = self - threedsWebViewController.url = threeDSURL.absoluteString - - present(threedsWebViewController, animated: true, completion: nil) - } - - func threeDSWebViewControllerAuthenticationDidSucceed(_ threeDSWebViewController: ThreedsWebViewController, token: String?) { - showAlert(with: "3DS success, token: \(token ?? "nil")") - } - - func threeDSWebViewControllerAuthenticationDidFail(_ threeDSWebViewController: ThreedsWebViewController) { - showAlert(with: "3DS Fail") - } } diff --git a/iOS Example Frame/iOS Example FrameUITests/iOS_Example_FrameUITests.swift b/iOS Example Frame/iOS Example FrameUITests/iOS_Example_FrameUITests.swift index 4552f1a1..ad8f1a41 100644 --- a/iOS Example Frame/iOS Example FrameUITests/iOS_Example_FrameUITests.swift +++ b/iOS Example Frame/iOS Example FrameUITests/iOS_Example_FrameUITests.swift @@ -33,7 +33,7 @@ class iOS_Example_FrameUITests: XCTestCase { // Use XCTAssert and related functions to verify your tests produce the correct results. let app = XCUIApplication() - app.buttons["Go to payment page"].tap() + app.buttons["OLD"].tap() let elementsQuery = app.scrollViews.otherElements elementsQuery.textFields["4242"].tap() elementsQuery.textFields["4242"].typeText("424242424242424242") From 3fa1922d9d8f5b4884380e865d370f5b42549b5c Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 15:37:39 +0100 Subject: [PATCH 37/55] Update `checkoutEventLoggerKitVersion` to `1.2.0` --- .../iOS Example Frame Carthage.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj b/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj index 7f2a52e4..1be8e81e 100644 --- a/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj +++ b/iOS Example Frame Carthage/iOS Example Frame Carthage.xcodeproj/project.pbxproj @@ -1687,7 +1687,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "checkoutEventLoggerKitVersion=\"1.1.1\"\nzipDownload=\"CheckoutEventLoggerKit.zip\"\n\ncurl -L \"https://github.com/checkout/checkout-event-logger-ios-framework/archive/refs/tags/$checkoutEventLoggerKitVersion.zip\" > $zipDownload\nunzip $zipDownload\ncp -r \"checkout-event-logger-ios-framework-$checkoutEventLoggerKitVersion/CheckoutEventLoggerKit.xcframework\" .\nrm -r \"checkout-event-logger-ios-framework-$checkoutEventLoggerKitVersion\"\nrm $zipDownload\n"; + shellScript = "checkoutEventLoggerKitVersion=\"1.2.0\"\nzipDownload=\"CheckoutEventLoggerKit.zip\"\n\ncurl -L \"https://github.com/checkout/checkout-event-logger-ios-framework/archive/refs/tags/$checkoutEventLoggerKitVersion.zip\" > $zipDownload\nunzip $zipDownload\ncp -r \"checkout-event-logger-ios-framework-$checkoutEventLoggerKitVersion/CheckoutEventLoggerKit.xcframework\" .\nrm -r \"checkout-event-logger-ios-framework-$checkoutEventLoggerKitVersion\"\nrm $zipDownload\n"; }; /* End PBXShellScriptBuildPhase section */ From db069fae05c1673b44d84c3ec52dab23e0cceb59 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 17:20:25 +0100 Subject: [PATCH 38/55] Change textfield color to red when it has error --- Cartfile.resolved | 2 +- .../BillingForm/View/Field/BillingFormTextFieldView.swift | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cartfile.resolved b/Cartfile.resolved index e8ee82b6..bb5ca898 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "marmelroy/PhoneNumberKit" "3.3.3" +github "marmelroy/PhoneNumberKit" "3.3.7" diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index 2950488e..71cb58e3 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -40,7 +40,7 @@ final class BillingFormTextFieldView: UIView { view.layer.borderWidth = 1.0 textField.autocorrectionType = .no view.translatesAutoresizingMaskIntoConstraints = false - view.layer.borderColor = style.textfield.normalBorderColor.cgColor + view.layer.borderColor = !style.error.isHidden ? style.textfield.errorBorderColor.cgColor : style.textfield.normalBorderColor.cgColor view.backgroundColor = style.textfield.backgroundColor textField.keyboardType = style.textfield.isSupprtingNumbericKeyboard ? .phonePad : .default textField.textContentType = style.textfield.isSupprtingNumbericKeyboard ? .telephoneNumber : .name @@ -150,8 +150,9 @@ extension BillingFormTextFieldView { extension BillingFormTextFieldView: UITextFieldDelegate { func textFieldDidBeginEditing(_ textField: UITextField) { - textFieldContainer.layer.borderColor = style.textfield.focusBorderColor.cgColor delegate?.textFieldShouldBeginEditing(textField: textField) + textFieldContainer.layer.borderColor = style.textfield.focusBorderColor.cgColor + } func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { From d1df9204b6604a8fbf2bcf3ac0229ac35b144767 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Mon, 9 May 2022 17:47:10 +0100 Subject: [PATCH 39/55] Fix screen leading and trailing --- .../View/Field/BillingFormTextFieldView.swift | 12 ++++-------- .../Fields/BillingFormTextFieldCell.swift | 9 +++------ .../ViewController/BillingFormViewController.swift | 7 +++---- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index 71cb58e3..ba224161 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -114,23 +114,19 @@ extension BillingFormTextFieldView { textFieldContainer.addSubview(textField) NSLayoutConstraint.activate([ textField.topAnchor.constraint(equalTo: textFieldContainer.topAnchor), - textField.leadingAnchor.constraint(equalTo: textFieldContainer.leadingAnchor, constant: 20), - textField.trailingAnchor.constraint(equalTo: textFieldContainer.trailingAnchor, constant: -20), + textField.leadingAnchor.constraint(equalTo: textFieldContainer.leadingAnchor), + textField.trailingAnchor.constraint(equalTo: textFieldContainer.trailingAnchor), textField.bottomAnchor.constraint(equalTo: textFieldContainer.bottomAnchor) ]) } private func setupTextFieldContainer() { addSubview(textFieldContainer) - - let width = textFieldContainer.widthAnchor.constraint(equalToConstant: style.textfield.width) - width.priority = UILayoutPriority(rawValue: 750) - + NSLayoutConstraint.activate([ textFieldContainer.topAnchor.constraint(equalTo: hintLabel.bottomAnchor, constant: 6), textFieldContainer.leadingAnchor.constraint(equalTo: leadingAnchor), - textFieldContainer.trailingAnchor.constraint(lessThanOrEqualTo: trailingAnchor), - width, + textFieldContainer.trailingAnchor.constraint(equalTo: trailingAnchor), textFieldContainer.heightAnchor.constraint(equalToConstant: style.textfield.height) ]) } diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift index 7ea39f6b..d0606c6d 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift @@ -44,14 +44,11 @@ extension BillingFormTextFieldCell { contentView.addSubview(paymentInputView) NSLayoutConstraint.activate([ paymentInputView.topAnchor.constraint( - equalTo: contentView.safeTopAnchor, - constant: 0), + equalTo: contentView.safeTopAnchor), paymentInputView.leadingAnchor.constraint( - equalTo: contentView.safeLeadingAnchor, - constant: 20), + equalTo: contentView.leadingAnchor), paymentInputView.trailingAnchor.constraint( - equalTo: contentView.safeTrailingAnchor, - constant: -20), + equalTo: contentView.trailingAnchor), paymentInputView.bottomAnchor.constraint( equalTo: contentView.safeBottomAnchor, constant: -24) diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index bb23ba88..195171a3 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -109,13 +109,12 @@ extension BillingFormViewController { view.addSubview(tableView) NSLayoutConstraint.activate([ tableView.topAnchor.constraint( - equalTo: headerView.safeBottomAnchor, - constant: 0), + equalTo: headerView.safeBottomAnchor), tableView.leadingAnchor.constraint( - equalTo: view.safeLeadingAnchor, + equalTo: view.leadingAnchor, constant: 20), tableView.trailingAnchor.constraint( - equalTo: view.safeTrailingAnchor, + equalTo: view.trailingAnchor, constant: -20), tableView.bottomAnchor.constraint( equalTo: view.safeBottomAnchor, From ecea7cdce5d43cbbb62d63f03926de336216aea4 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 09:50:43 +0100 Subject: [PATCH 40/55] Update country code --- .../UI/Controllers/CardViewController.swift | 10 +++++++- .../Factory/BillingFormFactory.swift | 3 ++- .../Field/BillingFormPhoneNumberText.swift | 24 ++++++++++++++----- .../View/Field/BillingFormTextFieldView.swift | 16 +++++++++---- .../Fields/BillingFormTextFieldCell.swift | 5 ++++ .../BillingFormViewController.swift | 9 +++++-- .../ViewModel/BillingFormViewModel.swift | 1 + .../DefaultBillingFormViewModel.swift | 8 +++++-- .../ViewModel/BillingFormViewModelTests.swift | 2 +- 9 files changed, 61 insertions(+), 17 deletions(-) diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index bdca9192..27e840f5 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -44,6 +44,7 @@ public class CardViewController: UIViewController, private var loggedForCurrentCorrelationID = false public var isNewUI = false + private var countryCode = 0 // MARK: - Initialization /// Returns a newly initialized view controller with the cardholder's name and billing details @@ -165,7 +166,10 @@ public class CardViewController: UIViewController, navigationController?.pushViewController(addressViewController, animated: true) return } - let viewController = BillingFormFactory.getBillingFormViewController(delegate: self) + guard let viewController = BillingFormFactory.getBillingFormViewController(delegate: self) else { + navigationController?.pushViewController(addressViewController, animated: true) + return + } navigationController?.present(viewController, animated: true) loggedForCurrentCorrelationID = true } @@ -347,6 +351,10 @@ public class CardViewController: UIViewController, extension CardViewController: BillingFormViewModelDelegate { + func updateCountryCode(code: Int) { + countryCode = code + } + func onTapDoneButton(address: CkoAddress, phone: CkoPhoneNumber) { billingDetailsAddress = address billingDetailsPhone = phone diff --git a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift index 0a1038c9..e4bf09de 100644 --- a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift +++ b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift @@ -13,8 +13,9 @@ struct BillingFormFactory { DefaultBillingFormPhoneNumberCellStyle() ] - static func getBillingFormViewController(delegate: BillingFormViewModelDelegate) -> UIViewController { + static func getBillingFormViewController(delegate: BillingFormViewModelDelegate) -> UIViewController? { let style = DefaultBillingFormStyle() + guard !style.fields.isEmpty else { return nil } let viewModel = DefaultBillingFormViewModel(style: style, initialCountry: "", delegate: delegate) return BillingFormViewController(viewModel: viewModel) } diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift index cf2e8813..96c74bc2 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormPhoneNumberText.swift @@ -1,8 +1,12 @@ import UIKit import PhoneNumberKit -final class BillingFormPhoneNumberText: BillingFormTextField { +protocol BillingFormPhoneNumberTextDelegate { + func updateCountryCode(code:Int) +} +final class BillingFormPhoneNumberText: BillingFormTextField { + var phoneNumberTextDelegate: BillingFormPhoneNumberTextDelegate? var phoneNumber: PhoneNumber? var nationalNumber: String { let rawNumber = self.text ?? "" @@ -21,10 +25,12 @@ final class BillingFormPhoneNumberText: BillingFormTextField { private var previousTextCount = 0 private var previousFormat = "" private let phoneNumberKit = PhoneNumberKit() + private lazy var _defaultRegion: String = PhoneNumberKit.defaultRegionCode() private lazy var partialFormatter = PartialFormatter(phoneNumberKit: phoneNumberKit, defaultRegion: "GB", withPrefix: true) - override init(type: BillingFormCellType, tag: Int) { + init(type: BillingFormCellType, tag: Int, phoneNumberTextDelegate: BillingFormPhoneNumberTextDelegate) { super.init(type: type,tag: tag) + self.phoneNumberTextDelegate = phoneNumberTextDelegate setup() } @@ -34,25 +40,30 @@ final class BillingFormPhoneNumberText: BillingFormTextField { private func setup() { keyboardType = .phonePad + updateTextFieldFormat(textField: self) addTarget(self, action: #selector(textFieldDidChange), for: UIControl.Event.editingChanged) } /// Called when the text changed. @objc private func textFieldDidChange(textField: UITextField) { + updateTextFieldFormat(textField: textField) + } + + private func updateTextFieldFormat(textField: UITextField) { var targetCursorPosition = 0 if let startPosition = textField.selectedTextRange?.start { targetCursorPosition = textField.offset(from: textField.beginningOfDocument, to: startPosition) } - let phoneNumber = textField.text! - let formatted = partialFormatter.formatPartial(phoneNumber) + let text = textField.text! + let formatted = partialFormatter.formatPartial(text) textField.text = formatted if var targetPosition = textField.position(from: textField.beginningOfDocument, offset: targetCursorPosition) { if targetCursorPosition != 0 { let lastChar = formatted[formatted.index(formatted.startIndex, offsetBy: targetCursorPosition - 1)] - if lastChar == " " && previousTextCount < formatted.count && phoneNumber != formatted { + if lastChar == " " && previousTextCount < formatted.count && text != formatted { guard let aTargetPosition = textField.position(from: textField.beginningOfDocument, offset: targetCursorPosition + 1) else { return @@ -61,7 +72,7 @@ final class BillingFormPhoneNumberText: BillingFormTextField { } } if (previousFormat.filter {$0 == " "}.count != formatted.filter {$0 == " "}.count) && - phoneNumber != formatted { + text != formatted { guard let aTargetPosition = textField.position(from: textField.beginningOfDocument, offset: targetCursorPosition + 1) else { return @@ -72,5 +83,6 @@ final class BillingFormPhoneNumberText: BillingFormTextField { } previousTextCount = formatted.count previousFormat = formatted + phoneNumberTextDelegate?.updateCountryCode(code: Int(phoneNumber?.countryCode ?? 44)) } } diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index ba224161..3591f412 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -1,12 +1,14 @@ import UIKit protocol BillingFormTextFieldViewDelegate: AnyObject { + func updateCountryCode(code: Int) func textFieldShouldBeginEditing(textField: UITextField) func textFieldShouldReturn() func textFieldShouldEndEditing(textField: UITextField, replacementString: String) } -final class BillingFormTextFieldView: UIView { +class BillingFormTextFieldView: UIView { + private var style: BillingFormTextFieldCellStyle private var type: BillingFormCellType @@ -48,7 +50,7 @@ final class BillingFormTextFieldView: UIView { }() private(set) lazy var textField: UITextField = { - let view = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type, tag: tag) : BillingFormTextField(type: self.type, tag: tag) + let view = self.type == .phoneNumber ? BillingFormPhoneNumberText(type: type, tag: tag, phoneNumberTextDelegate: self) : BillingFormTextField(type: self.type, tag: tag) view.text = style.textfield.text view.font = style.textfield.font view.placeholder = style.textfield.placeHolder @@ -114,8 +116,8 @@ extension BillingFormTextFieldView { textFieldContainer.addSubview(textField) NSLayoutConstraint.activate([ textField.topAnchor.constraint(equalTo: textFieldContainer.topAnchor), - textField.leadingAnchor.constraint(equalTo: textFieldContainer.leadingAnchor), - textField.trailingAnchor.constraint(equalTo: textFieldContainer.trailingAnchor), + textField.leadingAnchor.constraint(equalTo: textFieldContainer.leadingAnchor, constant: 20), + textField.trailingAnchor.constraint(equalTo: textFieldContainer.trailingAnchor, constant: -20), textField.bottomAnchor.constraint(equalTo: textFieldContainer.bottomAnchor) ]) } @@ -161,3 +163,9 @@ extension BillingFormTextFieldView: UITextFieldDelegate { return false } } + +extension BillingFormTextFieldView: BillingFormPhoneNumberTextDelegate { + func updateCountryCode(code: Int) { + delegate?.updateCountryCode(code: code) + } +} diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift index d0606c6d..2af561a2 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift @@ -2,6 +2,7 @@ import UIKit import PhoneNumberKit protocol BillingFormTextFieldCellDelegate: AnyObject { + func updateCountryCode(code: Int) func textFieldShouldBeginEditing(textField: UITextField) func textFieldShouldReturn() func textFieldShouldEndEditing(textField: UITextField, replacementString: String) @@ -57,6 +58,10 @@ extension BillingFormTextFieldCell { } extension BillingFormTextFieldCell: BillingFormTextFieldViewDelegate { + func updateCountryCode(code: Int) { + delegate?.updateCountryCode(code: code) + } + func textFieldShouldBeginEditing(textField: UITextField) { delegate?.textFieldShouldBeginEditing(textField: textField) diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 195171a3..3206c5d4 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -3,12 +3,13 @@ import UIKit protocol BillingFormViewControllerdelegate: AnyObject { func doneButtonIsPressed(sender: UIViewController) func cancelButtonIsPressed(sender: UIViewController) - func tableView(numberOfRowsInSection section: Int) -> Int func getViewForHeader(sender: UIViewController) -> UIView? + func validate(textField: BillingFormTextField) + func updateCountryCode(code: Int) + func tableView(numberOfRowsInSection section: Int) -> Int func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat func tableView(tableView: UITableView, cellForRowAt indexPath: IndexPath, sender: UIViewController) -> UITableViewCell func tableView(estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat - func validate(textField: BillingFormTextField) func textFieldShouldEndEditing(textField: BillingFormTextField, replacementString: String) } @@ -159,6 +160,10 @@ extension BillingFormViewController: BillingFormTextFieldCellDelegate { func textFieldShouldReturn() { view.endEditing(true) } + + func updateCountryCode(code: Int) { + delegate?.updateCountryCode(code: code) + } } //FormHeaderCellDelegate diff --git a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift index 2103b009..5ba00136 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/BillingFormViewModel.swift @@ -2,6 +2,7 @@ import Foundation protocol BillingFormViewModelDelegate: AnyObject { func onTapDoneButton(address: CkoAddress, phone: CkoPhoneNumber) + func updateCountryCode(code: Int) } protocol BillingFormViewModelEditingDelegate { diff --git a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift index 2e0cc855..e053b706 100644 --- a/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift +++ b/Source/UI/NewUI/BillingForm/ViewModel/DefaultBillingFormViewModel.swift @@ -16,6 +16,7 @@ final class DefaultBillingFormViewModel: BillingFormViewModel { private var initialCountry: String private var initialRegionCode: String? + private var countryCode: Int = 0 init(style: BillingFormStyle, initialCountry: String = "", @@ -57,6 +58,10 @@ final class DefaultBillingFormViewModel: BillingFormViewModel { } extension DefaultBillingFormViewModel: BillingFormViewControllerdelegate { + func updateCountryCode(code: Int) { + countryCode = code + } + func getViewForHeader(sender: UIViewController) -> UIView? { return getHeaderView(delegate: sender as? BillingFormHeaderCellDelegate) } @@ -92,8 +97,7 @@ extension DefaultBillingFormViewModel: BillingFormViewControllerdelegate { } func doneButtonIsPressed(sender: UIViewController) { -// let countryCode = "\(addressView.phoneInputView.phoneNumber?.countryCode ?? 44)" - let phone = CkoPhoneNumber(countryCode: "44", + let phone = CkoPhoneNumber(countryCode: "\(countryCode)", number: textValueOfCellType[.phoneNumber]) let address = CkoAddress(addressLine1: textValueOfCellType[.addressLine1], addressLine2: textValueOfCellType[.addressLine2], diff --git a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift index ca1e9db7..a708d4fd 100644 --- a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift +++ b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift @@ -67,7 +67,7 @@ class BillingFormViewModelTests: XCTestCase { BillingFormCellType.addressLine2: "addressLine2" , BillingFormCellType.state: "state" ] - let countryCode = "44" //"\(addressView.phoneInputView.phoneNumber?.countryCode ?? 44)" + let countryCode = "44" let phone = CkoPhoneNumber(countryCode: countryCode, number: textValueOfCellType[.phoneNumber]) let address = CkoAddress(addressLine1: textValueOfCellType[.addressLine1], addressLine2: textValueOfCellType[.addressLine2], From b366298ec98ac1cbbbc5c8b8b5b32e144b8015ae Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 10:01:05 +0100 Subject: [PATCH 41/55] Expose `DefaultBillingFormViewModel` delegate --- Source/UI/Controllers/CardViewController.swift | 2 +- .../UI/NewUI/BillingForm/Factory/BillingFormFactory.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index 27e840f5..76a22db7 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -166,7 +166,7 @@ public class CardViewController: UIViewController, navigationController?.pushViewController(addressViewController, animated: true) return } - guard let viewController = BillingFormFactory.getBillingFormViewController(delegate: self) else { + guard let viewController = BillingFormFactory.getBillingFormViewController(delegate: self).1 else { navigationController?.pushViewController(addressViewController, animated: true) return } diff --git a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift index e4bf09de..c0ec5bff 100644 --- a/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift +++ b/Source/UI/NewUI/BillingForm/Factory/BillingFormFactory.swift @@ -13,11 +13,11 @@ struct BillingFormFactory { DefaultBillingFormPhoneNumberCellStyle() ] - static func getBillingFormViewController(delegate: BillingFormViewModelDelegate) -> UIViewController? { + static func getBillingFormViewController(delegate: BillingFormViewModelDelegate) -> (BillingFormViewModelDelegate?, UIViewController?) { let style = DefaultBillingFormStyle() - guard !style.fields.isEmpty else { return nil } + guard !style.fields.isEmpty else { return (nil, nil) } let viewModel = DefaultBillingFormViewModel(style: style, initialCountry: "", delegate: delegate) - return BillingFormViewController(viewModel: viewModel) + return (viewModel.delegate, BillingFormViewController(viewModel: viewModel)) } } From 06344746dfd55a5322ca6fc96dc6bc77d2c2e0f7 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 10:32:21 +0100 Subject: [PATCH 42/55] Rename `setupViews` to `setupViewsInOrder` --- .../View/Error/BillingFormTextFieldErrorView.swift | 4 ++-- .../BillingForm/View/Field/BillingFormTextFieldView.swift | 4 ++-- .../TableViewCell/Fields/BillingFormTextFieldCell.swift | 4 ++-- .../View/TableViewCell/Header/BillingFormHeaderCell.swift | 4 ++-- .../ViewController/BillingFormViewController.swift | 8 ++++++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift b/Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift index 5d17d8b8..9060f58b 100644 --- a/Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift +++ b/Source/UI/NewUI/BillingForm/View/Error/BillingFormTextFieldErrorView.swift @@ -28,7 +28,7 @@ final class BillingFormTextFieldErrorView: UIView { init(style: ErrorInputLabelStyle) { super.init(frame: .zero) self.style = style - setupViews() + setupViewsInOrder() } required init?(coder: NSCoder) { @@ -38,7 +38,7 @@ final class BillingFormTextFieldErrorView: UIView { extension BillingFormTextFieldErrorView { - private func setupViews(){ + private func setupViewsInOrder(){ backgroundColor = style.backgroundColor setupHeaderLabel() setupImageView() diff --git a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift index 3591f412..8effa294 100644 --- a/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift +++ b/Source/UI/NewUI/BillingForm/View/Field/BillingFormTextFieldView.swift @@ -74,7 +74,7 @@ class BillingFormTextFieldView: UIView { super.init(frame: .zero) self.delegate = delegate self.tag = tag - self.setupViews() + self.setupViewsInOrder() } required init?(coder: NSCoder) { @@ -85,7 +85,7 @@ class BillingFormTextFieldView: UIView { extension BillingFormTextFieldView { - private func setupViews(){ + private func setupViewsInOrder(){ backgroundColor = style.backgroundColor setupHeaderLabel() setupHintLabel() diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift index 2af561a2..2dc65acb 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift @@ -20,7 +20,7 @@ final class BillingFormTextFieldCell: UITableViewCell { func update(style: BillingFormTextFieldCellStyle, tag: Int) { self.style = style self.tag = tag - setupViews() + setupViewsInOrder() } @@ -41,7 +41,7 @@ final class BillingFormTextFieldCell: UITableViewCell { // setup views extension BillingFormTextFieldCell { - private func setupViews() { + private func setupViewsInOrder() { contentView.addSubview(paymentInputView) NSLayoutConstraint.activate([ paymentInputView.topAnchor.constraint( diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index 62ecee94..545b758f 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -51,7 +51,7 @@ final class BillingFormHeaderCell: UIView { self.style = style super.init(frame: .zero) self.delegate = delegate - setupViews() + setupViewsInOrder() } required init?(coder: NSCoder) { @@ -74,7 +74,7 @@ final class BillingFormHeaderCell: UIView { // setup views extension BillingFormHeaderCell { - private func setupViews() { + private func setupViewsInOrder() { backgroundColor = style.backgroundColor setupCancelButton() setupDoneButton() diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 3206c5d4..1c9a4ce5 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -44,8 +44,7 @@ final class BillingFormViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() view.backgroundColor = viewModel.style.mainBackground - setupHeaderView() - setupTableView() + setupViewsInOrder() } override func viewWillAppear(_ animated: Bool) { @@ -89,6 +88,11 @@ final class BillingFormViewController: UIViewController { // setup views extension BillingFormViewController { + private func setupViewsInOrder() { + setupHeaderView() + setupTableView() + } + private func setupHeaderView(){ view.addSubview(headerView) NSLayoutConstraint.activate([ From dbd2ef5bffa42190d628258b999eebfc36dad9ce Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 11:56:06 +0100 Subject: [PATCH 43/55] Clean test cases --- Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift | 9 +++++++++ Tests/Mocks/BillingFormViewControllerMockDelegate.swift | 9 +++++++++ Tests/Mocks/BillingFormViewModelMockDelegate.swift | 8 ++++++++ .../ViewModel/BillingFormViewModelTests.swift | 2 +- 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift b/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift index 2505971b..0afa6750 100644 --- a/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift +++ b/Tests/Mocks/BillingFormTextFieldCellMockDelegate.swift @@ -12,6 +12,9 @@ class BillingFormTextFieldCellMockDelegate: BillingFormTextFieldCellDelegate { var textFieldShouldEndEditingLastCalledWithTextField: UITextField? var textFieldDidChangeCharactersLastCalledWithReplacementString: String? + var updateCountryCodeCalledTimes = 0 + var updateCountryCodeLastCalledWithCode: Int? + func textFieldShouldBeginEditing(textField: UITextField) { textFieldShouldBeginEditingCalledTimes += 1 textFieldShouldBeginEditingLastCalledWithTextField = textField @@ -26,4 +29,10 @@ class BillingFormTextFieldCellMockDelegate: BillingFormTextFieldCellDelegate { textFieldShouldEndEditingLastCalledWithTextField = textField textFieldDidChangeCharactersLastCalledWithReplacementString = replacementString } + + + func updateCountryCode(code: Int) { + updateCountryCodeCalledTimes += 1 + updateCountryCodeLastCalledWithCode = code + } } diff --git a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift index 53c24be2..0325dbc0 100644 --- a/Tests/Mocks/BillingFormViewControllerMockDelegate.swift +++ b/Tests/Mocks/BillingFormViewControllerMockDelegate.swift @@ -38,6 +38,10 @@ class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { var textFieldShouldEndEditingLastCalledWithBillingFormTextField: BillingFormTextField? var textFieldShouldEndEditingLastCalledWithReplacementString: String? + var updateCountryCodeCalledTimes = 0 + var updateCountryCodeLastCalledWithCode: Int? + + func doneButtonIsPressed(sender: UIViewController) { doneButtonIsPressedCalledTimes += 1 doneButtonIsPressedLastCalledWithSender = sender @@ -104,4 +108,9 @@ class BillingFormViewControllerMockDelegate: BillingFormViewControllerdelegate { textFieldShouldEndEditingLastCalledWithBillingFormTextField = textField textFieldShouldEndEditingLastCalledWithReplacementString = replacementString } + + func updateCountryCode(code: Int) { + updateCountryCodeCalledTimes += 1 + updateCountryCodeLastCalledWithCode = code + } } diff --git a/Tests/Mocks/BillingFormViewModelMockDelegate.swift b/Tests/Mocks/BillingFormViewModelMockDelegate.swift index 780a81cd..01174d91 100644 --- a/Tests/Mocks/BillingFormViewModelMockDelegate.swift +++ b/Tests/Mocks/BillingFormViewModelMockDelegate.swift @@ -6,9 +6,17 @@ class BillingFormViewModelMockDelegate: BillingFormViewModelDelegate { var onTapDoneButtonLastCalledWithAddress: CkoAddress? var onTapDoneButtonLastCalledWithNumber: CkoPhoneNumber? + var updateCountryCodeCalledTimes = 0 + var updateCountryCodeLastCalledWithCode: Int? + func onTapDoneButton(address: CkoAddress, phone: CkoPhoneNumber) { onTapDoneButtonCalledTimes += 1 onTapDoneButtonLastCalledWithAddress = address onTapDoneButtonLastCalledWithNumber = phone } + + func updateCountryCode(code: Int) { + updateCountryCodeCalledTimes += 1 + updateCountryCodeLastCalledWithCode = code + } } diff --git a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift index a708d4fd..83f20cc0 100644 --- a/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift +++ b/Tests/UI/New UI/BillingForm/ViewModel/BillingFormViewModelTests.swift @@ -67,7 +67,7 @@ class BillingFormViewModelTests: XCTestCase { BillingFormCellType.addressLine2: "addressLine2" , BillingFormCellType.state: "state" ] - let countryCode = "44" + let countryCode = "0" let phone = CkoPhoneNumber(countryCode: countryCode, number: textValueOfCellType[.phoneNumber]) let address = CkoAddress(addressLine1: textValueOfCellType[.addressLine1], addressLine2: textValueOfCellType[.addressLine2], From dd4a5b26359c7ede7e23bb89d385f61ce128a7be Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 13:00:55 +0100 Subject: [PATCH 44/55] clean code --- .../BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift | 1 - .../BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift | 1 - .../Elements/Hint/DefaultHintInputLabelStyle.swift | 1 - .../BillingForm/Style/Protocols/ErrorInputLabelStyle.swift | 1 - .../NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift | 1 - .../UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift | 1 - .../View/TableViewCell/Fields/BillingFormTextFieldCell.swift | 1 - .../View/TableViewCell/Header/BillingFormHeaderCell.swift | 1 - .../BillingForm/ViewController/BillingFormViewController.swift | 3 --- 9 files changed, 11 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift index ef36590f..a80ba658 100644 --- a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormHeaderCellStyle.swift @@ -1,7 +1,6 @@ import Foundation import UIKit -// Header Cell public protocol BillingFormHeaderCellStyle { var backgroundColor: UIColor { get } var headerLabel: InputLabelStyle { get } diff --git a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift index 662b4586..e97df6fa 100644 --- a/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Cell/BillingFormTextFieldCellStyle.swift @@ -1,6 +1,5 @@ import UIKit -// Field Cell public protocol BillingFormTextFieldCellStyle { var type: BillingFormCellType { get } var backgroundColor: UIColor { get } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift index 8ad35116..9f99e978 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift @@ -1,6 +1,5 @@ import UIKit -// hint element struct DefaultHintInputLabelStyle: InputLabelStyle { var isHidden: Bool var text: String diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift index 3239a3a6..43ccff89 100644 --- a/Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/ErrorInputLabelStyle.swift @@ -1,6 +1,5 @@ import UIKit -// Error element public protocol ErrorInputLabelStyle { var isHidden: Bool { get set } var text: String { get } diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift index 9cb8c793..6ba22d46 100644 --- a/Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/FormTextFieldStyle.swift @@ -1,6 +1,5 @@ import UIKit -// TextField element public protocol TextFieldStyle { var text: String { get set } var placeHolder: String { get } diff --git a/Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift index 3eccf956..268bf0e1 100644 --- a/Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Protocols/InputLabelStyle.swift @@ -1,6 +1,5 @@ import UIKit -// Label element public protocol InputLabelStyle { var isHidden: Bool { get } var text: String { get } diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift index 2dc65acb..7d0a8fbc 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Fields/BillingFormTextFieldCell.swift @@ -38,7 +38,6 @@ final class BillingFormTextFieldCell: UITableViewCell { } -// setup views extension BillingFormTextFieldCell { private func setupViewsInOrder() { diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index 545b758f..cab82374 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -71,7 +71,6 @@ final class BillingFormHeaderCell: UIView { } } -// setup views extension BillingFormHeaderCell { private func setupViewsInOrder() { diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index 1c9a4ce5..e9a09e1a 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -85,7 +85,6 @@ final class BillingFormViewController: UIViewController { } } -// setup views extension BillingFormViewController { private func setupViewsInOrder() { @@ -134,7 +133,6 @@ extension BillingFormViewController { } } -// UITableViewDataSource extension BillingFormViewController: UITableViewDataSource, UITableViewDelegate{ func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { @@ -182,7 +180,6 @@ extension BillingFormViewController: BillingFormHeaderCellDelegate { } } -// ViewModel extension BillingFormViewController { private func setupViewModel() { viewModel.updateRow = { From 0c01976dc385aa40eec55eef5cef223a67559788 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 13:05:04 +0100 Subject: [PATCH 45/55] Join the guard statements for `isNewUI` and `getBillingFormViewController` --- Source/UI/Controllers/CardViewController.swift | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index 76a22db7..32224181 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -162,11 +162,7 @@ public class CardViewController: UIViewController, @objc func onTapAddressView() { checkoutApiClient?.logger.log(.billingFormPresented) - guard isNewUI else { - navigationController?.pushViewController(addressViewController, animated: true) - return - } - guard let viewController = BillingFormFactory.getBillingFormViewController(delegate: self).1 else { + guard isNewUI, let viewController = BillingFormFactory.getBillingFormViewController(delegate: self).1 else { navigationController?.pushViewController(addressViewController, animated: true) return } From 5e74377a6d6f5b115d4ba2584140e46e491f8983 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 14:09:23 +0100 Subject: [PATCH 46/55] Fix Memory Leak --- .../ViewController/BillingFormViewController.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift index e9a09e1a..0d0cfc22 100644 --- a/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift +++ b/Source/UI/NewUI/BillingForm/ViewController/BillingFormViewController.swift @@ -168,7 +168,6 @@ extension BillingFormViewController: BillingFormTextFieldCellDelegate { } } -//FormHeaderCellDelegate extension BillingFormViewController: BillingFormHeaderCellDelegate { func doneButtonIsPressed() { @@ -182,8 +181,8 @@ extension BillingFormViewController: BillingFormHeaderCellDelegate { extension BillingFormViewController { private func setupViewModel() { - viewModel.updateRow = { - DispatchQueue.main.async { [weak self] in + viewModel.updateRow = { [weak self] in + DispatchQueue.main.async { guard let row = self?.viewModel.updatedRow else { return } let indexPath = IndexPath(row: row, section: 0) self?.tableView.reloadRows(at: [indexPath], with: .automatic) From 61b42c0f71274b554a13a4f61f00193ccf30b11e Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Tue, 10 May 2022 15:11:52 +0100 Subject: [PATCH 47/55] TODO: CountryCode --- Source/UI/Controllers/CardViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index 32224181..4a9611e8 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -44,6 +44,7 @@ public class CardViewController: UIViewController, private var loggedForCurrentCorrelationID = false public var isNewUI = false + // TODO: [Will updated in the next ticket]. private var countryCode = 0 // MARK: - Initialization From 3b53468afb07fb22acaa8ed0042fd4b235793464 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 11 May 2022 09:55:38 +0100 Subject: [PATCH 48/55] //TODO: migrate to assets --- Source/Extensions/StringExtensions.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Extensions/StringExtensions.swift b/Source/Extensions/StringExtensions.swift index 13aa8993..cc3c8135 100644 --- a/Source/Extensions/StringExtensions.swift +++ b/Source/Extensions/StringExtensions.swift @@ -23,6 +23,7 @@ extension String { return UIImage(named: self, in: bundle, compatibleWith: nil) ?? UIImage() } + //TODO: migrate to assets //https://www.hackingwithswift.com/example-code/core-graphics/how-to-render-a-pdf-to-an-image func vectorPDFImage(forClass: AnyClass) -> UIImage? { let bundle = getBundle(forClass: forClass) From 07a18fd27c53ddfede6fd36528aebb4f608a7001 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 11 May 2022 09:57:08 +0100 Subject: [PATCH 49/55] revert to 3.3.3 --- Cartfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cartfile b/Cartfile index 2c11da54..31e1f226 100644 --- a/Cartfile +++ b/Cartfile @@ -1,2 +1,2 @@ -github "marmelroy/PhoneNumberKit" ~> 3.3.0 +github "marmelroy/PhoneNumberKit" ~> 3.3.3 From bad59978e7d85ae6e83186b5a8c2897bc128d4f7 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 11 May 2022 09:58:15 +0100 Subject: [PATCH 50/55] Revert `PhoneNumberKit` to 3.3.0 --- Cartfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cartfile b/Cartfile index 31e1f226..2c11da54 100644 --- a/Cartfile +++ b/Cartfile @@ -1,2 +1,2 @@ -github "marmelroy/PhoneNumberKit" ~> 3.3.3 +github "marmelroy/PhoneNumberKit" ~> 3.3.0 From 1dedcc8c33b0d618d7bd6078d3b3b23c89667c24 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Wed, 11 May 2022 17:43:11 +0100 Subject: [PATCH 51/55] Add required Fonts --- .../{CheckoutColor.swift => CKOColor.swift} | 7 +- Source/CKOFont.swift | 61 ++++++++++++ Source/Extensions/StringExtensions.swift | 19 ++-- .../UI/Controllers/CardViewController.swift | 4 +- .../Cancel/DefaultCancelButtonFormStyle.swift | 2 +- .../Title/DefaultHeaderLabelFormStyle.swift | 2 +- .../Error/DefaultErrorInputLabelStyle.swift | 2 +- .../Hint/DefaultHintInputLabelStyle.swift | 2 +- .../Elements/TextField/DefaultTextField.swift | 2 +- .../Title/DefaultTitleLabelStyle.swift | 2 +- Tests/Resources/CKOColorTests.swift | 85 ++++++++++++++++ Tests/Resources/CKOFontTests.swift | 97 +++++++++++++++++++ 12 files changed, 267 insertions(+), 18 deletions(-) rename Source/{CheckoutColor.swift => CKOColor.swift} (79%) create mode 100644 Source/CKOFont.swift create mode 100644 Tests/Resources/CKOColorTests.swift create mode 100644 Tests/Resources/CKOFontTests.swift diff --git a/Source/CheckoutColor.swift b/Source/CKOColor.swift similarity index 79% rename from Source/CheckoutColor.swift rename to Source/CKOColor.swift index de0d2de3..de1ea3d2 100644 --- a/Source/CheckoutColor.swift +++ b/Source/CKOColor.swift @@ -9,8 +9,11 @@ extension UIColor { } extension UIColor { - fileprivate convenience init(hex: String, alpha: CGFloat = 1.0) { - var cString = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased() + convenience init(hex: String, alpha: CGFloat = 1.0) { + var cString = hex + .trimmingCharacters(in: .whitespacesAndNewlines) + .replacingOccurrences(of: " ", with: "") + .uppercased() if cString.hasPrefix("#") { cString.removeFirst() } diff --git a/Source/CKOFont.swift b/Source/CKOFont.swift new file mode 100644 index 00000000..e2e5229f --- /dev/null +++ b/Source/CKOFont.swift @@ -0,0 +1,61 @@ +import UIKit + +extension UIFont { + + // load framework font in application + public static let loadAllFonts: () = { + for style in GraphikStyle.allCases { + style.fontName.register(for: CheckoutTheme.self, withExtension: "otf") + } + }() + +} + +extension UIFont { + + enum GraphikStyle: String, CaseIterable { + case regularIt + case thin + case thinIt + case extrabldIt + case lightIt + case black + case medium + case extrabld + case boldIt + case regular + case blackIt + case mediumIt + case bold + case light + case semiboldIt + case semibold + var fontName: String { + return "GraphikLCG-\(self.rawValue.capitalized)" + } + } + + convenience init(graphikStyle: GraphikStyle, size: CGFloat) { + self.init(name: graphikStyle.fontName, size: size)! + } + +} + + +extension String { + //MARK: - Make custom font bundle register to framework + + func register(for type: AnyClass, withExtension: String) { + let bundle = getBundle(forClass: type) + + if let pathForResourceString = bundle.url(forResource: self, withExtension: withExtension), + let fontData = NSData(contentsOf: pathForResourceString), let dataProvider = CGDataProvider.init(data: fontData) { + let fontRef = CGFont.init(dataProvider) + var errorRef: Unmanaged? = nil + if CTFontManagerRegisterGraphicsFont(fontRef!, &errorRef) == false { + print("Failed to register font - register graphics font failed - this font may have already been registered in the main bundle.") + } + } + } + +} diff --git a/Source/Extensions/StringExtensions.swift b/Source/Extensions/StringExtensions.swift index cc3c8135..0ca001f5 100644 --- a/Source/Extensions/StringExtensions.swift +++ b/Source/Extensions/StringExtensions.swift @@ -2,27 +2,27 @@ import Foundation import UIKit extension String { - - private func getBundle(forClass: Swift.AnyClass) -> Foundation.Bundle { - #if SWIFT_PACKAGE + + func getBundle(forClass: Swift.AnyClass) -> Foundation.Bundle { +#if SWIFT_PACKAGE let baseBundle = Bundle.module - #else +#else let baseBundle = Foundation.Bundle(for: forClass) - #endif +#endif let path = baseBundle.path(forResource: "Frames", ofType: "bundle") return path == nil ? baseBundle : Foundation.Bundle(path: path!)! } - + func localized(forClass: Swift.AnyClass, comment: String = "") -> String { let bundle = getBundle(forClass: forClass) return NSLocalizedString(self, bundle: bundle, comment: "") } - + func image(forClass: AnyClass) -> UIImage { let bundle = getBundle(forClass: forClass) return UIImage(named: self, in: bundle, compatibleWith: nil) ?? UIImage() } - + //TODO: migrate to assets //https://www.hackingwithswift.com/example-code/core-graphics/how-to-render-a-pdf-to-an-image func vectorPDFImage(forClass: AnyClass) -> UIImage? { @@ -30,7 +30,7 @@ extension String { guard let urlPath = bundle.url(forResource: self, withExtension: "pdf") else { return nil } guard let document = CGPDFDocument(urlPath as CFURL) else { return nil } guard let page = document.page(at: 1) else { return nil } - + let pageRect = page.getBoxRect(.mediaBox) let renderer = UIGraphicsImageRenderer(size: pageRect.size) @@ -42,4 +42,5 @@ extension String { $0.cgContext.drawPDFPage(page) } } + } diff --git a/Source/UI/Controllers/CardViewController.swift b/Source/UI/Controllers/CardViewController.swift index 4a9611e8..b3f00d60 100644 --- a/Source/UI/Controllers/CardViewController.swift +++ b/Source/UI/Controllers/CardViewController.swift @@ -47,11 +47,13 @@ public class CardViewController: UIViewController, // TODO: [Will updated in the next ticket]. private var countryCode = 0 // MARK: - Initialization - + + /// Returns a newly initialized view controller with the cardholder's name and billing details /// state specified. You can specified the region using the Iso2 region code ("UK" for "United Kingdom") public init(checkoutApiClient: CheckoutAPIClient, cardHolderNameState: InputState, billingDetailsState: InputState, defaultRegionCode: String? = nil) { + UIFont.loadAllFonts self.checkoutApiClient = checkoutApiClient self.cardHolderNameState = cardHolderNameState self.billingDetailsState = billingDetailsState diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift index e6c86a06..6d6b33da 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift @@ -14,7 +14,7 @@ struct DefaultCancelButtonFormStyle: FormButtonStyle { init( isEnabled: Bool = true, text: String = "cancel".localized(forClass: CheckoutTheme.self), - font: UIFont = UIFont.systemFont(ofSize: 17), + font: UIFont = UIFont.systemFont(ofSize: 17), activeTitleColor: UIColor = .brandeisBlue, disabledTitleColor: UIColor = .doveGray, disabledTintColor: UIColor = .doveGray, diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift index a4f65657..3434937f 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift @@ -3,6 +3,6 @@ import UIKit struct DefaultHeaderLabelFormStyle: InputLabelStyle { var isHidden: Bool { false } var text: String { "billingAddressTitle".localized(forClass: CheckoutTheme.self) } - var font: UIFont { UIFont.systemFont(ofSize: 24) } + var font: UIFont { UIFont(graphikStyle: .medium, size: 24) } var textColor: UIColor { .codGray } } diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift index 32479963..143d5a61 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift @@ -14,7 +14,7 @@ struct DefaultErrorInputLabelStyle: ErrorInputLabelStyle { backgroundColor: UIColor = .white, tintColor: UIColor = .tallPoppyRed, text: String = "", - font: UIFont = UIFont.systemFont(ofSize: 15), + font: UIFont = UIFont(graphikStyle: .medium, size: 13), textColor: UIColor = .tallPoppyRed, isWarningSympoleOnLeft: Bool = true, height: Double = 18.0) { diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift index 9f99e978..60d13cfb 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift @@ -8,7 +8,7 @@ struct DefaultHintInputLabelStyle: InputLabelStyle { init(isHidden: Bool = false, text: String = "", - font: UIFont = UIFont.systemFont(ofSize: 13), + font: UIFont = UIFont(graphikStyle: .regular, size: 13), textColor: UIColor = .doveGray) { self.isHidden = isHidden self.text = text diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift index 4fde3f5e..d591835b 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/TextField/DefaultTextField.swift @@ -19,7 +19,7 @@ struct DefaultTextField: TextFieldStyle { init(text: String = "", placeHolder: String = "", isPlaceHolderHidden: Bool = false, - font: UIFont = UIFont.systemFont(ofSize: 16), + font: UIFont = UIFont(graphikStyle: .regular, size: 16), textColor: UIColor = .codGray, normalBorderColor: UIColor = .mediumGray, focusBorderColor: UIColor = .brandeisBlue, diff --git a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Title/DefaultTitleLabelStyle.swift b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Title/DefaultTitleLabelStyle.swift index fb660602..72597db6 100644 --- a/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Title/DefaultTitleLabelStyle.swift +++ b/Source/UI/NewUI/BillingForm/Style/Default Implementation/Elements/Title/DefaultTitleLabelStyle.swift @@ -8,7 +8,7 @@ struct DefaultTitleLabelStyle: InputLabelStyle { init(isHidden: Bool = false, text: String = "", - font: UIFont = UIFont.systemFont(ofSize: 15), + font: UIFont = UIFont(graphikStyle: .regular, size: 15), textColor: UIColor = .codGray) { self.isHidden = isHidden self.text = text diff --git a/Tests/Resources/CKOColorTests.swift b/Tests/Resources/CKOColorTests.swift new file mode 100644 index 00000000..f90cd237 --- /dev/null +++ b/Tests/Resources/CKOColorTests.swift @@ -0,0 +1,85 @@ +// +// File.swift +// +// +// Created by Ehab Alsharkawy on 11/05/2022. +// + + +import XCTest +@testable import Frames + +final class CKOColorTests: XCTestCase { + + func testColorWithHexStartingWithHashSign(){ + + let brandeisBlue = UIColor(hex: "#0B5FF0") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(brandeisBlue) + XCTAssertNotEqual(brandeisBlue, gray) + } + + func testColorWithHexLowercassed(){ + + let brandeisBlue = UIColor(hex: "#0b5ff0") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(brandeisBlue) + XCTAssertNotEqual(brandeisBlue, gray) + } + + func testColorWithHexStartingWithOutHashSign(){ + + let brandeisBlue = UIColor(hex: "0B5FF0") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(brandeisBlue) + XCTAssertNotEqual(brandeisBlue, gray) + } + + func testColorWithHexEndingWithWhiteSpace(){ + + let brandeisBlue = UIColor(hex: "#0B5FF0\n") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(brandeisBlue) + XCTAssertNotEqual(brandeisBlue, gray) + } + + func testColorWithHexWithSpaces(){ + + let brandeisBlue = UIColor(hex: "#0 B 5 F F 0\n") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(brandeisBlue) + XCTAssertNotEqual(brandeisBlue, gray) + } + + func testColorWithHexMoreThan6Digits(){ + + let invalidColor = UIColor(hex: "123456789") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(invalidColor) + XCTAssertEqual(invalidColor, gray) + } + + func testColorWithHexLessThan6Digits(){ + + let invalidColor = UIColor(hex: "1") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(invalidColor) + XCTAssertEqual(invalidColor, gray) + } + + func testColorWithEmptyHex(){ + + let invalidColor = UIColor(hex: "") + let gray = UIColor(hex: "ff0000") + + XCTAssertNotNil(invalidColor) + XCTAssertEqual(invalidColor, gray) + } +} diff --git a/Tests/Resources/CKOFontTests.swift b/Tests/Resources/CKOFontTests.swift new file mode 100644 index 00000000..03e44f5a --- /dev/null +++ b/Tests/Resources/CKOFontTests.swift @@ -0,0 +1,97 @@ +// +// File.swift +// +// +// Created by Ehab Alsharkawy on 11/05/2022. +// + + +import XCTest +@testable import Frames + +final class CKOFontTests: XCTestCase { + + func testGraphikStyleRegular() { + UIFont.loadAllFonts + + let fontName = "GraphikLCG-Regular" + let expectedFontName = UIFont.GraphikStyle.regular.fontName + XCTAssertEqual(fontName, expectedFontName) + + let font = UIFont(graphikStyle: .regular, size: 20) + + XCTAssertNotNil(font) + } + + func testGraphikStyleThin() { + UIFont.loadAllFonts + + let fontName = "GraphikLCG-Thin" + let expectedFontName = UIFont.GraphikStyle.thin.fontName + XCTAssertEqual(fontName, expectedFontName) + + let font = UIFont(graphikStyle: .thin, size: 20) + + XCTAssertNotNil(font) + } + + func testGraphikStyleLight() { + UIFont.loadAllFonts + + let fontName = "GraphikLCG-Light" + let expectedFontName = UIFont.GraphikStyle.light.fontName + XCTAssertEqual(fontName, expectedFontName) + + let font = UIFont(graphikStyle: .light, size: 20) + + XCTAssertNotNil(font) + } + + func testGraphikStyleMedium() { + UIFont.loadAllFonts + + let fontName = "GraphikLCG-Medium" + let expectedFontName = UIFont.GraphikStyle.medium.fontName + XCTAssertEqual(fontName, expectedFontName) + + let font = UIFont(graphikStyle: .medium, size: 20) + + XCTAssertNotNil(font) + } + + func testGraphikStyleSemibold() { + UIFont.loadAllFonts + + let fontName = "GraphikLCG-Semibold" + let expectedFontName = UIFont.GraphikStyle.semibold.fontName + XCTAssertEqual(fontName, expectedFontName) + + let font = UIFont(graphikStyle: .semibold, size: 20) + + XCTAssertNotNil(font) + } + + func testGraphikStyleBold() { + UIFont.loadAllFonts + + let fontName = "GraphikLCG-Bold" + let expectedFontName = UIFont.GraphikStyle.bold.fontName + XCTAssertEqual(fontName, expectedFontName) + + let font = UIFont(graphikStyle: .bold, size: 20) + + XCTAssertNotNil(font) + } + + func testGraphikStyleBlack() { + UIFont.loadAllFonts + + let fontName = "GraphikLCG-Black" + let expectedFontName = UIFont.GraphikStyle.black.fontName + XCTAssertEqual(fontName, expectedFontName) + + let font = UIFont(graphikStyle: .black, size: 20) + + XCTAssertNotNil(font) + } +} From a57c2d78d4443940efa53629c55fd70fc5fd4cdc Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Thu, 12 May 2022 09:42:07 +0100 Subject: [PATCH 52/55] Update padding for header view --- .../Header/BillingFormHeaderCell.swift | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift index cab82374..66e9bb8c 100644 --- a/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift +++ b/Source/UI/NewUI/BillingForm/View/TableViewCell/Header/BillingFormHeaderCell.swift @@ -84,11 +84,9 @@ extension BillingFormHeaderCell { addSubview(cancelButton) NSLayoutConstraint.activate([ cancelButton.topAnchor.constraint( - equalTo: safeTopAnchor, - constant: 0), + equalTo: safeTopAnchor), cancelButton.leadingAnchor.constraint( - equalTo: safeLeadingAnchor, - constant: 20), + equalTo: safeLeadingAnchor), cancelButton.heightAnchor.constraint( equalToConstant: style.cancelButton.height), cancelButton.widthAnchor.constraint( @@ -100,11 +98,9 @@ extension BillingFormHeaderCell { addSubview(done) NSLayoutConstraint.activate([ done.topAnchor.constraint( - equalTo: safeTopAnchor, - constant: 0), + equalTo: safeTopAnchor), done.trailingAnchor.constraint( - equalTo: safeTrailingAnchor, - constant: -20), + equalTo: safeTrailingAnchor), done.heightAnchor.constraint( equalToConstant: style.doneButton.height), done.widthAnchor.constraint( @@ -119,11 +115,9 @@ extension BillingFormHeaderCell { equalTo: safeTopAnchor, constant: 58), headerLabel.leadingAnchor.constraint( - equalTo: safeLeadingAnchor, - constant: 20), + equalTo: safeLeadingAnchor), headerLabel.trailingAnchor.constraint( - equalTo: safeTrailingAnchor, - constant: -20), + equalTo: safeTrailingAnchor), headerLabel.bottomAnchor.constraint( equalTo: safeBottomAnchor, constant: -40) From b538fdeae8fa865004655d39ec3051b00f7eb8c6 Mon Sep 17 00:00:00 2001 From: Ehab Al Date: Thu, 12 May 2022 16:40:46 +0100 Subject: [PATCH 53/55] Clean code --- .../Font/Graphik/GraphikLCG-Black.otf | Bin 0 -> 186304 bytes .../Font/Graphik/GraphikLCG-BlackItalic.otf | Bin 0 -> 194168 bytes .../Font/Graphik/GraphikLCG-Bold.otf | Bin 0 -> 186184 bytes .../Font/Graphik/GraphikLCG-BoldItalic.otf | Bin 0 -> 190976 bytes .../Font/Graphik/GraphikLCG-Extralight.otf | Bin 0 -> 179476 bytes .../Graphik/GraphikLCG-ExtralightItalic.otf | Bin 0 -> 186424 bytes .../Font/Graphik/GraphikLCG-Light.otf | Bin 0 -> 179520 bytes .../Font/Graphik/GraphikLCG-LightItalic.otf | Bin 0 -> 186096 bytes .../Font/Graphik/GraphikLCG-Medium.otf | Bin 0 -> 183696 bytes .../Font/Graphik/GraphikLCG-MediumItalic.otf | Bin 0 -> 188032 bytes .../Font/Graphik/GraphikLCG-Regular.otf | Bin 0 -> 173828 bytes .../Font/Graphik/GraphikLCG-RegularItalic.otf | Bin 0 -> 177576 bytes .../Font/Graphik/GraphikLCG-Semibold.otf | Bin 0 -> 184788 bytes .../Graphik/GraphikLCG-SemiboldItalic.otf | Bin 0 -> 193312 bytes .../Font/Graphik/GraphikLCG-Super.otf | Bin 0 -> 185512 bytes .../Font/Graphik/GraphikLCG-SuperItalic.otf | Bin 0 -> 187784 bytes .../Font/Graphik/GraphikLCG-Thin.otf | Bin 0 -> 174084 bytes .../Font/Graphik/GraphikLCG-ThinItalic.otf | Bin 0 -> 177924 bytes .../UI/Controllers/CardViewController.swift | 4 +- ...aultBillingFormAddressLine1CellStyle.swift | 8 +- ...aultBillingFormAddressLine2CellStyle.swift | 8 +- .../DefaultBillingFormCityCellStyle.swift | 6 +- .../DefaultBillingFormCountryCellStyle.swift | 8 +- .../DefaultBillingFormFullNameCellStyle.swift | 6 +- ...faultBillingFormPhoneNumberCellStyle.swift | 8 +- .../DefaultBillingFormPostCodeCellStyle.swift | 6 +- .../DefaultBillingFormStateCellStyle.swift | 6 +- .../Cancel/DefaultCancelButtonFormStyle.swift | 0 .../Done/DefaultDoneFormButtonStyle.swift | 0 .../DefaultBillingFormHeaderCellStyle.swift | 0 .../Title/DefaultHeaderLabelFormStyle.swift | 0 .../Main/DefaultBillingFormStyle.swift | 6 +- .../Error/DefaultErrorInputLabelStyle.swift | 0 .../Hint/DefaultHintInputLabelStyle.swift | 0 .../Elements/TextField/DefaultTextField.swift | 0 .../Title/DefaultTitleLabelStyle.swift | 0 .../Factory/BillingFormFactory.swift | 21 ++-- .../Style/BillingFormCellType.swift | 51 +++++++++ .../Cell/BillingFormTextFieldCellStyle.swift | 2 +- .../Style/Protocols/BillingFormStyle.swift | 4 +- .../Style/Protocols/FormButtonStyle.swift | 1 - .../Field/BillingFormPhoneNumberText.swift | 2 +- .../View/Field/BillingFormTextField.swift | 4 +- .../View/Field/BillingFormTextFieldView.swift | 15 ++- .../Fields/BillingFormTextFieldCell.swift | 13 ++- .../BillingFormViewController.swift | 9 +- .../ViewModel/BillingFormCellType.swift | 25 ---- .../DefaultBillingFormViewModel.swift | 108 ++++++++++-------- ...BillingFormTextFieldCellMockDelegate.swift | 10 ++ ...illingFormViewControllerMockDelegate.swift | 31 +++-- .../AddressLine1ValidatorTests.swift | 4 +- .../AddressLine2ValidatorTests.swift | 4 +- .../Validator/CityValidatorTests.swift | 4 +- .../Validator/CountryValidatorTests.swift | 4 +- .../Validator/FullNameValidatorTests.swift | 4 +- .../Validator/PhoneNumberValidatorTests.swift | 4 +- .../Validator/PostCodeValidatorTests.swift | 4 +- .../Validator/StateValidatorTests.swift | 4 +- ...illingFormFullNameTextFieldCellTests.swift | 4 +- .../BillingFormTextFieldErrorViewTests.swift | 1 + .../View/BillingFormTextFieldViewTests.swift | 6 +- .../ViewModel/BillingFormCellTypeTests.swift | 18 +-- .../ViewModel/BillingFormViewModelTests.swift | 90 +++++++-------- 63 files changed, 295 insertions(+), 218 deletions(-) create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Black.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-BlackItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Bold.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-BoldItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Extralight.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-ExtralightItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Light.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-LightItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Medium.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-MediumItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Regular.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-RegularItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Semibold.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-SemiboldItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Super.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-SuperItalic.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-Thin.otf create mode 100644 Source/Resources/Font/Graphik/GraphikLCG-ThinItalic.otf rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/AddressLine1/DefaultBillingFormAddressLine1CellStyle.swift (88%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/AddressLine2/DefaultBillingFormAddressLine2CellStyle.swift (84%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/City/DefaultBillingFormCityCellStyle.swift (88%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/Country/DefaultBillingFormCountryCellStyle.swift (84%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/FullName/DefaultBillingFormFullNameCellStyle.swift (88%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/PhoneNumber/DefaultBillingFormPhoneNumberCellStyle.swift (86%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/Postcode/DefaultBillingFormPostCodeCellStyle.swift (88%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Fields/State/DefaultBillingFormStateCellStyle.swift (89%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Header/Cancel/DefaultCancelButtonFormStyle.swift (100%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Header/Done/DefaultDoneFormButtonStyle.swift (100%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Header/Main/DefaultBillingFormHeaderCellStyle.swift (100%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Header/Title/DefaultHeaderLabelFormStyle.swift (100%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/BillingForm/Main/DefaultBillingFormStyle.swift (69%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/Elements/Error/DefaultErrorInputLabelStyle.swift (100%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/Elements/Hint/DefaultHintInputLabelStyle.swift (100%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/Elements/TextField/DefaultTextField.swift (100%) rename Source/UI/NewUI/BillingForm/{Style => }/Default Implementation/Elements/Title/DefaultTitleLabelStyle.swift (100%) create mode 100644 Source/UI/NewUI/BillingForm/Style/BillingFormCellType.swift delete mode 100644 Source/UI/NewUI/BillingForm/ViewModel/BillingFormCellType.swift diff --git a/Source/Resources/Font/Graphik/GraphikLCG-Black.otf b/Source/Resources/Font/Graphik/GraphikLCG-Black.otf new file mode 100644 index 0000000000000000000000000000000000000000..f411d4aff63a7a3d19e6d4743cd0d4aaf249a318 GIT binary patch literal 186304 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