@finos_sdk/sdk-ekyc 1.5.0 → 1.5.1
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.
|
@@ -66,7 +66,10 @@ import java.io.FileInputStream
|
|
|
66
66
|
import java.io.InputStream
|
|
67
67
|
import java.util.Date
|
|
68
68
|
import android.app.Activity
|
|
69
|
+
import android.app.Application
|
|
70
|
+
import android.os.Bundle
|
|
69
71
|
import android.view.ViewGroup
|
|
72
|
+
import java.lang.ref.WeakReference
|
|
70
73
|
|
|
71
74
|
@ReactModule(name = EKYCModule.NAME)
|
|
72
75
|
class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
@@ -74,10 +77,71 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
74
77
|
companion object {
|
|
75
78
|
const val NAME = "EKYCModule"
|
|
76
79
|
private const val TAG = "EKYCModule"
|
|
80
|
+
|
|
81
|
+
// Full class name của SDK activity duy nhất
|
|
82
|
+
private const val SDK_EKYC_ACTIVITY = "finos.sdk.ekyc.sdkui.SDKeKYCActivity"
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
override fun getName(): String = NAME
|
|
80
86
|
|
|
87
|
+
/**
|
|
88
|
+
* WeakReference tới SDK activity đang foreground.
|
|
89
|
+
* Được set/clear bởi ActivityLifecycleCallbacks khi SDK activity resume/pause.
|
|
90
|
+
* @Volatile: viết từ UI thread (lifecycle callback), đọc từ JS bridge thread (showRNExitSheet).
|
|
91
|
+
* WeakReference để tránh memory leak nếu activity bị destroy mà chưa clear.
|
|
92
|
+
*/
|
|
93
|
+
@Volatile
|
|
94
|
+
private var activeSdkActivity: WeakReference<Activity>? = null
|
|
95
|
+
|
|
96
|
+
private val sdkActivityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
|
|
97
|
+
override fun onActivityResumed(activity: Activity) {
|
|
98
|
+
if (isSDKActivity(activity)) {
|
|
99
|
+
activeSdkActivity = WeakReference(activity)
|
|
100
|
+
Log.d(TAG, "📌 SDK Activity resumed: ${activity.javaClass.simpleName}")
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
override fun onActivityPaused(activity: Activity) {
|
|
104
|
+
if (activeSdkActivity?.get() == activity) {
|
|
105
|
+
activeSdkActivity = null
|
|
106
|
+
Log.d(TAG, "📌 SDK Activity paused: ${activity.javaClass.simpleName}")
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
override fun onActivityDestroyed(activity: Activity) {
|
|
110
|
+
if (activeSdkActivity?.get() == activity) {
|
|
111
|
+
activeSdkActivity = null
|
|
112
|
+
Log.d(TAG, "📌 SDK Activity destroyed: ${activity.javaClass.simpleName}")
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
|
|
116
|
+
override fun onActivityStarted(activity: Activity) {}
|
|
117
|
+
override fun onActivityStopped(activity: Activity) {}
|
|
118
|
+
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private fun isSDKActivity(activity: Activity): Boolean {
|
|
122
|
+
return activity.javaClass.name == SDK_EKYC_ACTIVITY
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
init {
|
|
126
|
+
// Đăng ký lifecycle callback để track SDK activity tự động
|
|
127
|
+
val app = reactContext.applicationContext as? Application
|
|
128
|
+
app?.registerActivityLifecycleCallbacks(sdkActivityLifecycleCallbacks)
|
|
129
|
+
?: Log.w(TAG, "⚠️ Could not register ActivityLifecycleCallbacks")
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Lấy SDK activity đang active, fallback về getTrueCurrentActivity() nếu không có.
|
|
134
|
+
*/
|
|
135
|
+
private fun getSDKActivity(): Activity? {
|
|
136
|
+
val sdk = activeSdkActivity?.get()
|
|
137
|
+
if (sdk != null && !sdk.isFinishing && !sdk.isDestroyed) {
|
|
138
|
+
Log.d(TAG, "✅ Using tracked SDK Activity: ${sdk.javaClass.simpleName}")
|
|
139
|
+
return sdk
|
|
140
|
+
}
|
|
141
|
+
Log.d(TAG, "⚠️ No active SDK activity tracked, falling back to getTrueCurrentActivity")
|
|
142
|
+
return getTrueCurrentActivity()
|
|
143
|
+
}
|
|
144
|
+
|
|
81
145
|
/**
|
|
82
146
|
* Reference tới BottomSheetDialog hiện đang hiển thị.
|
|
83
147
|
* @Volatile: resolveExit() chạy trên JS bridge thread, đọc field này được viết bởi UI thread.
|
|
@@ -199,9 +263,8 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
199
263
|
|
|
200
264
|
@ReactMethod
|
|
201
265
|
fun showRNExitSheet(bundleName: String, initialProps: ReadableMap, promise: Promise) {
|
|
202
|
-
// Fix: Move activity detection to UI thread to avoid race conditions and ensure correct window attachment
|
|
203
266
|
Handler(Looper.getMainLooper()).post {
|
|
204
|
-
val activity =
|
|
267
|
+
val activity = getSDKActivity() ?: run {
|
|
205
268
|
Log.e(TAG, "❌ showRNExitSheet failed: No visible activity found")
|
|
206
269
|
promise.reject("NO_ACTIVITY", "No visible activity found")
|
|
207
270
|
return@post
|
|
@@ -2733,6 +2796,10 @@ class EKYCModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
2733
2796
|
override fun onCatalystInstanceDestroy() {
|
|
2734
2797
|
super.onCatalystInstanceDestroy()
|
|
2735
2798
|
SDKeKYCExitHandlerManager.uiListener = null
|
|
2799
|
+
// Unregister lifecycle callback để tránh memory leak
|
|
2800
|
+
val app = reactApplicationContext.applicationContext as? Application
|
|
2801
|
+
app?.unregisterActivityLifecycleCallbacks(sdkActivityLifecycleCallbacks)
|
|
2802
|
+
activeSdkActivity = null
|
|
2736
2803
|
// Dismiss sheet nếu vẫn đang hiển thị khi RN catalyst instance destroy
|
|
2737
2804
|
val sheet = currentExitSheet
|
|
2738
2805
|
currentExitSheet = null
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finos_sdk/sdk-ekyc",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "React Native SDK for eKYC - Vietnamese CCCD NFC reading, OCR, Liveness detection, Face matching, and C06, eSign, SmsOTP residence verification",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -5,7 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const react_1 = __importDefault(require("react"));
|
|
7
7
|
const react_native_1 = require("react-native");
|
|
8
|
-
|
|
8
|
+
// Dùng NativeModules trực tiếp để tránh circular dependency với FinosEKYCModule
|
|
9
|
+
// (ExitConfirmSheet được load qua ExitSheetWrapper được import bởi FinosEKYCModule)
|
|
9
10
|
const BellIcon = () => (<react_native_1.View style={styles.bellWrapper}>
|
|
10
11
|
<react_native_1.View style={styles.bellMount}/>
|
|
11
12
|
<react_native_1.View style={styles.bellBody}/>
|
|
@@ -17,10 +18,12 @@ const ExitConfirmSheet = (props) => {
|
|
|
17
18
|
const confirmText = props.confirmText || 'Đồng ý';
|
|
18
19
|
const cancelText = props.cancelText || 'Ở lại';
|
|
19
20
|
const handleConfirm = async () => {
|
|
20
|
-
|
|
21
|
+
var _a, _b;
|
|
22
|
+
await ((_b = (_a = react_native_1.NativeModules.EKYCModule) === null || _a === void 0 ? void 0 : _a.resolveExit) === null || _b === void 0 ? void 0 : _b.call(_a, 'CONFIRM'));
|
|
21
23
|
};
|
|
22
24
|
const handleCancel = async () => {
|
|
23
|
-
|
|
25
|
+
var _a, _b;
|
|
26
|
+
await ((_b = (_a = react_native_1.NativeModules.EKYCModule) === null || _a === void 0 ? void 0 : _a.resolveExit) === null || _b === void 0 ? void 0 : _b.call(_a, 'CANCEL'));
|
|
24
27
|
};
|
|
25
28
|
return (<react_native_1.View style={styles.container} onLayout={(e) => {
|
|
26
29
|
var _a, _b;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@finos_sdk/sdk-ekyc",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "React Native SDK for eKYC - Vietnamese CCCD NFC reading, OCR, Liveness detection, Face matching, and C06, eSign, SmsOTP residence verification",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
TouchableOpacity,
|
|
7
7
|
NativeModules,
|
|
8
8
|
} from 'react-native';
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
// Dùng NativeModules trực tiếp để tránh circular dependency với FinosEKYCModule
|
|
11
|
+
// (ExitConfirmSheet được load qua ExitSheetWrapper được import bởi FinosEKYCModule)
|
|
10
12
|
|
|
11
13
|
const BellIcon = () => (
|
|
12
14
|
<View style={styles.bellWrapper}>
|
|
@@ -23,11 +25,11 @@ const ExitConfirmSheet = (props: any) => {
|
|
|
23
25
|
const cancelText = props.cancelText || 'Ở lại';
|
|
24
26
|
|
|
25
27
|
const handleConfirm = async () => {
|
|
26
|
-
await
|
|
28
|
+
await NativeModules.EKYCModule?.resolveExit?.('CONFIRM');
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
const handleCancel = async () => {
|
|
30
|
-
await
|
|
32
|
+
await NativeModules.EKYCModule?.resolveExit?.('CANCEL');
|
|
31
33
|
};
|
|
32
34
|
|
|
33
35
|
return (
|