@aigens/aigens-sdk-core 0.5.0 → 0.5.2
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.
- package/android/src/main/java/com/aigens/sdk/WebContainerActivity.java +182 -14
- package/android/src/main/java/com/aigens/sdk/plugins/CorePlugin.java +117 -18
- package/android/src/main/res/layout/sdk_layout_main.xml +1 -0
- package/ios/Plugin/CorePlugin.m +1 -0
- package/ios/Plugin/CorePlugin.swift +55 -2
- package/ios/Plugin/SecondWebContainerView.swift +157 -0
- package/ios/Plugin/WebContainerViewController.swift +17 -0
- package/package.json +1 -1
@@ -9,17 +9,24 @@ import android.graphics.Color;
|
|
9
9
|
import android.net.Uri;
|
10
10
|
import android.os.Build;
|
11
11
|
import android.os.Bundle;
|
12
|
+
import android.os.Handler;
|
13
|
+
import android.os.Looper;
|
12
14
|
import android.text.TextUtils;
|
13
15
|
import android.util.Log;
|
14
16
|
import android.view.View;
|
17
|
+
import android.view.ViewGroup;
|
18
|
+
import android.webkit.JavascriptInterface;
|
15
19
|
import android.webkit.ServiceWorkerClient;
|
16
20
|
import android.webkit.ServiceWorkerController;
|
17
21
|
import android.webkit.ValueCallback;
|
22
|
+
import android.webkit.WebResourceError;
|
18
23
|
import android.webkit.WebResourceRequest;
|
19
24
|
import android.webkit.WebResourceResponse;
|
20
25
|
import android.webkit.WebSettings;
|
21
26
|
import android.webkit.WebView;
|
27
|
+
import android.webkit.WebViewClient;
|
22
28
|
import android.widget.Button;
|
29
|
+
import android.widget.FrameLayout;
|
23
30
|
|
24
31
|
import com.aigens.sdk.plugins.CorePlugin;
|
25
32
|
import com.getcapacitor.Bridge;
|
@@ -286,18 +293,21 @@ public class WebContainerActivity extends BridgeActivity {
|
|
286
293
|
|
287
294
|
List<Class<? extends Plugin>> auto = loadPlugins();
|
288
295
|
|
289
|
-
|
296
|
+
if (auto != null) {
|
297
|
+
for (Class c : auto) {
|
290
298
|
|
291
|
-
|
299
|
+
String clsName = c.getName();
|
292
300
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
301
|
+
if (clsName.endsWith("SplashScreenPlugin")) {
|
302
|
+
//don't add the splash screen plugin so it doesn't show the splash screen again
|
303
|
+
} else {
|
304
|
+
allPlugins.add(c);
|
305
|
+
}
|
298
306
|
|
307
|
+
}
|
299
308
|
}
|
300
309
|
|
310
|
+
|
301
311
|
// com.getcapacitor.community.firebaseanalytics.FirebaseAnalytics
|
302
312
|
addExtraPlugins(new String[]{
|
303
313
|
"com.aigens.googlepay.GooglePayPlugin",
|
@@ -307,6 +317,10 @@ public class WebContainerActivity extends BridgeActivity {
|
|
307
317
|
"com.aigens.alipay.AliPayPlugin",
|
308
318
|
"com.aigens.alipayhk.AliPayhkPlugin",
|
309
319
|
"com.aigens.payme.PaymePlugin",
|
320
|
+
"com.aigens.sdk.alipay.AlipayPlugin",
|
321
|
+
"com.aigens.sdk.wechat.WechatPlugin",
|
322
|
+
"com.aigens.sdk.utils.AigensUtilsPlugin",
|
323
|
+
"com.aigens.sdk.preferences.AigensPreferencesPlugin"
|
310
324
|
}, allPlugins);
|
311
325
|
addExtraPlugins(intent.getStringArrayExtra("extraClasspaths"), allPlugins);
|
312
326
|
|
@@ -318,6 +332,8 @@ public class WebContainerActivity extends BridgeActivity {
|
|
318
332
|
this.config = cc;
|
319
333
|
this.bridgeBuilder.setInstanceState(currentInstanceState);
|
320
334
|
this.load();
|
335
|
+
this.bridgeBuilder.setPlugins(allPlugins);
|
336
|
+
|
321
337
|
|
322
338
|
//still have time to override webview client to avoid any intercept
|
323
339
|
|
@@ -358,23 +374,49 @@ public class WebContainerActivity extends BridgeActivity {
|
|
358
374
|
// sometime not callback , use Use manual injection js
|
359
375
|
// disableServiceWorker(this.url, this.bridge);
|
360
376
|
|
377
|
+
|
378
|
+
// test
|
379
|
+
// new Handler(getMainLooper()).postDelayed(new Runnable() {
|
380
|
+
// @Override
|
381
|
+
// public void run() {
|
382
|
+
// openSecondBrowser("https://cloud-api.loginradius.com/sso/oidc/v2/loyaltypos/authorize?client_id=1196e953-6981-4dcb-ab65-99102facbc2d&redirect_uri=https%3a%2f%2fuatyuuapi.pizzahut.com.hk%2fapi%2fV3%2fYuu%2fLogin%2fCallBack%2f4b0717d0-9203-402c-8a09-202503111111&scope=openid&response_mode=query&response_type=code&ui_locales=ecomm_zh-hant", null, new SecondBrowserInterface() {
|
383
|
+
// @Override
|
384
|
+
// public void secondBrowserInterfaceYuuLoginCallback(View targetView, String status, String yuuToken, String cardNo, String warning, boolean cancel) {
|
385
|
+
// Log.i("Jason open", status+yuuToken+cardNo+warning+cancel);
|
386
|
+
// ViewGroup parent = (ViewGroup) targetView.getParent();
|
387
|
+
// if (parent != null) {
|
388
|
+
// parent.removeView(targetView);
|
389
|
+
// }
|
390
|
+
// }
|
391
|
+
|
392
|
+
// @Override
|
393
|
+
// public void customHandler(View targetView, String params1, String params2) {
|
394
|
+
|
395
|
+
// }
|
396
|
+
// });
|
397
|
+
// }
|
398
|
+
// }, 20000);
|
399
|
+
|
361
400
|
}
|
362
401
|
|
363
402
|
@Override
|
364
403
|
protected void load() {
|
365
404
|
List<Class<? extends Plugin>> allPlugins = new ArrayList<>();
|
366
405
|
List<Class<? extends Plugin>> auto = loadPlugins();
|
367
|
-
|
406
|
+
if (auto != null) {
|
407
|
+
for (Class c : auto) {
|
368
408
|
|
369
|
-
|
409
|
+
String clsName = c.getName();
|
370
410
|
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
411
|
+
if (clsName.endsWith("SplashScreenPlugin")) {
|
412
|
+
//don't add the splash screen plugin so it doesn't show the splash screen again
|
413
|
+
} else {
|
414
|
+
allPlugins.add(c);
|
415
|
+
}
|
376
416
|
|
417
|
+
}
|
377
418
|
}
|
419
|
+
|
378
420
|
this.bridgeBuilder.setPlugins(allPlugins);
|
379
421
|
super.load();
|
380
422
|
}
|
@@ -641,9 +683,12 @@ public class WebContainerActivity extends BridgeActivity {
|
|
641
683
|
return null;
|
642
684
|
}
|
643
685
|
|
686
|
+
private boolean shouldHandleBackPress = true;
|
644
687
|
@Override
|
645
688
|
public void onBackPressed() {
|
646
689
|
|
690
|
+
if (!shouldHandleBackPress) return;
|
691
|
+
|
647
692
|
super.onBackPressed();
|
648
693
|
|
649
694
|
boolean canBack = this.bridge.getWebView().canGoBack();
|
@@ -844,5 +889,128 @@ public class WebContainerActivity extends BridgeActivity {
|
|
844
889
|
}*/
|
845
890
|
}
|
846
891
|
|
892
|
+
private static final int SECOND_WEBVIEW_ID = 1000001;
|
893
|
+
private String currentUrl = "";
|
894
|
+
public void openSecondBrowser(String url, String serviceName, SecondBrowserInterface callback) {
|
895
|
+
|
896
|
+
try {
|
897
|
+
Handler mainHandler = new Handler(getMainLooper());
|
898
|
+
mainHandler.post(() -> {
|
899
|
+
FrameLayout layout = findViewById(R.id.aigens_sdk_layout_main);
|
900
|
+
|
901
|
+
WebView existingWebView = layout.findViewById(SECOND_WEBVIEW_ID);
|
902
|
+
if (existingWebView != null) {
|
903
|
+
layout.removeView(existingWebView);
|
904
|
+
}
|
905
|
+
|
906
|
+
|
907
|
+
WebView webView = new WebView(this);
|
908
|
+
webView.setId(SECOND_WEBVIEW_ID);
|
909
|
+
|
910
|
+
// webView.setVisibility(showError ? View.VISIBLE : View.INVISIBLE);
|
911
|
+
// webView.setVisibility(View.VISIBLE);
|
912
|
+
|
913
|
+
WebSettings webSettings = webView.getSettings();
|
914
|
+
webSettings.setJavaScriptEnabled(true);
|
915
|
+
webSettings.setDomStorageEnabled(true);
|
916
|
+
|
917
|
+
|
918
|
+
layout.addView(webView, new FrameLayout.LayoutParams(
|
919
|
+
FrameLayout.LayoutParams.MATCH_PARENT,
|
920
|
+
FrameLayout.LayoutParams.MATCH_PARENT
|
921
|
+
));
|
922
|
+
|
923
|
+
webView.setWebViewClient(new WebViewClient() {
|
924
|
+
@Override
|
925
|
+
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
926
|
+
|
927
|
+
Uri url = request.getUrl();
|
928
|
+
// Log.i("jason shouldOverrideUrl", url.toString());
|
929
|
+
|
930
|
+
//return super.shouldOverrideUrlLoading(view, request);
|
931
|
+
currentUrl = url.toString();
|
932
|
+
new Handler(getMainLooper()).postDelayed(new Runnable() {
|
933
|
+
@Override
|
934
|
+
public void run() {
|
935
|
+
if ("about:blank".equals(currentUrl)) {
|
936
|
+
shouldHandleBackPress = true;
|
937
|
+
callback.secondBrowserInterfaceYuuLoginCallback(webView, "", "", "", "", true);;
|
938
|
+
}
|
939
|
+
}
|
940
|
+
}, 1000); // 1s
|
941
|
+
return false;
|
942
|
+
}
|
943
|
+
|
944
|
+
@Override
|
945
|
+
public void onPageStarted(WebView view, String url, Bitmap favicon) {
|
946
|
+
|
947
|
+
super.onPageStarted(view, url, favicon);
|
948
|
+
// Log.i("jason onPageStarted", url);
|
949
|
+
|
950
|
+
|
951
|
+
}
|
952
|
+
|
953
|
+
@Override
|
954
|
+
public void onPageFinished(WebView view, String url) {
|
955
|
+
// Log.i("Jason onPageFinished", url);
|
956
|
+
super.onPageFinished(view, url);
|
957
|
+
|
958
|
+
}
|
959
|
+
|
960
|
+
@Override
|
961
|
+
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
|
962
|
+
super.onReceivedError(view, request, error);
|
963
|
+
// Log.i("Jason onReceivedError", error.toString());
|
964
|
+
shouldHandleBackPress = true;
|
965
|
+
ViewGroup parent = (ViewGroup) view.getParent();
|
966
|
+
if (parent != null) {
|
967
|
+
parent.removeView(view);
|
968
|
+
}
|
969
|
+
}
|
970
|
+
});
|
971
|
+
|
972
|
+
webView.addJavascriptInterface(new SecondWebAppInterface(webView, callback), "android");
|
973
|
+
if (serviceName != null) {
|
974
|
+
webView.addJavascriptInterface(new SecondWebAppInterface(webView, callback), serviceName);
|
975
|
+
}
|
976
|
+
|
977
|
+
shouldHandleBackPress = false;
|
978
|
+
webView.loadUrl(url);
|
979
|
+
});
|
980
|
+
}catch (Exception e) {
|
981
|
+
e.printStackTrace();
|
982
|
+
}
|
983
|
+
|
984
|
+
|
985
|
+
|
986
|
+
}
|
987
|
+
|
988
|
+
public class SecondWebAppInterface {
|
989
|
+
private SecondBrowserInterface callback;
|
990
|
+
private View targetView;
|
991
|
+
public SecondWebAppInterface(View targetView, SecondBrowserInterface callback) {
|
992
|
+
this.callback = callback;
|
993
|
+
this.targetView = targetView;
|
994
|
+
}
|
995
|
+
|
996
|
+
@JavascriptInterface
|
997
|
+
public void yuuLoginHandler(String status, String yuuToken, String cardNo, String warning) {
|
998
|
+
shouldHandleBackPress = true;
|
999
|
+
callback.secondBrowserInterfaceYuuLoginCallback(targetView, status, yuuToken, cardNo, warning, false);
|
1000
|
+
}
|
1001
|
+
|
1002
|
+
@JavascriptInterface
|
1003
|
+
public void customHandler(String params1, String params2) {
|
1004
|
+
shouldHandleBackPress = true;
|
1005
|
+
callback.customHandler(targetView, params1, params2);
|
1006
|
+
}
|
1007
|
+
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
public interface SecondBrowserInterface {
|
1011
|
+
void secondBrowserInterfaceYuuLoginCallback(View targetView, String status, String yuuToken, String cardNo, String warning, boolean cancel);
|
1012
|
+
void customHandler(View targetView, String params1, String params2);
|
1013
|
+
|
1014
|
+
}
|
847
1015
|
|
848
1016
|
}
|
@@ -2,15 +2,20 @@ package com.aigens.sdk.plugins;
|
|
2
2
|
|
3
3
|
import android.Manifest;
|
4
4
|
import android.app.Activity;
|
5
|
+
import android.app.ActivityManager;
|
5
6
|
import android.content.ClipData;
|
6
7
|
import android.content.ClipDescription;
|
7
8
|
import android.content.ClipboardManager;
|
9
|
+
import android.content.ComponentName;
|
8
10
|
import android.content.Context;
|
9
11
|
import android.content.Intent;
|
10
12
|
import android.content.pm.PackageInfo;
|
11
13
|
import android.content.pm.PackageManager;
|
12
14
|
import android.net.Uri;
|
15
|
+
import android.os.Build;
|
13
16
|
import android.os.Handler;
|
17
|
+
import android.view.View;
|
18
|
+
import android.view.ViewGroup;
|
14
19
|
import android.webkit.WebSettings;
|
15
20
|
import android.webkit.WebView;
|
16
21
|
|
@@ -449,31 +454,42 @@ public class CorePlugin extends Plugin {
|
|
449
454
|
public void readClipboard(PluginCall call) {
|
450
455
|
JSObject object = new JSObject();
|
451
456
|
try {
|
452
|
-
|
453
457
|
ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
454
|
-
|
458
|
+
String value = "";
|
459
|
+
String type = "text/plain";
|
460
|
+
|
455
461
|
if (clipboard.hasPrimaryClip()) {
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
+
ClipData clipData = clipboard.getPrimaryClip();
|
463
|
+
if (clipData != null && clipData.getItemCount() > 0) {
|
464
|
+
ClipData.Item item = clipData.getItemAt(0);
|
465
|
+
ClipDescription description = clipData.getDescription();
|
466
|
+
|
467
|
+
// 优先使用系统报告的MIME类型
|
468
|
+
if (description != null && description.getMimeTypeCount() > 0) {
|
469
|
+
type = description.getMimeType(0);
|
470
|
+
}
|
471
|
+
|
472
|
+
// 获取剪贴板内容
|
473
|
+
CharSequence text = item.getText();
|
474
|
+
if (text != null) {
|
475
|
+
value = text.toString();
|
476
|
+
} else {
|
477
|
+
// 处理非文本内容
|
478
|
+
value = item.coerceToText(getContext()).toString();
|
479
|
+
|
480
|
+
// 如果系统未报告类型,检查URI格式
|
481
|
+
if (type.equals("text/plain") && value.startsWith("data:")) {
|
482
|
+
type = value.split(";")[0].split(":")[1];
|
483
|
+
}
|
484
|
+
}
|
462
485
|
}
|
463
486
|
}
|
464
|
-
|
465
|
-
|
466
|
-
object.put("value", value.toString());
|
467
|
-
}else {
|
468
|
-
object.put("value", "");
|
469
|
-
}
|
470
|
-
if (value != null && value.toString().startsWith("data:")) {
|
471
|
-
type = value.toString().split(";")[0].split(":")[1];
|
472
|
-
}
|
487
|
+
|
488
|
+
object.put("value", value);
|
473
489
|
object.put("type", type);
|
474
490
|
} catch (Exception e) {
|
475
491
|
object.put("value", "");
|
476
|
-
object.put("type", "");
|
492
|
+
object.put("type", "text/plain");
|
477
493
|
e.printStackTrace();
|
478
494
|
}
|
479
495
|
call.resolve(object);
|
@@ -527,4 +543,87 @@ public class CorePlugin extends Plugin {
|
|
527
543
|
call.resolve(ret);
|
528
544
|
}
|
529
545
|
|
546
|
+
@PluginMethod
|
547
|
+
public void openSecondBrowser(PluginCall call) {
|
548
|
+
String url = call.getString("url", null);
|
549
|
+
String serviceName = call.getString("serviceName", null);
|
550
|
+
if (url == null) {
|
551
|
+
call.reject("url is missing");
|
552
|
+
return;
|
553
|
+
}
|
554
|
+
|
555
|
+
ActivityManager activityManager = (ActivityManager) getActivity().getSystemService(Context.ACTIVITY_SERVICE);
|
556
|
+
if (activityManager == null) {
|
557
|
+
call.reject("activityManager is missing");
|
558
|
+
return;
|
559
|
+
}
|
560
|
+
Activity currentActivity = null;
|
561
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
562
|
+
List<ActivityManager.AppTask> tasks = activityManager.getAppTasks();
|
563
|
+
if (tasks != null && !tasks.isEmpty()) {
|
564
|
+
ActivityManager.RecentTaskInfo taskInfo = tasks.get(0).getTaskInfo();
|
565
|
+
if (taskInfo.topActivity.getClassName().equals(WebContainerActivity.class.getName())) {
|
566
|
+
try {
|
567
|
+
Class<?> activityClass = Class.forName(taskInfo.topActivity.getClassName());
|
568
|
+
currentActivity = (Activity) activityClass.newInstance();
|
569
|
+
} catch (Exception e) {
|
570
|
+
e.printStackTrace();
|
571
|
+
}
|
572
|
+
|
573
|
+
}
|
574
|
+
}
|
575
|
+
} else {
|
576
|
+
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
|
577
|
+
if (tasks != null && !tasks.isEmpty()) {
|
578
|
+
ActivityManager.RunningTaskInfo taskInfo = tasks.get(0);
|
579
|
+
if (taskInfo.topActivity.getClassName().equals(WebContainerActivity.class.getName())) {
|
580
|
+
try {
|
581
|
+
Class<?> activityClass = Class.forName(taskInfo.topActivity.getClassName());
|
582
|
+
currentActivity = (Activity) activityClass.newInstance();
|
583
|
+
} catch (Exception e) {
|
584
|
+
e.printStackTrace();
|
585
|
+
}
|
586
|
+
|
587
|
+
|
588
|
+
}
|
589
|
+
}
|
590
|
+
}
|
591
|
+
|
592
|
+
if (currentActivity == null) {
|
593
|
+
call.reject("currentActivity is missing");
|
594
|
+
return;
|
595
|
+
}
|
596
|
+
|
597
|
+
if (currentActivity instanceof WebContainerActivity) {
|
598
|
+
((WebContainerActivity) currentActivity).openSecondBrowser(url, null, new WebContainerActivity.SecondBrowserInterface() {
|
599
|
+
@Override
|
600
|
+
public void secondBrowserInterfaceYuuLoginCallback(View targetView, String status, String yuuToken, String cardNo, String warning, boolean cancel) {
|
601
|
+
JSObject ret = new JSObject();
|
602
|
+
ret.put("cancel", cancel);
|
603
|
+
ret.put("yuuToken", yuuToken);
|
604
|
+
ret.put("cardNo", cardNo);
|
605
|
+
ret.put("warning", warning);
|
606
|
+
call.resolve(ret);
|
607
|
+
ViewGroup parent = (ViewGroup) targetView.getParent();
|
608
|
+
if (parent != null) {
|
609
|
+
parent.removeView(targetView);
|
610
|
+
}
|
611
|
+
}
|
612
|
+
|
613
|
+
@Override
|
614
|
+
public void customHandler(View targetView, String params1, String params2) {
|
615
|
+
JSObject ret = new JSObject();
|
616
|
+
ret.put("params1", params1);
|
617
|
+
ret.put("params2", params2);
|
618
|
+
call.resolve(ret);
|
619
|
+
ViewGroup parent = (ViewGroup) targetView.getParent();
|
620
|
+
if (parent != null) {
|
621
|
+
parent.removeView(targetView);
|
622
|
+
}
|
623
|
+
}
|
624
|
+
});
|
625
|
+
}
|
626
|
+
|
627
|
+
}
|
628
|
+
|
530
629
|
}
|
package/ios/Plugin/CorePlugin.m
CHANGED
@@ -8,6 +8,7 @@ CAP_PLUGIN(CorePlugin, "Core",
|
|
8
8
|
CAP_PLUGIN_METHOD(dismiss, CAPPluginReturnPromise);
|
9
9
|
CAP_PLUGIN_METHOD(finish, CAPPluginReturnPromise);
|
10
10
|
CAP_PLUGIN_METHOD(openBrowser, CAPPluginReturnPromise);
|
11
|
+
CAP_PLUGIN_METHOD(openSecondBrowser, CAPPluginReturnPromise);
|
11
12
|
CAP_PLUGIN_METHOD(getDeeplink, CAPPluginReturnPromise);
|
12
13
|
CAP_PLUGIN_METHOD(getMember, CAPPluginReturnPromise);
|
13
14
|
CAP_PLUGIN_METHOD(isInstalledApp, CAPPluginReturnPromise);
|
@@ -27,11 +27,20 @@ public class CorePlugin: CAPPlugin {
|
|
27
27
|
public static var member: Dictionary<String, Any>?
|
28
28
|
public static var deeplink: Dictionary<String, Any>?
|
29
29
|
|
30
|
-
|
30
|
+
static var StaticBridge: CAPBridgeProtocol?
|
31
31
|
public override func load() {
|
32
32
|
handleOpenUrl()
|
33
|
+
CorePlugin.StaticBridge = self.bridge;
|
34
|
+
}
|
35
|
+
|
36
|
+
public static func getCoreInstance() -> CorePlugin? {
|
37
|
+
if let instance = StaticBridge?.plugin(withName: "Core") as? CorePlugin {
|
38
|
+
return instance
|
39
|
+
}
|
40
|
+
return nil
|
33
41
|
}
|
34
42
|
|
43
|
+
|
35
44
|
private func handleOpenUrl() {
|
36
45
|
NotificationCenter.default.addObserver(self, selector: #selector(self.handleUniversalLink(notification:)), name: Notification.Name.capacitorOpenUniversalLink, object: nil)
|
37
46
|
|
@@ -111,7 +120,7 @@ public class CorePlugin: CAPPlugin {
|
|
111
120
|
|
112
121
|
activityViewController.completionWithItemsHandler = { (activityType, completed, returnedItems, activityError) in
|
113
122
|
// Start the activity chosen to complete the payment
|
114
|
-
print("Start the activity chosen to complete the payment : \(completed)")
|
123
|
+
// print("Start the activity chosen to complete the payment : \(completed)")
|
115
124
|
if !completed {
|
116
125
|
CorePlugin.HKFPSCall?.keepAlive = false;
|
117
126
|
CorePlugin.HKFPSCall = nil;
|
@@ -259,6 +268,41 @@ public class CorePlugin: CAPPlugin {
|
|
259
268
|
CorePlugin.dismissCall = call
|
260
269
|
}
|
261
270
|
|
271
|
+
var openEmbedBrowserCallback: CAPPluginCall?
|
272
|
+
@objc func openSecondBrowser(_ call: CAPPluginCall) {
|
273
|
+
aigensprint("CorePlugin openEmbedBrowser")
|
274
|
+
guard let url = call.getString("url") else {
|
275
|
+
call.reject("url is missing")
|
276
|
+
return;
|
277
|
+
}
|
278
|
+
let serviceName = call.getString("serviceName")
|
279
|
+
|
280
|
+
DispatchQueue.main.async {
|
281
|
+
guard let currentVc = self.bridge?.viewController?.view else {
|
282
|
+
call.reject("currentVc is missing")
|
283
|
+
return;
|
284
|
+
}
|
285
|
+
|
286
|
+
let secondView = SecondWebContainerView()
|
287
|
+
self.insertView(secondView, currentVc)
|
288
|
+
secondView.delegate = self
|
289
|
+
secondView.serviceName = serviceName
|
290
|
+
secondView.loadUrl(urlString: url)
|
291
|
+
call.keepAlive = true
|
292
|
+
self.openEmbedBrowserCallback = call
|
293
|
+
}
|
294
|
+
|
295
|
+
}
|
296
|
+
|
297
|
+
public func insertView(_ newView: SecondWebContainerView, _ parentView: UIView) {
|
298
|
+
parentView.subviews
|
299
|
+
.filter { $0 is SecondWebContainerView }
|
300
|
+
.forEach { $0.removeFromSuperview() }
|
301
|
+
|
302
|
+
parentView.addSubview(newView)
|
303
|
+
newView.setCustomFrame(CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height:UIScreen.main.bounds.size.height))
|
304
|
+
}
|
305
|
+
|
262
306
|
|
263
307
|
@objc func openBrowser(_ call: CAPPluginCall) {
|
264
308
|
|
@@ -495,6 +539,15 @@ public class CorePlugin: CAPPlugin {
|
|
495
539
|
|
496
540
|
|
497
541
|
|
542
|
+
}
|
543
|
+
|
544
|
+
extension CorePlugin: SecondWebContainerDelegate {
|
545
|
+
|
546
|
+
public func secondWebContainerViewYuuLoginCallback(view: UIView, data: [String: Any]) {
|
547
|
+
guard let callback = openEmbedBrowserCallback else {return}
|
548
|
+
callback.resolve(data)
|
549
|
+
view.removeFromSuperview()
|
550
|
+
}
|
498
551
|
}
|
499
552
|
|
500
553
|
|
@@ -0,0 +1,157 @@
|
|
1
|
+
//
|
2
|
+
// SecondWebContainerView.swift
|
3
|
+
// AigensSdkCore
|
4
|
+
//
|
5
|
+
// Created by 陈培爵 on 2025/3/10.
|
6
|
+
//
|
7
|
+
|
8
|
+
import WebKit
|
9
|
+
|
10
|
+
@objc public protocol SecondWebContainerDelegate: AnyObject {
|
11
|
+
func secondWebContainerViewYuuLoginCallback(view: UIView, data: [String: Any])
|
12
|
+
}
|
13
|
+
|
14
|
+
@objc open class SecondWebContainerView: UIView {
|
15
|
+
|
16
|
+
public let webView: WKWebView
|
17
|
+
|
18
|
+
private let messageHandlerName = "YuuLoginHandler"
|
19
|
+
private let messageHandlerName2 = "yuuLoginHandler"
|
20
|
+
private var messageHandler: SecondWebViewMessageHandler?
|
21
|
+
|
22
|
+
public weak var delegate: SecondWebContainerDelegate?
|
23
|
+
|
24
|
+
private var currentUrl: String?
|
25
|
+
public var serviceName: String?
|
26
|
+
override init(frame: CGRect) {
|
27
|
+
// 创建 WebView 配置
|
28
|
+
let webConfiguration = WKWebViewConfiguration()
|
29
|
+
webView = WKWebView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height:UIScreen.main.bounds.size.height), configuration: webConfiguration)
|
30
|
+
|
31
|
+
super.init(frame: frame)
|
32
|
+
setupView()
|
33
|
+
}
|
34
|
+
|
35
|
+
required public init?(coder: NSCoder) {
|
36
|
+
fatalError("init(coder:) has not been implemented")
|
37
|
+
}
|
38
|
+
|
39
|
+
private func setupView() {
|
40
|
+
|
41
|
+
addSubview(webView)
|
42
|
+
webView.translatesAutoresizingMaskIntoConstraints = false
|
43
|
+
NSLayoutConstraint.activate([
|
44
|
+
webView.topAnchor.constraint(equalTo: topAnchor),
|
45
|
+
webView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
46
|
+
webView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
47
|
+
webView.bottomAnchor.constraint(equalTo: bottomAnchor)
|
48
|
+
])
|
49
|
+
|
50
|
+
|
51
|
+
webView.navigationDelegate = self
|
52
|
+
webView.allowsBackForwardNavigationGestures = false
|
53
|
+
webView.scrollView.minimumZoomScale = 1.0
|
54
|
+
webView.scrollView.maximumZoomScale = 1.0
|
55
|
+
|
56
|
+
// 禁用双击缩放
|
57
|
+
let disableDoubleTapScript = """
|
58
|
+
var script = document.createElement('script');
|
59
|
+
script.textContent = 'document.documentElement.style.webkitTouchCallout = "none";';
|
60
|
+
document.documentElement.appendChild(script);
|
61
|
+
"""
|
62
|
+
let userScript = WKUserScript(source: disableDoubleTapScript,
|
63
|
+
injectionTime: .atDocumentEnd,
|
64
|
+
forMainFrameOnly: true)
|
65
|
+
webView.configuration.userContentController.addUserScript(userScript)
|
66
|
+
|
67
|
+
}
|
68
|
+
|
69
|
+
deinit {
|
70
|
+
|
71
|
+
print("SecondWebContainerView deinit")
|
72
|
+
webView.configuration.userContentController.removeScriptMessageHandler(forName: messageHandlerName)
|
73
|
+
}
|
74
|
+
|
75
|
+
public func loadUrl(urlString: String) {
|
76
|
+
guard let url = URL(string: urlString) else {
|
77
|
+
aigensprint("secondview Invalid URL: \(urlString)")
|
78
|
+
return
|
79
|
+
}
|
80
|
+
|
81
|
+
messageHandler = SecondWebViewMessageHandler(serviceName: self.serviceName, callback: { [weak self] message in
|
82
|
+
guard let s = self else { return }
|
83
|
+
self?.delegate?.secondWebContainerViewYuuLoginCallback(view: s, data: message)
|
84
|
+
})
|
85
|
+
|
86
|
+
webView.configuration.userContentController.add(messageHandler!, name: messageHandlerName)
|
87
|
+
webView.configuration.userContentController.add(messageHandler!, name: messageHandlerName2)
|
88
|
+
if let name = serviceName {
|
89
|
+
webView.configuration.userContentController.add(messageHandler!, name: name)
|
90
|
+
}
|
91
|
+
|
92
|
+
let request = URLRequest(url: url)
|
93
|
+
webView.load(request)
|
94
|
+
webView.navigationDelegate = self
|
95
|
+
}
|
96
|
+
|
97
|
+
|
98
|
+
public func setCustomFrame(_ frame: CGRect) {
|
99
|
+
self.frame = frame
|
100
|
+
layoutIfNeeded()
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
private class SecondWebViewMessageHandler: NSObject, WKScriptMessageHandler {
|
105
|
+
private let callback: ([String: Any]) -> Void
|
106
|
+
|
107
|
+
private let messageHandlerName = "YuuLoginHandler"
|
108
|
+
private let messageHandlerName2 = "yuuLoginHandler"
|
109
|
+
private var serviceName: String?
|
110
|
+
init(serviceName: String?, callback: @escaping ([String: Any]) -> Void) {
|
111
|
+
self.callback = callback
|
112
|
+
self.serviceName = serviceName
|
113
|
+
}
|
114
|
+
|
115
|
+
func userContentController(_ userContentController: WKUserContentController,
|
116
|
+
didReceive message: WKScriptMessage) {
|
117
|
+
// print("jason message:\(message.name)")
|
118
|
+
|
119
|
+
guard (message.name == messageHandlerName || message.name == messageHandlerName2 || message.name == serviceName ?? ""),
|
120
|
+
let messageBody = message.body as? [String: Any] else {
|
121
|
+
return
|
122
|
+
}
|
123
|
+
|
124
|
+
aigensprint("Received credit card token: \(messageBody)")
|
125
|
+
callback(messageBody)
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
// MARK: - WKNavigationDelegate 实现
|
130
|
+
extension SecondWebContainerView: WKNavigationDelegate {
|
131
|
+
public func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
|
132
|
+
if let navURL = navigationAction.request.url {
|
133
|
+
currentUrl = navURL.absoluteString
|
134
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
135
|
+
if let url = self.currentUrl, url == "about:blank" {
|
136
|
+
self.delegate?.secondWebContainerViewYuuLoginCallback(view: self, data: ["cancel": true])
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
}
|
141
|
+
|
142
|
+
|
143
|
+
decisionHandler(.allow)
|
144
|
+
}
|
145
|
+
|
146
|
+
public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
147
|
+
print("jason secondnavURL didFinish")
|
148
|
+
}
|
149
|
+
|
150
|
+
public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
151
|
+
|
152
|
+
print("jason secondnavURL didFail")
|
153
|
+
self.removeFromSuperview()
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
|
@@ -301,6 +301,23 @@ import Capacitor
|
|
301
301
|
return str.removingPercentEncoding ?? str
|
302
302
|
}
|
303
303
|
|
304
|
+
public func insertView(_ newView: SecondWebContainerView) {
|
305
|
+
|
306
|
+
if let parentView = self.view {
|
307
|
+
parentView.subviews
|
308
|
+
.filter { $0 is SecondWebContainerView }
|
309
|
+
.forEach { $0.removeFromSuperview() }
|
310
|
+
|
311
|
+
}
|
312
|
+
|
313
|
+
if webContainerView.superview != nil {
|
314
|
+
self.view.insertSubview(newView, belowSubview: webContainerView)
|
315
|
+
} else {
|
316
|
+
self.view.addSubview(newView)
|
317
|
+
}
|
318
|
+
newView.setCustomFrame(CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height:UIScreen.main.bounds.size.height))
|
319
|
+
}
|
320
|
+
|
304
321
|
public final func loadWebViewCustom() {
|
305
322
|
|
306
323
|
//let bridge = self.bridge
|