@aigens/aigens-sdk-core 0.0.38 → 0.0.40
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.
@@ -42,6 +42,8 @@ import java.io.BufferedReader;
|
|
42
42
|
import java.io.IOException;
|
43
43
|
import java.io.InputStream;
|
44
44
|
import java.io.InputStreamReader;
|
45
|
+
import java.io.UnsupportedEncodingException;
|
46
|
+
import java.net.URLDecoder;
|
45
47
|
import java.util.ArrayList;
|
46
48
|
import java.util.Collection;
|
47
49
|
import java.util.HashMap;
|
@@ -80,6 +82,7 @@ public class WebContainerActivity extends BridgeActivity {
|
|
80
82
|
add("payme://");
|
81
83
|
add("https://play.google.com");
|
82
84
|
add("hsbcpaymepay://");
|
85
|
+
add("mpay://");
|
83
86
|
}};
|
84
87
|
|
85
88
|
private void debug(Object... msgs) {
|
@@ -93,9 +96,9 @@ public class WebContainerActivity extends BridgeActivity {
|
|
93
96
|
}
|
94
97
|
}
|
95
98
|
|
96
|
-
private String getRedirectUrl() {
|
99
|
+
private String getRedirectUrl(Intent intent) {
|
97
100
|
try {
|
98
|
-
Intent intent = getIntent();
|
101
|
+
// Intent intent = getIntent();
|
99
102
|
Uri uri = intent.getData();
|
100
103
|
if (uri != null) {
|
101
104
|
String totalUrl = uri.toString();
|
@@ -104,12 +107,25 @@ public class WebContainerActivity extends BridgeActivity {
|
|
104
107
|
if (perviousIntent != null) {
|
105
108
|
Map member = (Map) perviousIntent.getSerializableExtra("member");
|
106
109
|
universalLink = (String) member.get("universalLink");
|
107
|
-
universalLink
|
110
|
+
if (universalLink != null && !universalLink.isEmpty()) {
|
111
|
+
universalLink = universalLink.trim();
|
112
|
+
}else {
|
113
|
+
universalLink = null;
|
114
|
+
}
|
108
115
|
}
|
109
|
-
if (universalLink != null && totalUrl.startsWith(universalLink) && totalUrl.indexOf("redirect=") >= 0) {
|
116
|
+
if (universalLink != null && (totalUrl.startsWith(universalLink) || universalLink.contains("aigens=true")) && totalUrl.indexOf("redirect=") >= 0) {
|
110
117
|
redirectUrl = totalUrl.split("redirect=")[1];
|
111
118
|
}
|
119
|
+
if (universalLink != null && (totalUrl.startsWith(universalLink) || universalLink.contains("aigens=true")) && totalUrl.indexOf("aigensRedirect/") >= 0) {
|
120
|
+
redirectUrl = totalUrl.split("aigensRedirect/")[1];
|
121
|
+
}
|
112
122
|
Log.i("getRedirectUrl", totalUrl);
|
123
|
+
if (redirectUrl != null) {
|
124
|
+
redirectUrl = this.decodeURIComponent(redirectUrl);
|
125
|
+
}
|
126
|
+
if (!redirectUrl.startsWith("http://") && !redirectUrl.startsWith("https://")) {
|
127
|
+
redirectUrl = "https://" + redirectUrl;
|
128
|
+
}
|
113
129
|
return redirectUrl;
|
114
130
|
} else {
|
115
131
|
Log.i("getRedirectUrl", "null");
|
@@ -122,6 +138,22 @@ public class WebContainerActivity extends BridgeActivity {
|
|
122
138
|
|
123
139
|
}
|
124
140
|
|
141
|
+
|
142
|
+
@Override
|
143
|
+
protected void onNewIntent(Intent intent) {
|
144
|
+
super.onNewIntent(intent);
|
145
|
+
// System.out.println("OPEN URL: onNewIntent" + intent.toString());
|
146
|
+
String redirectUrl = getRedirectUrl(intent);
|
147
|
+
if (redirectUrl != null) {
|
148
|
+
if (this.bridge != null && this.bridge.getWebView() != null) {
|
149
|
+
initLayout(false, true, false);
|
150
|
+
this.bridge.getWebView().loadUrl(redirectUrl);
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
}
|
156
|
+
|
125
157
|
private void addChannel() {
|
126
158
|
if (getIntent() == null) return;
|
127
159
|
String url = getIntent().getStringExtra("url");
|
@@ -144,9 +176,9 @@ public class WebContainerActivity extends BridgeActivity {
|
|
144
176
|
|
145
177
|
setContentView(com.aigens.sdk.R.layout.sdk_layout_main);
|
146
178
|
|
147
|
-
String redirectUrl = getRedirectUrl();
|
148
179
|
Intent intent = getIntent();
|
149
180
|
|
181
|
+
String redirectUrl = getRedirectUrl(intent);
|
150
182
|
if (redirectUrl != null && !redirectUrl.equals("") && WebContainerActivity.perviousIntent != null) {
|
151
183
|
WebContainerActivity.perviousIntent.putExtra("url", redirectUrl);
|
152
184
|
intent = WebContainerActivity.perviousIntent;
|
@@ -266,7 +298,7 @@ public class WebContainerActivity extends BridgeActivity {
|
|
266
298
|
this.bridge.getWebView().setWebViewClient(wvc);
|
267
299
|
if (DEBUG) {
|
268
300
|
this.bridge.getWebView().setWebContentsDebuggingEnabled(true);
|
269
|
-
}else {
|
301
|
+
} else {
|
270
302
|
this.bridge.getWebView().setWebContentsDebuggingEnabled(false);
|
271
303
|
}
|
272
304
|
|
@@ -427,6 +459,15 @@ public class WebContainerActivity extends BridgeActivity {
|
|
427
459
|
return plugins;
|
428
460
|
}
|
429
461
|
|
462
|
+
private String decodeURIComponent(String encodedStr) {
|
463
|
+
String decodedStr = encodedStr;
|
464
|
+
try {
|
465
|
+
decodedStr = URLDecoder.decode(encodedStr, "UTF-8");
|
466
|
+
} catch (UnsupportedEncodingException e) {
|
467
|
+
decodedStr = encodedStr;
|
468
|
+
}
|
469
|
+
return decodedStr;
|
470
|
+
}
|
430
471
|
private boolean isDevMode() {
|
431
472
|
return (this.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
|
432
473
|
}
|
@@ -732,6 +773,7 @@ public class WebContainerActivity extends BridgeActivity {
|
|
732
773
|
@Override
|
733
774
|
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
734
775
|
|
776
|
+
// Log.wtf(TAG, "onPageStarted: "+url );
|
735
777
|
debug("onPageStarted", url);
|
736
778
|
|
737
779
|
super.onPageStarted(view, url, favicon);
|
@@ -752,7 +794,7 @@ public class WebContainerActivity extends BridgeActivity {
|
|
752
794
|
@Override
|
753
795
|
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
|
754
796
|
debug("onReceivedErrorOld", errorCode, description, failingUrl);
|
755
|
-
System.out.println("onReceivedErrorOld:"+description+failingUrl);
|
797
|
+
System.out.println("onReceivedErrorOld:" + description + failingUrl);
|
756
798
|
if (isFirstError) { // reload
|
757
799
|
isFirstError = false;
|
758
800
|
reload();
|
@@ -135,7 +135,9 @@ public class CorePlugin extends Plugin {
|
|
135
135
|
}
|
136
136
|
}
|
137
137
|
|
138
|
-
getActivity()
|
138
|
+
if (getActivity() != null) {
|
139
|
+
getActivity().finish();
|
140
|
+
}
|
139
141
|
|
140
142
|
}
|
141
143
|
|
@@ -159,7 +161,9 @@ public class CorePlugin extends Plugin {
|
|
159
161
|
}
|
160
162
|
}
|
161
163
|
|
162
|
-
getActivity()
|
164
|
+
if (getActivity() != null) {
|
165
|
+
getActivity().finish();
|
166
|
+
}
|
163
167
|
|
164
168
|
|
165
169
|
}
|
@@ -164,6 +164,8 @@ public class CorePlugin: CAPPlugin {
|
|
164
164
|
let member = call.getObject("member")
|
165
165
|
let deeplink = call.getObject("deeplink")
|
166
166
|
let externalProtocols = call.getArray("externalProtocols")
|
167
|
+
let addPaddingProtocols = call.getArray("addPaddingProtocols")
|
168
|
+
|
167
169
|
let clearCache = call.getBool("clearCache") ?? false
|
168
170
|
aigensDebug = call.getBool("debug") ?? false
|
169
171
|
|
@@ -186,6 +188,9 @@ public class CorePlugin: CAPPlugin {
|
|
186
188
|
if (externalProtocols != nil) {
|
187
189
|
options["externalProtocols"] = externalProtocols as AnyObject
|
188
190
|
}
|
191
|
+
if (addPaddingProtocols != nil) {
|
192
|
+
options["addPaddingProtocols"] = addPaddingProtocols as AnyObject
|
193
|
+
}
|
189
194
|
|
190
195
|
bridgeVC.options = options;
|
191
196
|
|
@@ -266,7 +271,7 @@ public class CorePlugin: CAPPlugin {
|
|
266
271
|
@objc func setTextZoom(_ call: CAPPluginCall) {
|
267
272
|
call.unimplemented("ios does not implement.")
|
268
273
|
}
|
269
|
-
|
274
|
+
|
270
275
|
private func getStringFromQr(_ image: UIImage) -> String? {
|
271
276
|
guard let ciImage = CIImage(image: image) else {
|
272
277
|
return nil
|
@@ -18,8 +18,27 @@ import Capacitor
|
|
18
18
|
private var redirectLink = ""
|
19
19
|
private var universalLink = ""
|
20
20
|
var externalProtocols: [String] = [
|
21
|
-
"octopus://", "alipay://", "alipays://", "alipayhk://", "https://itunes.apple.com", "tel:", "mailto:", "itms-apps://itunes.apple.com", "https://apps.apple.com", "payme://", "weixin://", "hsbcpaymepay://"
|
21
|
+
"octopus://", "alipay://", "alipays://", "alipayhk://", "https://play.google.com", "https://itunes.apple.com", "tel:", "mailto:", "itms-apps://itunes.apple.com", "https://apps.apple.com", "payme://", "weixin://", "hsbcpaymepay://", "mpay://"
|
22
22
|
]
|
23
|
+
var addPaddingProtocols: [String] = [
|
24
|
+
"https://ap-gateway.mastercard.com",
|
25
|
+
"https://mapi-hk.alipay.com/",
|
26
|
+
"https://mclient.alipay.com/",
|
27
|
+
"https://tscenter.alipay.com/",
|
28
|
+
"https://test.paydollar.com/",
|
29
|
+
"https://paydollar.com/",
|
30
|
+
"https://www.paydollar.com/",
|
31
|
+
"https://web-test.online.octopus.com.hk",
|
32
|
+
"https://web.online.octopus.com.hk",
|
33
|
+
"https://web-prd.online.octopus.com.hk",
|
34
|
+
"http://vmp.eftpay.com.cn",
|
35
|
+
"https://wx.tenpay.com",
|
36
|
+
"https://uatopenapi.macaupay.com.mo",
|
37
|
+
"https://uatpay.macaupass.com",
|
38
|
+
"https://prdpay.macaupass.com",
|
39
|
+
"https://pay.macaupass.com",
|
40
|
+
]
|
41
|
+
|
23
42
|
let containerView = WebContainer.webContainer()
|
24
43
|
var webContainerView: WebContainer {
|
25
44
|
return containerView
|
@@ -50,6 +69,15 @@ import Capacitor
|
|
50
69
|
|
51
70
|
}
|
52
71
|
|
72
|
+
private func isPaddingUrl(_ url: URL) -> Bool {
|
73
|
+
var result = false
|
74
|
+
addPaddingProtocols.forEach { (url_) in
|
75
|
+
if (url.absoluteString.starts(with: url_)) {
|
76
|
+
result = true
|
77
|
+
}
|
78
|
+
}
|
79
|
+
return result
|
80
|
+
}
|
53
81
|
private func addChannel() {
|
54
82
|
if let urlString = self.options?["url"] as? String {
|
55
83
|
|
@@ -109,11 +137,13 @@ import Capacitor
|
|
109
137
|
}
|
110
138
|
|
111
139
|
aigensprint("handleUrlOpened url:\(object)")
|
112
|
-
guard
|
140
|
+
guard var url = object["url"] as? URL else {
|
113
141
|
return
|
114
142
|
}
|
115
143
|
|
116
|
-
|
144
|
+
url = decodeURIComponent(url);
|
145
|
+
|
146
|
+
if universalLink.isEmpty || (!url.absoluteString.starts(with: universalLink) && !universalLink.contains("aigens=true")) {
|
117
147
|
return;
|
118
148
|
}
|
119
149
|
|
@@ -124,6 +154,10 @@ import Capacitor
|
|
124
154
|
aigensprint("handleUniversalLink has -- redirect:\(redirect)")
|
125
155
|
webContainerView.showLoading(true)
|
126
156
|
webContainerView.showError(false)
|
157
|
+
}else if newUrl.absoluteString.range(of: "aigensRedirect/") != nil, let redirect = newUrl.absoluteString.components(separatedBy:"aigensRedirect/").last, !redirect.isEmpty {
|
158
|
+
aigensprint("handleUniversalLink has -- aigensRedirect:\(redirect)")
|
159
|
+
webContainerView.showLoading(true)
|
160
|
+
webContainerView.showError(false)
|
127
161
|
}
|
128
162
|
|
129
163
|
webView?.load(rUrl)
|
@@ -135,11 +169,14 @@ import Capacitor
|
|
135
169
|
}
|
136
170
|
|
137
171
|
aigensprint("handleUniversalLink url:\(object)")
|
138
|
-
guard
|
172
|
+
guard var url = object["url"] as? URL else {
|
139
173
|
return
|
140
174
|
}
|
141
175
|
|
142
|
-
|
176
|
+
url = decodeURIComponent(url);
|
177
|
+
|
178
|
+
|
179
|
+
if universalLink.isEmpty || (!url.absoluteString.starts(with: universalLink) && !universalLink.contains("aigens=true")) {
|
143
180
|
return;
|
144
181
|
}
|
145
182
|
|
@@ -151,6 +188,10 @@ import Capacitor
|
|
151
188
|
aigensprint("handleUniversalLink has -- redirect:\(redirect)")
|
152
189
|
webContainerView.showLoading(true)
|
153
190
|
webContainerView.showError(false)
|
191
|
+
}else if newUrl.absoluteString.range(of: "aigensRedirect/") != nil, let redirect = newUrl.absoluteString.components(separatedBy:"aigensRedirect/").last, !redirect.isEmpty {
|
192
|
+
aigensprint("handleUniversalLink has -- aigensRedirect:\(redirect)")
|
193
|
+
webContainerView.showLoading(true)
|
194
|
+
webContainerView.showError(false)
|
154
195
|
}
|
155
196
|
|
156
197
|
|
@@ -206,6 +247,20 @@ import Capacitor
|
|
206
247
|
self.externalProtocols.append(contentsOf: externalProtocols)
|
207
248
|
}
|
208
249
|
|
250
|
+
if let addPaddingProtocols = options?["addPaddingProtocols"] as? [String] {
|
251
|
+
self.addPaddingProtocols.append(contentsOf: addPaddingProtocols)
|
252
|
+
}
|
253
|
+
|
254
|
+
}
|
255
|
+
|
256
|
+
private func decodeURIComponent(_ url: URL) -> URL {
|
257
|
+
let str = url.absoluteString
|
258
|
+
let urlStr = str.removingPercentEncoding ?? str
|
259
|
+
return URL(string: urlStr) ?? url
|
260
|
+
}
|
261
|
+
|
262
|
+
private func decodeURIComponent(_ str: String) -> String {
|
263
|
+
return str.removingPercentEncoding ?? str
|
209
264
|
}
|
210
265
|
|
211
266
|
public final func loadWebViewCustom() {
|
@@ -215,6 +270,13 @@ import Capacitor
|
|
215
270
|
|
216
271
|
|
217
272
|
let urlString = self.options?["url"] as? String;
|
273
|
+
// urlString = "https://payment2.pizzahut.com.hk/v3/Payment/Completed?TransId=N224A2306130302&Code=4F19FC65-E099-4339-ADF4-3986EF539233"
|
274
|
+
// urlString = "https://payment2.pizzahut.com.hk/v3/Payment/UserCancel?TransId=N224A2306130301&Code=44D4B103-4962-432E-A323-086D46F8BB6F"
|
275
|
+
// urlString = "https://payment2.pizzahut.com.hk/v3/Payment/Completed?TransId=A224A2306131102&Code=104A53FB-053E-4FC1-870E-29D7B39AE2C5"
|
276
|
+
|
277
|
+
// urlString = "https%3a%2f%2fpayment2.pizzahut.com.hk%2fv3%2fPayment%2fCompleted%3fTransId%3dA224A2306131102%26Code%3d104A53FB-053E-4FC1-870E-29D7B39AE2C5";
|
278
|
+
//
|
279
|
+
// urlString = decodeURIComponent(urlString!)
|
218
280
|
|
219
281
|
if(urlString == nil){
|
220
282
|
return;
|
@@ -311,19 +373,40 @@ extension WebContainerViewController: WKNavigationDelegate {
|
|
311
373
|
}
|
312
374
|
|
313
375
|
aigensprint("navURL--:\(navURL)")
|
376
|
+
if !universalLink.isEmpty && (navURL.absoluteString.starts(with: universalLink) || universalLink.contains("aigens=true")) {
|
314
377
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
378
|
+
if navURL.absoluteString.range(of: "redirect=") != nil, var redirect = navURL.absoluteString.components(separatedBy:"redirect=").last{
|
379
|
+
if !redirect.starts(with: "http://") && !redirect.starts(with: "https://") {
|
380
|
+
redirect = "https://" + redirect
|
381
|
+
}
|
382
|
+
if let redirectUrl = URL(string: redirect) {
|
383
|
+
self.redirectLink = redirect
|
384
|
+
aigensprint("navURL-- redirect:\(redirect)")
|
385
|
+
webContainerView.showLoading(true)
|
386
|
+
webContainerView.showError(false)
|
387
|
+
let rUrl = URLRequest(url: redirectUrl)
|
388
|
+
webView.load(rUrl)
|
389
|
+
decisionHandler(.cancel)
|
390
|
+
return;
|
391
|
+
}
|
324
392
|
}
|
325
|
-
|
326
|
-
|
393
|
+
|
394
|
+
if navURL.absoluteString.range(of: "aigensRedirect/") != nil, var redirect = navURL.absoluteString.components(separatedBy:"aigensRedirect/").last, !redirect.isEmpty{
|
395
|
+
if !redirect.starts(with: "http://") && !redirect.starts(with: "https://") {
|
396
|
+
redirect = "https://" + redirect
|
397
|
+
}
|
398
|
+
if let redirectUrl = URL(string: redirect) {
|
399
|
+
self.redirectLink = redirect
|
400
|
+
aigensprint("navURL-- aigensRedirect:\(redirect)")
|
401
|
+
webContainerView.showLoading(true)
|
402
|
+
webContainerView.showError(false)
|
403
|
+
let rUrl = URLRequest(url: redirectUrl)
|
404
|
+
webView.load(rUrl)
|
405
|
+
decisionHandler(.cancel)
|
406
|
+
return;
|
407
|
+
}
|
408
|
+
}
|
409
|
+
|
327
410
|
}
|
328
411
|
|
329
412
|
var isCanOpen = false
|
@@ -394,9 +477,27 @@ extension WebContainerViewController: WKNavigationDelegate {
|
|
394
477
|
// webView.isOpaque = isOpaque
|
395
478
|
// webViewLoadingState = .subsequentLoad
|
396
479
|
// }
|
480
|
+
|
481
|
+
if let navURL = webView.url, isPaddingUrl(navURL) {
|
482
|
+
webView.evaluateJavaScript("""
|
483
|
+
let bg = document.getElementsByTagName('body');
|
484
|
+
if (bg && bg[0]) {
|
485
|
+
bg[0].style.paddingTop = "\(UIDevice.xp_statusBarHeight())px";
|
486
|
+
}
|
487
|
+
|
488
|
+
let app = document.querySelector('body>#app');
|
489
|
+
if (app && window) {
|
490
|
+
if (window.getComputedStyle(app).position == 'absolute') {
|
491
|
+
app.style.top = "\(UIDevice.xp_statusBarHeight())px";
|
492
|
+
}
|
493
|
+
}
|
494
|
+
|
495
|
+
""")
|
496
|
+
}
|
497
|
+
|
397
498
|
webContainerView.showLoading(false)
|
398
499
|
webContainerView.showError(false)
|
399
|
-
CAPLog.print("⚡️ WebView loaded")
|
500
|
+
CAPLog.print("⚡️ WebView loaded:\(webView.url)")
|
400
501
|
}
|
401
502
|
|
402
503
|
// The force unwrap is part of the protocol declaration, so we should keep it.
|
@@ -464,3 +565,70 @@ extension UIColor {
|
|
464
565
|
alpha: alpha);
|
465
566
|
}
|
466
567
|
}
|
568
|
+
|
569
|
+
|
570
|
+
extension UIDevice {
|
571
|
+
|
572
|
+
/// 顶部安全区高度
|
573
|
+
static func xp_safeDistanceTop() -> CGFloat {
|
574
|
+
if #available(iOS 13.0, *) {
|
575
|
+
let scene = UIApplication.shared.connectedScenes.first
|
576
|
+
guard let windowScene = scene as? UIWindowScene else { return 0 }
|
577
|
+
guard let window = windowScene.windows.first else { return 0 }
|
578
|
+
return window.safeAreaInsets.top
|
579
|
+
} else if #available(iOS 11.0, *) {
|
580
|
+
guard let window = UIApplication.shared.windows.first else { return 0 }
|
581
|
+
return window.safeAreaInsets.top
|
582
|
+
}
|
583
|
+
return 0;
|
584
|
+
}
|
585
|
+
|
586
|
+
/// 底部安全区高度
|
587
|
+
static func xp_safeDistanceBottom() -> CGFloat {
|
588
|
+
if #available(iOS 13.0, *) {
|
589
|
+
let scene = UIApplication.shared.connectedScenes.first
|
590
|
+
guard let windowScene = scene as? UIWindowScene else { return 0 }
|
591
|
+
guard let window = windowScene.windows.first else { return 0 }
|
592
|
+
return window.safeAreaInsets.bottom
|
593
|
+
} else if #available(iOS 11.0, *) {
|
594
|
+
guard let window = UIApplication.shared.windows.first else { return 0 }
|
595
|
+
return window.safeAreaInsets.bottom
|
596
|
+
}
|
597
|
+
return 0;
|
598
|
+
}
|
599
|
+
|
600
|
+
/// 顶部状态栏高度(包括安全区)
|
601
|
+
static func xp_statusBarHeight() -> CGFloat {
|
602
|
+
var statusBarHeight: CGFloat = 0
|
603
|
+
if #available(iOS 13.0, *) {
|
604
|
+
let scene = UIApplication.shared.connectedScenes.first
|
605
|
+
guard let windowScene = scene as? UIWindowScene else { return 0 }
|
606
|
+
guard let statusBarManager = windowScene.statusBarManager else { return 0 }
|
607
|
+
statusBarHeight = statusBarManager.statusBarFrame.height
|
608
|
+
} else {
|
609
|
+
statusBarHeight = UIApplication.shared.statusBarFrame.height
|
610
|
+
}
|
611
|
+
CAPLog.print("navURL-- height:\(statusBarHeight)")
|
612
|
+
return statusBarHeight
|
613
|
+
}
|
614
|
+
|
615
|
+
/// 导航栏高度
|
616
|
+
static func xp_navigationBarHeight() -> CGFloat {
|
617
|
+
return 44.0
|
618
|
+
}
|
619
|
+
|
620
|
+
/// 状态栏+导航栏的高度
|
621
|
+
static func xp_navigationFullHeight() -> CGFloat {
|
622
|
+
return UIDevice.xp_statusBarHeight() + UIDevice.xp_navigationBarHeight()
|
623
|
+
}
|
624
|
+
|
625
|
+
/// 底部导航栏高度
|
626
|
+
static func xp_tabBarHeight() -> CGFloat {
|
627
|
+
return 49.0
|
628
|
+
}
|
629
|
+
|
630
|
+
/// 底部导航栏高度(包括安全区)
|
631
|
+
static func xp_tabBarFullHeight() -> CGFloat {
|
632
|
+
return UIDevice.xp_tabBarHeight() + UIDevice.xp_safeDistanceBottom()
|
633
|
+
}
|
634
|
+
}
|