@jimrising/easymerchantsdk-react-native 2.5.3 → 2.5.4

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.
@@ -84,7 +84,7 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
84
84
  return
85
85
  }
86
86
 
87
- guard let presentingVC = presentingViewControllerInWindowHierarchy() else {
87
+ guard let (presentingVC, toDismiss) = presentingViewControllerAndOptionalDismiss() else {
88
88
  reject("NO_VIEW_CONTROLLER", "Unable to find a view controller in the window hierarchy", nil)
89
89
  clearCallbacks()
90
90
  return
@@ -98,8 +98,8 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
98
98
  }
99
99
 
100
100
  let controller = EasyPayViewController(request: request, delegate: self)
101
- DispatchQueue.main.async {
102
- presentingVC.present(controller, animated: true)
101
+ DispatchQueue.main.async { [weak self] in
102
+ self?.presentPaymentController(controller, from: presentingVC, dismissFirst: toDismiss)
103
103
  }
104
104
  }
105
105
 
@@ -117,15 +117,15 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
117
117
  return
118
118
  }
119
119
 
120
- guard let presentingVC = presentingViewControllerInWindowHierarchy() else {
120
+ guard let (presentingVC, toDismiss) = presentingViewControllerAndOptionalDismiss() else {
121
121
  reject("NO_VIEW_CONTROLLER", "Unable to find a view controller in the window hierarchy", nil)
122
122
  clearCallbacks()
123
123
  return
124
124
  }
125
125
 
126
126
  let controller = EasyPayViewController(request: request, delegate: self)
127
- DispatchQueue.main.async {
128
- presentingVC.present(controller, animated: true)
127
+ DispatchQueue.main.async { [weak self] in
128
+ self?.presentPaymentController(controller, from: presentingVC, dismissFirst: toDismiss)
129
129
  }
130
130
  }
131
131
 
@@ -155,14 +155,61 @@ public class EasyMerchantSdkPlugin: NSObject, RCTBridgeModule {
155
155
  return UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController
156
156
  }
157
157
 
158
- /// Present from the last VC in the chain whose view is in the window. RCTFabricModalHostViewController
159
- /// is often on top but its view is not in the window hierarchy; presenting from it crashes.
158
+ /// Returns (presenter, viewControllerToDismiss). If the top is a modal host or our EasyPay, we must dismiss it first so presenter is not "already presenting".
159
+ private func presentingViewControllerAndOptionalDismiss() -> (UIViewController, UIViewController?)? {
160
+ guard var vc = keyWindowRootViewController() else { return nil }
161
+ while let presented = vc.presentedViewController {
162
+ vc = presented
163
+ }
164
+ let top = vc
165
+ // Step back from modal host or our own payment VC to get the real presenter
166
+ while (isModalHostViewController(vc) || isEasyPayViewController(vc)), let presenter = vc.presentingViewController {
167
+ vc = presenter
168
+ }
169
+ if isModalHostViewController(vc) || isEasyPayViewController(vc) { return nil }
170
+ // If top was a modal or EasyPay, that top is currently presented by vc; we must dismiss it first
171
+ let dismissFirst: UIViewController? = (top !== vc) ? top : nil
172
+ return (vc, dismissFirst)
173
+ }
174
+
175
+ private func presentPaymentController(_ controller: UIViewController, from presentingVC: UIViewController, dismissFirst: UIViewController?) {
176
+ if let toDismiss = dismissFirst {
177
+ toDismiss.dismiss(animated: false) { [weak self] in
178
+ DispatchQueue.main.async {
179
+ // After dismiss, get top then step back from modal host / EasyPay so we never present from them
180
+ guard let presenter = self?.presentingViewControllerInWindowHierarchy() else {
181
+ presentingVC.present(controller, animated: true)
182
+ return
183
+ }
184
+ presenter.present(controller, animated: true)
185
+ }
186
+ }
187
+ } else {
188
+ presentingVC.present(controller, animated: true)
189
+ }
190
+ }
191
+
192
+ /// Present from a VC that can safely present (not RCTFabricModalHostViewController; not our EasyPayViewController).
160
193
  private func presentingViewControllerInWindowHierarchy() -> UIViewController? {
161
194
  guard var vc = keyWindowRootViewController() else { return nil }
162
- while let presented = vc.presentedViewController, presented.viewIfLoaded?.window != nil {
195
+ while let presented = vc.presentedViewController {
163
196
  vc = presented
164
197
  }
165
- return vc.viewIfLoaded?.window != nil ? vc : nil
198
+ while (isModalHostViewController(vc) || isEasyPayViewController(vc)), let presenter = vc.presentingViewController {
199
+ vc = presenter
200
+ }
201
+ if isModalHostViewController(vc) || isEasyPayViewController(vc) { return nil }
202
+ return vc
203
+ }
204
+
205
+ private func isModalHostViewController(_ vc: UIViewController?) -> Bool {
206
+ guard let vc = vc else { return false }
207
+ let name = String(describing: type(of: vc))
208
+ return name.contains("ModalHost") || name.contains("RCTModalHost")
209
+ }
210
+
211
+ private func isEasyPayViewController(_ vc: UIViewController?) -> Bool {
212
+ vc is EasyPayViewController
166
213
  }
167
214
 
168
215
  private func getTopViewController() -> UIViewController? {
@@ -17,7 +17,7 @@ enum GrailPaySource {
17
17
  case newAccount
18
18
  }
19
19
 
20
- let easymerchantsdk = UIStoryboard(name: "easymerchantsdk", bundle: Bundle.easyPayBundle)
20
+ let easymerchantsdk = UIStoryboard(name: "EasyPaySdk", bundle: Bundle.easyPayBundle)
21
21
 
22
22
  class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
23
23
 
@@ -2038,7 +2038,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2038
2038
  }
2039
2039
 
2040
2040
  @objc func aboutTerms(sender: UITapGestureRecognizer) {
2041
- guard let vc = UIStoryboard(name: "easymerchantsdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2041
+ guard let vc = UIStoryboard(name: "EasyPaySdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2042
2042
  print("Error: Could not find TermAndConditionsVC in easymerchantsdk storyboard.")
2043
2043
  return
2044
2044
  }
@@ -2066,7 +2066,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2066
2066
  }
2067
2067
 
2068
2068
  @objc func aboutTermsAndConditions(sender: UITapGestureRecognizer) {
2069
- guard let vc = UIStoryboard(name: "easymerchantsdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2069
+ guard let vc = UIStoryboard(name: "EasyPaySdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2070
2070
  return
2071
2071
  }
2072
2072
  vc.modalPresentationStyle = .overFullScreen
@@ -2118,7 +2118,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2118
2118
  }
2119
2119
 
2120
2120
  @objc func aboutTermsGrailPayConditions(sender: UITapGestureRecognizer) {
2121
- guard let vc = UIStoryboard(name: "easymerchantsdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2121
+ guard let vc = UIStoryboard(name: "EasyPaySdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2122
2122
  return
2123
2123
  }
2124
2124
  vc.modalPresentationStyle = .overFullScreen
@@ -2145,7 +2145,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2145
2145
  }
2146
2146
 
2147
2147
  @objc func aboutTermsGrailPayNewAccountConditions(sender: UITapGestureRecognizer) {
2148
- guard let vc = UIStoryboard(name: "easymerchantsdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2148
+ guard let vc = UIStoryboard(name: "EasyPaySdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2149
2149
  return
2150
2150
  }
2151
2151
  vc.modalPresentationStyle = .overFullScreen
@@ -2172,7 +2172,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2172
2172
  }
2173
2173
 
2174
2174
  @objc func aboutTermsNewAccountViewConditions(sender: UITapGestureRecognizer) {
2175
- guard let vc = UIStoryboard(name: "easymerchantsdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2175
+ guard let vc = UIStoryboard(name: "EasyPaySdk", bundle: Bundle.easyPayBundle).instantiateViewController(withIdentifier: "TermAndConditionsVC") as? TermAndConditionsVC else {
2176
2176
  return
2177
2177
  }
2178
2178
  vc.modalPresentationStyle = .overFullScreen
@@ -2785,7 +2785,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2785
2785
  }
2786
2786
  else if showBilling {
2787
2787
  // Push to BillingInfoVC
2788
- let billingInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
2788
+ let billingInfoVC = UIStoryboard(name: "EasyPaySdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "BillingInfoVC") as! BillingInfoVC
2789
2789
 
2790
2790
  billingInfoVC.isFrom = "SavedCards"
2791
2791
  billingInfoVC.selectedCard = self.selectedCard // Passing the selected card data
@@ -2811,7 +2811,7 @@ class PaymentInfoVC: BaseVC, BillingInfoVCDelegate {
2811
2811
  }
2812
2812
  else {
2813
2813
  // Push to AdditionalInfoVC
2814
- let additionalInfoVC = UIStoryboard(name: "easymerchantsdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
2814
+ let additionalInfoVC = UIStoryboard(name: "EasyPaySdk", bundle: .easyPayBundle).instantiateViewController(withIdentifier: "AdditionalInfoVC") as! AdditionalInfoVC
2815
2815
  additionalInfoVC.isFrom = "SavedCards"
2816
2816
  additionalInfoVC.selectedCard = self.selectedCard // Passing the selected card data
2817
2817
  additionalInfoVC.cvvText = cvvText // Passing the CVV text
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |s|
2
2
  s.name = 'easymerchantsdk'
3
- s.version = '2.5.3'
3
+ s.version = '2.5.4'
4
4
  s.summary = 'A React Native SDK for Easy Merchant.'
5
5
  s.description = <<-DESC
6
6
  A React Native SDK to enable Easy Merchant functionality in mobile applications.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jimrising/easymerchantsdk-react-native",
3
- "version": "2.5.3",
3
+ "version": "2.5.4",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {