mvcgen 0.1.14 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/mvcgen/filemanager.rb +1 -1
- data/lib/mvcgen/generator.rb +36 -33
- data/lib/mvcgen/version.rb +1 -1
- data/lib/templates/default/mvcspec.yml +1 -1
- data/lib/templates/default/podfile/Podfile +73 -0
- data/lib/templates/default/swift/AppDelegate.swift +181 -0
- data/lib/templates/default/swift/Assets.xcassets/AppIcon.appiconset/Contents.json +133 -0
- data/lib/templates/default/swift/Assets.xcassets/Back.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/Back.imageset/icons8-back-filled-100-2.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Contents.json +6 -0
- data/lib/templates/default/swift/Assets.xcassets/Down.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/Down.imageset/icons8-expand-arrow-filled-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Forward.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/Forward.imageset/icons8-forward-filled-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Key.imageset/Contents.json +1 -0
- data/lib/templates/default/swift/Assets.xcassets/Key.imageset/universal_Key.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Shopping-cart.imageset/Contents.json +1 -0
- data/lib/templates/default/swift/Assets.xcassets/Shopping-cart.imageset/universal_Shopping-cart.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Tick.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/Tick.imageset/icons8-Checkmark-96 (1).png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Up.imageset/Contents.json +22 -0
- data/lib/templates/default/swift/Assets.xcassets/Up.imageset/icons8-collapse-arrow-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Up.imageset/icons8-collapse-arrow-50.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Uruguay.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/Uruguay.imageset/icons8-uruguay-40.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Wallet.imageset/Contents.json +1 -0
- data/lib/templates/default/swift/Assets.xcassets/Wallet.imageset/universal_Wallet.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_001.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_001.imageset/Icons_NotATour_Welcome_001.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_002.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_002.imageset/Icons_NotATour_Welcome_002.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_003.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_003.imageset/Icons_NotATour_Welcome_003.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_004.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/Welcome_004.imageset/Icons_NotATour_Welcome_004.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_beach.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_beach.imageset/icons8-beach-64.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_nobaggage.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_nobaggage.imageset/icons8-no-baggage-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_signpost.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_signpost.imageset/icons8-signpost-64.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_sunbed.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/alert_sunbed.imageset/sunbed.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/arrow.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/arrow.imageset/arrow.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/baggage.imageset/Contents.json +22 -0
- data/lib/templates/default/swift/Assets.xcassets/baggage.imageset/baggage.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/baggage.imageset/baggage@2x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/burger.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/burger.imageset/burger.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/calendar-white.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/calendar-white.imageset/icons8-calendar.pdf +70 -0
- data/lib/templates/default/swift/Assets.xcassets/calendar.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/calendar.imageset/calendar.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/dots.imageset/Contents.json +24 -0
- data/lib/templates/default/swift/Assets.xcassets/dots.imageset/dots.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/edit.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/edit.imageset/edit.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/emptylogin.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/emptylogin.imageset/empty state loging.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/envelope.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/envelope.imageset/icons8-envelope.pdf +70 -0
- data/lib/templates/default/swift/Assets.xcassets/expandSection.imageset/Contents.json +22 -0
- data/lib/templates/default/swift/Assets.xcassets/expandSection.imageset/icons8-expand-arrow-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/expandSection.imageset/icons8-expand-arrow-50.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/facebook.imageset/Contents.json +24 -0
- data/lib/templates/default/swift/Assets.xcassets/facebook.imageset/icons8-facebook-f.pdf +68 -0
- data/lib/templates/default/swift/Assets.xcassets/filter-white.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/filter-white.imageset/icons8-adjust (3).pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/filter.imageset/Contents.json +15 -0
- data/lib/templates/default/swift/Assets.xcassets/filter.imageset/filter.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/food.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/food.imageset/food.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/forgot-password.imageset/Contents.json +23 -0
- data/lib/templates/default/swift/Assets.xcassets/forgot-password.imageset/page-1.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/forgot-password.imageset/page-1@2x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/forgot-password.imageset/page-1@3x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/heart-active.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/heart-active.imageset/favortio activo.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/heart.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/heart.imageset/favorito inactivo.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/icons8-delete.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/icons8-delete.imageset/icons8-delete (3).pdf +69 -0
- data/lib/templates/default/swift/Assets.xcassets/lock.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/lock.imageset/icons8-lock.pdf +69 -0
- data/lib/templates/default/swift/Assets.xcassets/man-avatar.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/man-avatar.imageset/man-avatar.pdf +1149 -1
- data/lib/templates/default/swift/Assets.xcassets/new-notification.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/new-notification.imageset/icons8-filled-circle-filled-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/no-fav.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/no-fav.imageset/page-1@2x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/notificaciones.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/notificaciones.imageset/notificaciones.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/notification.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/notification.imageset/icons8-notification-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/other.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/other.imageset/other.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/page-1.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/page-1.imageset/page-1@2x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/page-3.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/page-3.imageset/page-1@2x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/photo.imageset/Contents.json +24 -0
- data/lib/templates/default/swift/Assets.xcassets/photo.imageset/photo.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/plus-white.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/plus-white.imageset/icons8-plus-math-26.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/plus.imageset/+.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/plus.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/register.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/register.imageset/registro.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/search.imageset/Contents.json +15 -0
- data/lib/templates/default/swift/Assets.xcassets/search.imageset/search.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/settings.imageset/Contents.json +23 -0
- data/lib/templates/default/swift/Assets.xcassets/settings.imageset/icons8-settings-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/settings.imageset/icons8-settings-50.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/settings.imageset/icons8-settings-500.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/shape.imageset/Contents.json +23 -0
- data/lib/templates/default/swift/Assets.xcassets/shape.imageset/shape.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/shape.imageset/shape@2x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/shape.imageset/shape@3x.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/signpost.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/signpost.imageset/icons8-signpost-50.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/stars.imageset/Contents.json +24 -0
- data/lib/templates/default/swift/Assets.xcassets/stars.imageset/stars.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/terms.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/terms.imageset/terminos y condiciones.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/tickets.imageset/Contents.json +12 -0
- data/lib/templates/default/swift/Assets.xcassets/tickets.imageset/tickets.pdf +0 -0
- data/lib/templates/default/swift/Assets.xcassets/user.imageset/Contents.json +22 -0
- data/lib/templates/default/swift/Assets.xcassets/user.imageset/icons8-account-100.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/user.imageset/icons8-account-50.png +0 -0
- data/lib/templates/default/swift/Assets.xcassets/visa.imageset/Contents.json +21 -0
- data/lib/templates/default/swift/Assets.xcassets/visa.imageset/visa.png +0 -0
- data/lib/templates/default/swift/Config/Config.swift +1 -1
- data/lib/templates/default/swift/Controllers/Login/ForgetPasswordVC.swift +125 -0
- data/lib/templates/default/swift/Controllers/Login/LoginVC.swift +244 -0
- data/lib/templates/default/swift/Controllers/Login/RegisterVC.swift +213 -0
- data/lib/templates/default/swift/Controllers/Notifications/Cells/NotificationCell.swift +51 -0
- data/lib/templates/default/swift/Controllers/Notifications/NotificationsVC.swift +164 -0
- data/lib/templates/default/swift/Controllers/OtherLogin/ForgetPasswordTVC.swift +98 -0
- data/lib/templates/default/swift/Controllers/OtherLogin/LoginTVC.swift +245 -0
- data/lib/templates/default/swift/Controllers/OtherLogin/OtherRegisterVC.swift +299 -0
- data/lib/templates/default/swift/Controllers/OtherLogin/SelectLanguageCell.swift +17 -0
- data/lib/templates/default/swift/Controllers/OtherLogin/SelectLanguageVC.swift +116 -0
- data/lib/templates/default/swift/Controllers/OtherLogin/TermsAndConditionsVC.swift +76 -0
- data/lib/templates/default/swift/Controllers/Profile/AboutUsVC.swift +93 -0
- data/lib/templates/default/swift/Controllers/Profile/Cells/AboutUsImageCell.swift +66 -0
- data/lib/templates/default/swift/Controllers/Profile/Cells/DescriptionCell.swift +16 -0
- data/lib/templates/default/swift/Controllers/Profile/Cells/DestinationCell.swift +35 -0
- data/lib/templates/default/swift/Controllers/Profile/Cells/DestinationCellView.xib +84 -0
- data/lib/templates/default/swift/Controllers/Profile/Cells/FavoriteCollectionCell.swift +24 -0
- data/lib/templates/default/swift/Controllers/Profile/Cells/ImagesCollectionViewCell.swift +15 -0
- data/lib/templates/default/swift/Controllers/Profile/ProfileContainerVC.swift +72 -0
- data/lib/templates/default/swift/Controllers/Profile/ProfileTVC.swift +581 -0
- data/lib/templates/default/swift/Controllers/Tutorial/TutorialVC.swift +121 -0
- data/lib/templates/default/swift/Extensions/ArrayDuplicates.swift +35 -0
- data/lib/templates/default/swift/Extensions/Buttons.swift +1 -1
- data/lib/templates/default/swift/Extensions/CustomCamera.swift +65 -0
- data/lib/templates/default/swift/Extensions/GradientView.swift +121 -0
- data/lib/templates/default/swift/Extensions/HideKeyboard.swift +22 -0
- data/lib/templates/default/swift/Extensions/Images.swift +82 -0
- data/lib/templates/default/swift/Extensions/InnerShadowExtension.swift +83 -0
- data/lib/templates/default/swift/Extensions/TableViewEmptyView.swift +30 -0
- data/lib/templates/default/swift/Extensions/TapEffectExtension.swift +48 -0
- data/lib/templates/default/swift/Extensions/{ColorHex.swift → UIColorExtensions.swift} +2 -2
- data/lib/templates/default/swift/Extensions/UnderlinedTextView.swift +61 -0
- data/lib/templates/default/swift/Extensions/UnderlinedWithIconTextField.swift +55 -0
- data/lib/templates/default/swift/Helper/APIHelper.swift +4 -4
- data/lib/templates/default/swift/Helper/APIManager.swift +81 -14
- data/lib/templates/default/swift/Helper/APIRequestBody.swift +1 -1
- data/lib/templates/default/swift/Helper/AWSManager.swift +1 -1
- data/lib/templates/default/swift/Helper/FilesManager.swift +1 -1
- data/lib/templates/default/swift/Helper/S3Manager.swift +1 -1
- data/lib/templates/default/swift/Helper/Utils.swift +3 -1
- data/lib/templates/default/swift/Info.plist +53 -0
- data/lib/templates/default/swift/Models/Country.swift +28 -0
- data/lib/templates/default/swift/Models/Managers/UserManager.swift +1 -1
- data/lib/templates/default/swift/Models/Notif.swift +71 -0
- data/lib/templates/default/swift/Models/Responses/BaseResponse.swift +1 -1
- data/lib/templates/default/swift/Models/Responses/NotificationResponse.swift +24 -0
- data/lib/templates/default/swift/Models/Responses/UserResponse.swift +1 -1
- data/lib/templates/default/swift/Models/Responses/UserSingupResponse.swift +1 -1
- data/lib/templates/default/swift/Models/User.swift +2 -2
- data/lib/templates/default/swift/UI/Storyboards/Home.storyboard +2113 -0
- data/lib/templates/default/swift/UI/Storyboards/Login.storyboard +814 -0
- data/lib/templates/default/swift/UI/Storyboards/OtherLogin.storyboard +1031 -0
- data/lib/templates/default/swift/UI/Views/EmptyTableView/EmptyTableLabelView.swift +18 -0
- data/lib/templates/default/swift/UI/Views/EmptyTableView/NoNotificationView.swift +16 -0
- data/lib/templates/default/swift/UI/Views/EmptyTableView/Xibs/EmptyTableLabelView.xib +72 -0
- data/lib/templates/default/swift/UI/Views/EmptyTableView/Xibs/NoNotificationsView.xib +61 -0
- metadata +176 -4
Binary file
|
@@ -0,0 +1,125 @@
|
|
1
|
+
//
|
2
|
+
// ForgetPasswordVC.swift
|
3
|
+
// MVCGEN
|
4
|
+
//
|
5
|
+
// Created by Daniel Martinez on 23/7/18.
|
6
|
+
// Copyright © 2018 Houlak. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
import Foundation
|
10
|
+
|
11
|
+
import UIKit
|
12
|
+
|
13
|
+
protocol ForgetPasswordVCDelegate: class {
|
14
|
+
func removeBlurredBackgroundView()
|
15
|
+
}
|
16
|
+
class ForgetPasswordVC: UIViewController, UIGestureRecognizerDelegate {
|
17
|
+
|
18
|
+
weak var delegate: ForgetPasswordVCDelegate?
|
19
|
+
private var keybaordIsShowing: Bool = false
|
20
|
+
|
21
|
+
@IBOutlet weak var cancelButton: UIButton!
|
22
|
+
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!
|
23
|
+
@IBOutlet weak var topConstraint: NSLayoutConstraint!
|
24
|
+
@IBOutlet weak var backgroundView: UIView!
|
25
|
+
@IBOutlet weak var recoverView: UIView!
|
26
|
+
@IBOutlet weak var emailTextField: UITextField!
|
27
|
+
@IBOutlet weak var sendButton: LoadingButton!
|
28
|
+
|
29
|
+
override func viewDidLoad() {
|
30
|
+
super.viewDidLoad()
|
31
|
+
|
32
|
+
hideKeyboardWhenTappedAround()
|
33
|
+
|
34
|
+
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissView))
|
35
|
+
|
36
|
+
tap.delegate = self
|
37
|
+
|
38
|
+
self.backgroundView.addGestureRecognizer(tap)
|
39
|
+
|
40
|
+
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasShown), name: .UIKeyboardWillShow, object: nil);
|
41
|
+
NotificationCenter.default.addObserver(self, selector: #selector(self.keyboardWasHidden), name: .UIKeyboardWillHide, object: nil);
|
42
|
+
|
43
|
+
|
44
|
+
}
|
45
|
+
|
46
|
+
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
|
47
|
+
if keybaordIsShowing {
|
48
|
+
return false
|
49
|
+
}
|
50
|
+
if touch.view?.restorationIdentifier == "backViewID" {
|
51
|
+
return true
|
52
|
+
}
|
53
|
+
return false
|
54
|
+
}
|
55
|
+
|
56
|
+
@objc func dismissView(){
|
57
|
+
dismiss(animated: true, completion: nil)
|
58
|
+
delegate?.removeBlurredBackgroundView()
|
59
|
+
}
|
60
|
+
|
61
|
+
|
62
|
+
@objc func keyboardWasShown(notification: NSNotification) {
|
63
|
+
|
64
|
+
self.keybaordIsShowing = true
|
65
|
+
|
66
|
+
UIView.animate(withDuration: 0.5, animations: { () -> Void in
|
67
|
+
self.bottomConstraint.constant = 287
|
68
|
+
self.topConstraint.constant = 10
|
69
|
+
})
|
70
|
+
}
|
71
|
+
|
72
|
+
@objc func keyboardWasHidden(notification: NSNotification) {
|
73
|
+
|
74
|
+
self.keybaordIsShowing = false
|
75
|
+
|
76
|
+
UIView.animate(withDuration: 0.5, animations: { () -> Void in
|
77
|
+
self.topConstraint.constant = 148.5
|
78
|
+
self.bottomConstraint.constant = 148.5
|
79
|
+
})
|
80
|
+
}
|
81
|
+
|
82
|
+
override func viewDidLayoutSubviews() {
|
83
|
+
view.backgroundColor = UIColor.clear
|
84
|
+
|
85
|
+
//ensure that the icon embeded in the cancel button fits in nicely
|
86
|
+
cancelButton.imageView?.contentMode = .scaleAspectFit
|
87
|
+
|
88
|
+
//add a white tint color for the Cancel button image
|
89
|
+
// let cancelImage = UIImage(named: "Cancel")
|
90
|
+
|
91
|
+
// let tintedCancelImage = cancelImage?.withRenderingMode(.alwaysTemplate)
|
92
|
+
// cancelButton.setImage(tintedCancelImage, for: .normal)
|
93
|
+
// cancelButton.tintColor = .white
|
94
|
+
}
|
95
|
+
|
96
|
+
// MARK: - Actions
|
97
|
+
@IBAction func cancelTapped(_ sender: UIButton) {
|
98
|
+
self.dismissView()
|
99
|
+
}
|
100
|
+
|
101
|
+
@IBAction func sendTapped(_ sender: UIButton) {
|
102
|
+
if let email = self.emailTextField.text, isValidEmail(email) {
|
103
|
+
self.sendButton.showLoading()
|
104
|
+
APIManager.sharedInstance.forgotPwd(withParameters: APIRequestBody.forgotPwd(withEmail: email), completion: {
|
105
|
+
result in
|
106
|
+
self.sendButton.hideLoading()
|
107
|
+
if result == .success {
|
108
|
+
APIHelper.sharedInstance.showSuccesMessage(with: NSLocalizedString("Email sent!", comment: ""), and: "")
|
109
|
+
}
|
110
|
+
})
|
111
|
+
} else {
|
112
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("Invalid email", comment: ""), and: "")
|
113
|
+
}
|
114
|
+
}
|
115
|
+
|
116
|
+
// MARK: - Private
|
117
|
+
|
118
|
+
private func isValidEmail(_ testStr:String) -> Bool {
|
119
|
+
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
|
120
|
+
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
|
121
|
+
return emailTest.evaluate(with: testStr)
|
122
|
+
}
|
123
|
+
|
124
|
+
|
125
|
+
}
|
@@ -0,0 +1,244 @@
|
|
1
|
+
//
|
2
|
+
// LoginVC.swift
|
3
|
+
// MVCGEN
|
4
|
+
//
|
5
|
+
// Created by Daniel Martinez on 23/7/18.
|
6
|
+
// Copyright © 2018 Houlak. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
import UIKit
|
10
|
+
import Pastel
|
11
|
+
import FacebookLogin
|
12
|
+
|
13
|
+
class LoginVC: UITableViewController, UITextFieldDelegate, ForgetPasswordVCDelegate {
|
14
|
+
|
15
|
+
// MARK: - Outlets
|
16
|
+
|
17
|
+
@IBOutlet weak var emailTextField: UITextField!
|
18
|
+
@IBOutlet weak var passwordTextField: UITextField!
|
19
|
+
@IBOutlet weak var forgetPasswordLabel: UILabel!
|
20
|
+
@IBOutlet weak var loginButton: LoadingButton!{
|
21
|
+
didSet{
|
22
|
+
loginButton.addShadow()
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
private let homeStoryboard = UIStoryboard(name: "Home", bundle: Bundle.main)
|
27
|
+
|
28
|
+
@IBOutlet weak var registerButton: UIButton!{
|
29
|
+
didSet{
|
30
|
+
registerButton.addShadow()
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
@IBOutlet weak var facebookLoginButton: LoadingButton!{
|
35
|
+
didSet{
|
36
|
+
facebookLoginButton.addShadow()
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
private var pastelView: PastelView!
|
41
|
+
|
42
|
+
override func viewDidLoad() {
|
43
|
+
super.viewDidLoad()
|
44
|
+
|
45
|
+
|
46
|
+
self.emailTextField.delegate = self
|
47
|
+
self.passwordTextField.delegate = self
|
48
|
+
|
49
|
+
configureText()
|
50
|
+
|
51
|
+
configureViews()
|
52
|
+
|
53
|
+
hideKeyboardWhenTappedAround()
|
54
|
+
|
55
|
+
}
|
56
|
+
|
57
|
+
override func viewWillAppear(_ animated: Bool) {
|
58
|
+
super.viewWillAppear(animated)
|
59
|
+
|
60
|
+
self.pastelView.startAnimation()
|
61
|
+
}
|
62
|
+
|
63
|
+
// MARK: - Actions
|
64
|
+
|
65
|
+
@IBAction func loginTapped(_ sender: UIButton) {
|
66
|
+
self.emailLoginTapped()
|
67
|
+
}
|
68
|
+
|
69
|
+
@IBAction func facebookLoginTapped(_ sender: UIButton) {
|
70
|
+
self.facebookLoginButton.showLoading()
|
71
|
+
let fbLoginManager = LoginManager()
|
72
|
+
// TODO: Comment next line after logout is done
|
73
|
+
fbLoginManager.logOut()
|
74
|
+
fbLoginManager.logIn(readPermissions: [.email, .userBirthday, .publicProfile], viewController: self, completion: { loginResult in
|
75
|
+
switch loginResult {
|
76
|
+
case .failed(let error):
|
77
|
+
self.facebookLoginButton.hideLoading()
|
78
|
+
print(error)
|
79
|
+
break
|
80
|
+
case .cancelled:
|
81
|
+
self.facebookLoginButton.hideLoading()
|
82
|
+
print("User cancelled login.")
|
83
|
+
break
|
84
|
+
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
|
85
|
+
// let photoURL = URL(string: "https://graph.facebook.com/\(accessToken.userId ?? "")/picture?type=large&return_ssl_resources=1")
|
86
|
+
APIManager.sharedInstance.loginfb(withParameters: APIRequestBody.getFbLoginBody(withAccesToken: accessToken.authenticationToken), completion: {
|
87
|
+
result in
|
88
|
+
self.facebookLoginButton.hideLoading()
|
89
|
+
if result == .success {
|
90
|
+
self.performSegue(withIdentifier: "GoHome", sender: nil)
|
91
|
+
}
|
92
|
+
})
|
93
|
+
}
|
94
|
+
})
|
95
|
+
}
|
96
|
+
|
97
|
+
@IBAction func forgetPasswordTapped(_ sender: UIButton) {
|
98
|
+
self.definesPresentationContext = true
|
99
|
+
self.providesPresentationContextTransitionStyle = true
|
100
|
+
|
101
|
+
self.overlayBlurredBackgroundView()
|
102
|
+
}
|
103
|
+
|
104
|
+
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
|
105
|
+
if let identifier = segue.identifier {
|
106
|
+
if identifier == "ShowForgetPassword" {
|
107
|
+
if let viewController = segue.destination as? ForgetPasswordVC {
|
108
|
+
viewController.delegate = self
|
109
|
+
viewController.modalPresentationStyle = .overFullScreen
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
// MARK: - UITextFieldDelegate
|
116
|
+
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
117
|
+
|
118
|
+
if textField.tag == 1 {
|
119
|
+
textField.resignFirstResponder()
|
120
|
+
emailLoginTapped()
|
121
|
+
return true
|
122
|
+
}
|
123
|
+
|
124
|
+
let nextTage = textField.tag+1
|
125
|
+
|
126
|
+
// Try to find next responder
|
127
|
+
guard let nextResponder = textField.superview?.superview?.superview?.viewWithTag(nextTage) as UIResponder? else {
|
128
|
+
textField.resignFirstResponder()
|
129
|
+
return false
|
130
|
+
}
|
131
|
+
|
132
|
+
nextResponder.becomeFirstResponder()
|
133
|
+
|
134
|
+
return false // We do not want UITextField to insert line-breaks.
|
135
|
+
}
|
136
|
+
|
137
|
+
// MARK: - Private
|
138
|
+
|
139
|
+
private func configureText(){
|
140
|
+
|
141
|
+
self.emailTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Email", comment: ""),
|
142
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
143
|
+
self.passwordTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Password", comment: ""),
|
144
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
145
|
+
|
146
|
+
let normalText = NSLocalizedString("Forget your password?", comment: "")
|
147
|
+
let normalAttrs = [NSAttributedStringKey.font : Fonts.roboto(type: 0, fontSize: 15)]
|
148
|
+
let normalString = NSMutableAttributedString(string:normalText,attributes: normalAttrs)
|
149
|
+
|
150
|
+
let boldText = NSLocalizedString(" Restore", comment: "")
|
151
|
+
let attrs = [NSAttributedStringKey.font : Fonts.roboto(type: 4, fontSize: 15)]
|
152
|
+
let attributedString = NSMutableAttributedString(string:boldText, attributes:attrs)
|
153
|
+
|
154
|
+
normalString.append(attributedString)
|
155
|
+
|
156
|
+
self.forgetPasswordLabel.attributedText = normalString
|
157
|
+
|
158
|
+
}
|
159
|
+
|
160
|
+
private func configureViews(){
|
161
|
+
self.pastelView = PastelView(frame: self.tableView.bounds)
|
162
|
+
|
163
|
+
// Custom Direction
|
164
|
+
pastelView.startPastelPoint = .bottomLeft
|
165
|
+
pastelView.endPastelPoint = .topRight
|
166
|
+
|
167
|
+
// Custom Duration
|
168
|
+
pastelView.animationDuration = 3.0
|
169
|
+
|
170
|
+
// Custom Color
|
171
|
+
pastelView.setColors([Colors.firstGradientColor, Colors.textColor, Colors.secondGradientColor, Colors.thirdGradientColor])
|
172
|
+
|
173
|
+
self.tableView.backgroundView = pastelView
|
174
|
+
|
175
|
+
}
|
176
|
+
|
177
|
+
private func emailLoginTapped(){
|
178
|
+
if self.validateForm(){
|
179
|
+
if let email = self.emailTextField.text, let password = self.passwordTextField.text{
|
180
|
+
self.loginButton.showLoading()
|
181
|
+
APIManager.sharedInstance.login(withParameters: APIRequestBody.getLoginBody(withEmail: email, withPassword: password), completion: {
|
182
|
+
result in
|
183
|
+
self.loginButton.hideLoading()
|
184
|
+
if result == .success {
|
185
|
+
let rootController = self.homeStoryboard.instantiateViewController(withIdentifier: "Home")
|
186
|
+
UIApplication.shared.keyWindow?.rootViewController = rootController
|
187
|
+
self.performSegue(withIdentifier: "GoHome", sender: nil)
|
188
|
+
}
|
189
|
+
})
|
190
|
+
}
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
194
|
+
private func validateForm() -> Bool {
|
195
|
+
|
196
|
+
if self.emailTextField.text == "" {
|
197
|
+
errorOnLogin(causeOfFailure: "email")
|
198
|
+
return false
|
199
|
+
}
|
200
|
+
|
201
|
+
if self.passwordTextField.text == "" {
|
202
|
+
errorOnLogin(causeOfFailure: "password")
|
203
|
+
return false
|
204
|
+
}
|
205
|
+
|
206
|
+
return true
|
207
|
+
}
|
208
|
+
|
209
|
+
private func errorOnLogin(causeOfFailure error: String){
|
210
|
+
|
211
|
+
switch error {
|
212
|
+
case "email":
|
213
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("You must enter an email", comment: ""), and: "")
|
214
|
+
break
|
215
|
+
case "password":
|
216
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("You must enter a password", comment: ""), and: "")
|
217
|
+
break
|
218
|
+
default:
|
219
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("Check the entered data", comment: ""), and: "")
|
220
|
+
break
|
221
|
+
}
|
222
|
+
|
223
|
+
}
|
224
|
+
|
225
|
+
private func overlayBlurredBackgroundView() {
|
226
|
+
|
227
|
+
let blurredBackgroundView = UIVisualEffectView()
|
228
|
+
|
229
|
+
blurredBackgroundView.frame = self.tableView.bounds
|
230
|
+
blurredBackgroundView.effect = UIBlurEffect(style: .dark)
|
231
|
+
|
232
|
+
self.tableView.addSubview(blurredBackgroundView)
|
233
|
+
|
234
|
+
}
|
235
|
+
|
236
|
+
@objc func removeBlurredBackgroundView() {
|
237
|
+
|
238
|
+
for subview in self.tableView.subviews {
|
239
|
+
if subview.isKind(of: UIVisualEffectView.self) {
|
240
|
+
subview.removeFromSuperview()
|
241
|
+
}
|
242
|
+
}
|
243
|
+
}
|
244
|
+
}
|
@@ -0,0 +1,213 @@
|
|
1
|
+
//
|
2
|
+
// RegisterVC.swift
|
3
|
+
// MVCGEN
|
4
|
+
//
|
5
|
+
// Created by Daniel Martinez on 23/7/18.
|
6
|
+
// Copyright © 2018 Houlak. All rights reserved.
|
7
|
+
//
|
8
|
+
|
9
|
+
import UIKit
|
10
|
+
import Pastel
|
11
|
+
|
12
|
+
class RegisterVC: UITableViewController, UITextFieldDelegate {
|
13
|
+
|
14
|
+
@IBOutlet weak var nameTextField: UITextField!
|
15
|
+
@IBOutlet weak var lastnameTextField: UITextField!
|
16
|
+
@IBOutlet weak var cellphoneTextField: UITextField!
|
17
|
+
@IBOutlet weak var emailTextField: UITextField!
|
18
|
+
@IBOutlet weak var passwordTextField: UITextField!
|
19
|
+
@IBOutlet weak var confirmPasswordTextField: UITextField!
|
20
|
+
@IBOutlet weak var createAccountButton: LoadingButton!{
|
21
|
+
didSet{
|
22
|
+
createAccountButton.addShadow()
|
23
|
+
}
|
24
|
+
}
|
25
|
+
@IBOutlet weak var acceptTermsButton: UIButton!
|
26
|
+
|
27
|
+
private var pastelView: PastelView!
|
28
|
+
|
29
|
+
private var termsAndConditionsAccepted: Bool = false
|
30
|
+
|
31
|
+
override func viewDidLoad() {
|
32
|
+
super.viewDidLoad()
|
33
|
+
|
34
|
+
self.nameTextField.delegate = self
|
35
|
+
self.lastnameTextField.delegate = self
|
36
|
+
self.cellphoneTextField.delegate = self
|
37
|
+
self.emailTextField.delegate = self
|
38
|
+
self.passwordTextField.delegate = self
|
39
|
+
self.confirmPasswordTextField.delegate = self
|
40
|
+
|
41
|
+
configureText()
|
42
|
+
|
43
|
+
configureViews()
|
44
|
+
|
45
|
+
hideKeyboardWhenTappedAround()
|
46
|
+
|
47
|
+
}
|
48
|
+
|
49
|
+
override func viewWillAppear(_ animated: Bool) {
|
50
|
+
super.viewWillAppear(animated)
|
51
|
+
|
52
|
+
self.pastelView.startAnimation()
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
// MARK: - UITextFieldDelegate
|
57
|
+
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
58
|
+
|
59
|
+
let nextTage = textField.tag+1
|
60
|
+
|
61
|
+
// Try to find next responder
|
62
|
+
guard let nextResponder = textField.superview?.superview?.superview?.viewWithTag(nextTage) as UIResponder? else {
|
63
|
+
textField.resignFirstResponder()
|
64
|
+
return false
|
65
|
+
}
|
66
|
+
|
67
|
+
nextResponder.becomeFirstResponder()
|
68
|
+
|
69
|
+
return false // We do not want UITextField to insert line-breaks.
|
70
|
+
}
|
71
|
+
|
72
|
+
// MARK: - Actions
|
73
|
+
|
74
|
+
@IBAction func createTapped(_ sender: UIButton) {
|
75
|
+
if self.validateForm(){
|
76
|
+
if let email = self.emailTextField.text, let password = self.passwordTextField.text, let name = self.nameTextField.text, let lastname = self.lastnameTextField.text, let cellphone = self.cellphoneTextField.text {
|
77
|
+
self.createAccountButton.showLoading()
|
78
|
+
APIManager.sharedInstance.signup(withParameters: APIRequestBody.getSignupBody(withEmail: email, withPassword: password, withFirstName: name, withLastname: lastname, withPhone: cellphone, withProfilePic: "", withStudies: "", withCertifications: "", withAbout: ""), completion: {
|
79
|
+
result, user in
|
80
|
+
if result == .success {
|
81
|
+
APIManager.sharedInstance.login(withParameters: APIRequestBody.getLoginBody(withEmail: email, withPassword: password), completion: {
|
82
|
+
result in
|
83
|
+
self.createAccountButton.hideLoading()
|
84
|
+
if result == .success {
|
85
|
+
self.performSegue(withIdentifier: "SuccesfullySignup", sender: nil)
|
86
|
+
}
|
87
|
+
})
|
88
|
+
} else {
|
89
|
+
self.createAccountButton.hideLoading()
|
90
|
+
}
|
91
|
+
})
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
@IBAction func termsTapped(_ sender: UIButton) {
|
97
|
+
if !termsAndConditionsAccepted {
|
98
|
+
let tintedImage = Asset.tick.image.withRenderingMode(.alwaysTemplate)
|
99
|
+
sender.setImage(tintedImage, for: .normal)
|
100
|
+
sender.tintColor = UIColor.init(red: 51/255, green: 125/255, blue: 173/255, alpha: 1.0)
|
101
|
+
if let image = sender.imageView {
|
102
|
+
sender.bringSubview(toFront: image)
|
103
|
+
}
|
104
|
+
termsAndConditionsAccepted = true
|
105
|
+
} else {
|
106
|
+
sender.setImage(nil, for: .normal)
|
107
|
+
termsAndConditionsAccepted = false
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
@IBAction func termsAndConditionsTapped(_ sender: UIButton) {
|
112
|
+
// TODO: View url
|
113
|
+
if let url = URL(string: "http://dils.com/terms-and-conditions") {
|
114
|
+
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
115
|
+
}
|
116
|
+
}
|
117
|
+
|
118
|
+
@IBAction func alreadyHaveAccountTapped(_ sender: UIButton) {
|
119
|
+
self.dismiss(animated: true, completion: nil)
|
120
|
+
}
|
121
|
+
|
122
|
+
|
123
|
+
|
124
|
+
// MARK: - Private
|
125
|
+
|
126
|
+
private func configureText(){
|
127
|
+
|
128
|
+
self.emailTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Email", comment: ""),
|
129
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
130
|
+
|
131
|
+
self.nameTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Name", comment: ""),
|
132
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
133
|
+
|
134
|
+
self.lastnameTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Lastname", comment: ""),
|
135
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
136
|
+
|
137
|
+
self.cellphoneTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Cellphone (optional)", comment: ""),
|
138
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
139
|
+
|
140
|
+
self.passwordTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Password", comment: ""),
|
141
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
142
|
+
|
143
|
+
self.confirmPasswordTextField.attributedPlaceholder = NSAttributedString(string: NSLocalizedString("Confirm password", comment: ""),
|
144
|
+
attributes: [NSAttributedStringKey.foregroundColor: UIColor.lightGray, NSAttributedStringKey.font: Fonts.roboto(type: 1, fontSize: 17)])
|
145
|
+
|
146
|
+
|
147
|
+
}
|
148
|
+
|
149
|
+
private func configureViews(){
|
150
|
+
self.pastelView = PastelView(frame: self.tableView.bounds)
|
151
|
+
|
152
|
+
// Custom Direction
|
153
|
+
pastelView.startPastelPoint = .bottomLeft
|
154
|
+
pastelView.endPastelPoint = .topRight
|
155
|
+
|
156
|
+
// Custom Duration
|
157
|
+
pastelView.animationDuration = 3.0
|
158
|
+
|
159
|
+
// Custom Color
|
160
|
+
pastelView.setColors([Colors.firstGradientColor, Colors.textColor, Colors.secondGradientColor, Colors.thirdGradientColor])
|
161
|
+
|
162
|
+
self.tableView.backgroundView = pastelView
|
163
|
+
|
164
|
+
}
|
165
|
+
|
166
|
+
private func validateForm() -> Bool {
|
167
|
+
|
168
|
+
if let password = self.passwordTextField.text, let confirmPassword = self.confirmPasswordTextField.text {
|
169
|
+
if password != confirmPassword {
|
170
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("Passwords don't match", comment: ""), and: "")
|
171
|
+
return false
|
172
|
+
}
|
173
|
+
}
|
174
|
+
if let name = self.nameTextField.text, name.isEmpty {
|
175
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("Check the entered data", comment: ""), and: "")
|
176
|
+
return false
|
177
|
+
}
|
178
|
+
if let lastname = self.lastnameTextField.text, lastname.isEmpty {
|
179
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("Check the entered data", comment: ""), and: "")
|
180
|
+
return false
|
181
|
+
}
|
182
|
+
if let email = self.emailTextField.text{
|
183
|
+
if !isValidEmail(email.trimmingCharacters(in: .whitespacesAndNewlines)) {
|
184
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("Invalid email", comment: ""), and: "")
|
185
|
+
return false
|
186
|
+
}
|
187
|
+
}
|
188
|
+
if !termsAndConditionsAccepted{
|
189
|
+
APIHelper.sharedInstance.showErrorMessage(with: NSLocalizedString("Check the entered data", comment: ""), and: NSLocalizedString("You have to accept terms & conditions", comment: ""))
|
190
|
+
return false
|
191
|
+
}
|
192
|
+
return true
|
193
|
+
}
|
194
|
+
|
195
|
+
private func isValidEmail(_ testStr:String) -> Bool {
|
196
|
+
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
|
197
|
+
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
|
198
|
+
return emailTest.evaluate(with: testStr)
|
199
|
+
}
|
200
|
+
|
201
|
+
private func isValidName(_ testStr:String) -> Bool {
|
202
|
+
let nameRegEx = "[A-Za-z\\s]+"
|
203
|
+
let nameTest = NSPredicate(format:"SELF MATCHES %@", nameRegEx)
|
204
|
+
return nameTest.evaluate(with: testStr)
|
205
|
+
}
|
206
|
+
|
207
|
+
private func isValidPhone(_ testStr:String) -> Bool {
|
208
|
+
let phoneRegEx = "[0-9]*"
|
209
|
+
let phoneTest = NSPredicate(format:"SELF MATCHES %@", phoneRegEx)
|
210
|
+
return phoneTest.evaluate(with: testStr)
|
211
|
+
}
|
212
|
+
|
213
|
+
}
|