react-native-persona 2.32.1 → 2.32.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/RNPersonaInquiry2.podspec +1 -1
- package/android/build.gradle +13 -3
- package/android/src/main/java/com/withpersona/sdk2/reactnative/InlineInquiryWrapperFragment.kt +103 -0
- package/android/src/main/java/com/withpersona/sdk2/reactnative/InquiryEventEmitter.kt +25 -0
- package/android/src/main/java/com/withpersona/sdk2/reactnative/{InquiryEventEmitter.java → InquiryResultEmitter.java} +2 -2
- package/android/src/main/java/com/withpersona/sdk2/reactnative/InquiryUtils.java +26 -0
- package/android/src/main/java/com/withpersona/sdk2/reactnative/PersonaInquiryModule2.java +3 -23
- package/android/src/main/java/com/withpersona/sdk2/reactnative/PersonaInquiryViewManager.java +29 -7
- package/android/src/main/res/values/ids.xml +1 -0
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -3,6 +3,8 @@ def DEFAULT_MIN_SDK_VERSION = 21
|
|
|
3
3
|
def DEFAULT_TARGET_SDK_VERSION = 35
|
|
4
4
|
|
|
5
5
|
buildscript {
|
|
6
|
+
ext.kotlin_version = '2.1.21'
|
|
7
|
+
|
|
6
8
|
if (project == rootProject) {
|
|
7
9
|
repositories {
|
|
8
10
|
google()
|
|
@@ -11,11 +13,13 @@ buildscript {
|
|
|
11
13
|
|
|
12
14
|
dependencies {
|
|
13
15
|
classpath 'com.android.tools.build:gradle:8.1.1'
|
|
16
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
apply plugin: 'com.android.library'
|
|
22
|
+
apply plugin: 'kotlin-android'
|
|
19
23
|
|
|
20
24
|
def safeExtGet(prop, fallback) {
|
|
21
25
|
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
@@ -40,8 +44,11 @@ android {
|
|
|
40
44
|
disable 'GradleCompatible'
|
|
41
45
|
}
|
|
42
46
|
compileOptions {
|
|
43
|
-
sourceCompatibility JavaVersion.
|
|
44
|
-
targetCompatibility JavaVersion.
|
|
47
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
48
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
49
|
+
}
|
|
50
|
+
kotlinOptions {
|
|
51
|
+
jvmTarget = '17'
|
|
45
52
|
}
|
|
46
53
|
dexOptions {
|
|
47
54
|
preDexLibraries = false
|
|
@@ -65,6 +72,9 @@ dependencies {
|
|
|
65
72
|
implementation("com.facebook.react:react-android:+")
|
|
66
73
|
|
|
67
74
|
// NB: be sure to bump `nfc-impl` in example/android/app/build.gradle as well
|
|
68
|
-
implementation 'com.withpersona.sdk2:inquiry:2.32.
|
|
75
|
+
implementation 'com.withpersona.sdk2:inquiry:2.32.2'
|
|
69
76
|
implementation("androidx.fragment:fragment:1.8.6")
|
|
77
|
+
|
|
78
|
+
// Kotlin
|
|
79
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
70
80
|
}
|
package/android/src/main/java/com/withpersona/sdk2/reactnative/InlineInquiryWrapperFragment.kt
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
package com.withpersona.sdk2.reactnative
|
|
2
|
+
|
|
3
|
+
import android.os.Bundle
|
|
4
|
+
import android.view.LayoutInflater
|
|
5
|
+
import android.view.View
|
|
6
|
+
import android.view.ViewGroup
|
|
7
|
+
import android.widget.FrameLayout
|
|
8
|
+
import androidx.fragment.app.Fragment
|
|
9
|
+
import androidx.lifecycle.lifecycleScope
|
|
10
|
+
import com.withpersona.sdk2.inquiry.ExperimentalInlineApi
|
|
11
|
+
import com.withpersona.sdk2.inquiry.inline_inquiry.InlineInquiryController
|
|
12
|
+
import com.withpersona.sdk2.inquiry.inline_inquiry.InlineInquiryScreen
|
|
13
|
+
import com.withpersona.sdk2.inquiry.types.DEFAULT_REQUEST_KEY
|
|
14
|
+
import kotlinx.coroutines.launch
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Wrapper fragment that acts as a parent for [InquiryFragment] and implements
|
|
18
|
+
* [InlineInquiryController] to receive event callbacks from the child [InquiryFragment].
|
|
19
|
+
*/
|
|
20
|
+
@OptIn(ExperimentalInlineApi::class)
|
|
21
|
+
class InlineInquiryWrapperFragment : Fragment(), InlineInquiryController {
|
|
22
|
+
|
|
23
|
+
companion object {
|
|
24
|
+
private const val ARG_REQUEST_KEY = "pi2_rn_request_key"
|
|
25
|
+
|
|
26
|
+
const val ARG_EVENT = "pi2_rn_event"
|
|
27
|
+
|
|
28
|
+
fun newInstance(
|
|
29
|
+
requestKey: String,
|
|
30
|
+
inquiryFragment: Fragment,
|
|
31
|
+
): InlineInquiryWrapperFragment = InlineInquiryWrapperFragment().apply {
|
|
32
|
+
arguments = Bundle().apply {
|
|
33
|
+
putString(ARG_REQUEST_KEY, requestKey)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// This is a hack in order to let InlineInquiryWrapperFragment launch the InquiryFragment.
|
|
37
|
+
// This is very difficult to do without code changes to the SDK side. This hack should
|
|
38
|
+
// not cause any issues since the fragment should only need to be launched once.
|
|
39
|
+
// On kill/restore, the fragment state should be saved by the fragment manager.
|
|
40
|
+
this.inquiryFragment = inquiryFragment
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
private var inlineInquiryScreen: InlineInquiryScreen? = null
|
|
45
|
+
private var inquiryFragment: Fragment? = null
|
|
46
|
+
private var requestKey: String? = null
|
|
47
|
+
|
|
48
|
+
override fun onCreateView(
|
|
49
|
+
inflater: LayoutInflater,
|
|
50
|
+
container: ViewGroup?,
|
|
51
|
+
savedInstanceState: Bundle?
|
|
52
|
+
): View {
|
|
53
|
+
return FrameLayout(requireContext()).apply {
|
|
54
|
+
id = R.id.pi2_rn_wrapper_fragment_frame_layout
|
|
55
|
+
layoutParams = ViewGroup.LayoutParams(
|
|
56
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
57
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
63
|
+
super.onViewCreated(view, savedInstanceState)
|
|
64
|
+
|
|
65
|
+
requestKey = arguments?.getString(ARG_REQUEST_KEY)
|
|
66
|
+
|
|
67
|
+
childFragmentManager.setFragmentResultListener(DEFAULT_REQUEST_KEY, viewLifecycleOwner) { _, result ->
|
|
68
|
+
parentFragmentManager.setFragmentResult(DEFAULT_REQUEST_KEY, result)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Only add the fragment on first launch. On save/restore, the fragment manager should
|
|
72
|
+
// restore the fragment for us.
|
|
73
|
+
if (savedInstanceState == null) {
|
|
74
|
+
inquiryFragment?.let { fragment ->
|
|
75
|
+
childFragmentManager
|
|
76
|
+
.beginTransaction()
|
|
77
|
+
.add(R.id.pi2_rn_wrapper_fragment_frame_layout, fragment)
|
|
78
|
+
.commit()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
override fun onAttached(inlineInquiryScreen: InlineInquiryScreen) {
|
|
84
|
+
this.inlineInquiryScreen = inlineInquiryScreen
|
|
85
|
+
viewLifecycleOwner.lifecycleScope.launch {
|
|
86
|
+
inlineInquiryScreen.eventFlow.collect {
|
|
87
|
+
val requestKey = requestKey
|
|
88
|
+
if (requestKey != null) {
|
|
89
|
+
parentFragmentManager.setFragmentResult(
|
|
90
|
+
requestKey,
|
|
91
|
+
Bundle().apply {
|
|
92
|
+
putParcelable(ARG_EVENT, it)
|
|
93
|
+
}
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
override fun onDetached() {
|
|
101
|
+
inlineInquiryScreen = null
|
|
102
|
+
}
|
|
103
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
package com.withpersona.sdk2.reactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments.createMap
|
|
4
|
+
import com.facebook.react.bridge.ReactContext
|
|
5
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
6
|
+
import com.withpersona.sdk2.inquiry.ExperimentalInlineApi
|
|
7
|
+
import com.withpersona.sdk2.inquiry.inline_inquiry.InquiryEvent
|
|
8
|
+
|
|
9
|
+
class InquiryEventEmitter(
|
|
10
|
+
private val reactContext: ReactContext,
|
|
11
|
+
private val targetId: Int,
|
|
12
|
+
) {
|
|
13
|
+
|
|
14
|
+
@OptIn(ExperimentalInlineApi::class)
|
|
15
|
+
fun emitEvent(inquiryEvent: InquiryEvent) {
|
|
16
|
+
val map = InquiryUtils.inquiryEventToMap(inquiryEvent)
|
|
17
|
+
|
|
18
|
+
if (map != null) {
|
|
19
|
+
val params = createMap()
|
|
20
|
+
params.putMap("event", map)
|
|
21
|
+
reactContext.getJSModule<RCTEventEmitter?>(RCTEventEmitter::class.java)
|
|
22
|
+
.receiveEvent(targetId, "onEvent", params)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -18,10 +18,10 @@ import com.withpersona.sdk2.inquiry.InquiryResponse;
|
|
|
18
18
|
|
|
19
19
|
import java.util.Map;
|
|
20
20
|
|
|
21
|
-
public class
|
|
21
|
+
public class InquiryResultEmitter {
|
|
22
22
|
@NonNull private final ReactContext reactContext;
|
|
23
23
|
|
|
24
|
-
public
|
|
24
|
+
public InquiryResultEmitter(@NonNull ReactContext reactContext) {
|
|
25
25
|
this.reactContext = reactContext;
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.withpersona.sdk2.reactnative;
|
|
2
2
|
|
|
3
|
+
import androidx.annotation.NonNull;
|
|
3
4
|
import androidx.annotation.Nullable;
|
|
5
|
+
import androidx.annotation.OptIn;
|
|
4
6
|
|
|
5
7
|
import com.facebook.react.bridge.Arguments;
|
|
6
8
|
import com.facebook.react.bridge.ReadableArray;
|
|
@@ -9,12 +11,14 @@ import com.facebook.react.bridge.WritableArray;
|
|
|
9
11
|
import com.facebook.react.bridge.WritableMap;
|
|
10
12
|
import com.withpersona.sdk2.inquiry.ClientThemeSource;
|
|
11
13
|
import com.withpersona.sdk2.inquiry.Environment;
|
|
14
|
+
import com.withpersona.sdk2.inquiry.ExperimentalInlineApi;
|
|
12
15
|
import com.withpersona.sdk2.inquiry.Fields;
|
|
13
16
|
import com.withpersona.sdk2.inquiry.Inquiry;
|
|
14
17
|
import com.withpersona.sdk2.inquiry.InquiryBuilder;
|
|
15
18
|
import com.withpersona.sdk2.inquiry.InquiryTemplateBuilder;
|
|
16
19
|
import com.withpersona.sdk2.inquiry.ServerThemeSource;
|
|
17
20
|
import com.withpersona.sdk2.inquiry.StyleVariant;
|
|
21
|
+
import com.withpersona.sdk2.inquiry.inline_inquiry.InquiryEvent;
|
|
18
22
|
import com.withpersona.sdk2.inquiry.types.collected_data.CollectedData;
|
|
19
23
|
import com.withpersona.sdk2.inquiry.types.collected_data.DocumentFile;
|
|
20
24
|
import com.withpersona.sdk2.inquiry.types.collected_data.GovernmentIdCapture;
|
|
@@ -260,6 +264,28 @@ class InquiryUtils {
|
|
|
260
264
|
return collectedDataMap;
|
|
261
265
|
}
|
|
262
266
|
|
|
267
|
+
@OptIn(markerClass = ExperimentalInlineApi.class)
|
|
268
|
+
@Nullable
|
|
269
|
+
protected static ReadableMap inquiryEventToMap(@NonNull InquiryEvent inquiryEvent) {
|
|
270
|
+
WritableMap inquiryEventMap = Arguments.createMap();
|
|
271
|
+
|
|
272
|
+
if (inquiryEvent instanceof InquiryEvent.StartEvent) {
|
|
273
|
+
InquiryEvent.StartEvent start = (InquiryEvent.StartEvent) inquiryEvent;
|
|
274
|
+
inquiryEventMap.putString("type", "start");
|
|
275
|
+
inquiryEventMap.putString("inquiryId", start.getInquiryId());
|
|
276
|
+
inquiryEventMap.putString("sessionToken", start.getSessionToken());
|
|
277
|
+
} else if (inquiryEvent instanceof InquiryEvent.PageChange) {
|
|
278
|
+
InquiryEvent.PageChange pageChange = (InquiryEvent.PageChange) inquiryEvent;
|
|
279
|
+
inquiryEventMap.putString("type", "page_change");
|
|
280
|
+
inquiryEventMap.putString("name", pageChange.getName());
|
|
281
|
+
inquiryEventMap.putString("path", pageChange.getPath());
|
|
282
|
+
} else {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return inquiryEventMap;
|
|
287
|
+
}
|
|
288
|
+
|
|
263
289
|
private static Environment environmentFromString(@Nullable String environment) {
|
|
264
290
|
if (environment == null) {
|
|
265
291
|
return null;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
package com.withpersona.sdk2.reactnative;
|
|
2
2
|
|
|
3
|
+
import static com.withpersona.sdk2.reactnative.InquiryUtils.inquiryEventToMap;
|
|
4
|
+
|
|
3
5
|
import android.app.Activity;
|
|
4
6
|
import android.content.Intent;
|
|
5
7
|
|
|
@@ -60,7 +62,7 @@ public class PersonaInquiryModule2 extends ReactContextBaseJavaModule
|
|
|
60
62
|
if (requestCode == PERSONA_INQUIRY_REQUEST_CODE) {
|
|
61
63
|
InquiryResponse response = Inquiry.onActivityResult(data);
|
|
62
64
|
|
|
63
|
-
new
|
|
65
|
+
new InquiryResultEmitter(reactContext).emitResponse(response);
|
|
64
66
|
}
|
|
65
67
|
}
|
|
66
68
|
|
|
@@ -123,28 +125,6 @@ public class PersonaInquiryModule2 extends ReactContextBaseJavaModule
|
|
|
123
125
|
});
|
|
124
126
|
}
|
|
125
127
|
|
|
126
|
-
@OptIn(markerClass = ExperimentalInlineApi.class)
|
|
127
|
-
@Nullable
|
|
128
|
-
private ReadableMap inquiryEventToMap(@NonNull InquiryEvent inquiryEvent) {
|
|
129
|
-
WritableMap inquiryEventMap = Arguments.createMap();
|
|
130
|
-
|
|
131
|
-
if (inquiryEvent instanceof InquiryEvent.StartEvent) {
|
|
132
|
-
InquiryEvent.StartEvent start = (InquiryEvent.StartEvent) inquiryEvent;
|
|
133
|
-
inquiryEventMap.putString("type", "start");
|
|
134
|
-
inquiryEventMap.putString("inquiryId", start.getInquiryId());
|
|
135
|
-
inquiryEventMap.putString("sessionToken", start.getSessionToken());
|
|
136
|
-
} else if (inquiryEvent instanceof InquiryEvent.PageChange) {
|
|
137
|
-
InquiryEvent.PageChange pageChange = (InquiryEvent.PageChange) inquiryEvent;
|
|
138
|
-
inquiryEventMap.putString("type", "page_change");
|
|
139
|
-
inquiryEventMap.putString("name", pageChange.getName());
|
|
140
|
-
inquiryEventMap.putString("path", pageChange.getPath());
|
|
141
|
-
} else {
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return inquiryEventMap;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
128
|
@Nullable
|
|
149
129
|
private DeviceEventManagerModule.RCTDeviceEventEmitter getJsModule() {
|
|
150
130
|
try {
|
package/android/src/main/java/com/withpersona/sdk2/reactnative/PersonaInquiryViewManager.java
CHANGED
|
@@ -2,8 +2,8 @@ package com.withpersona.sdk2.reactnative;
|
|
|
2
2
|
|
|
3
3
|
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
|
4
4
|
import static com.withpersona.sdk2.inquiry.types.ConstsKt.DEFAULT_REQUEST_KEY;
|
|
5
|
+
import static com.withpersona.sdk2.reactnative.InlineInquiryWrapperFragment.ARG_EVENT;
|
|
5
6
|
|
|
6
|
-
import android.graphics.Color;
|
|
7
7
|
import android.view.Choreographer;
|
|
8
8
|
import android.view.View;
|
|
9
9
|
import android.view.ViewGroup;
|
|
@@ -14,7 +14,6 @@ import androidx.annotation.Nullable;
|
|
|
14
14
|
import androidx.fragment.app.Fragment;
|
|
15
15
|
import androidx.fragment.app.FragmentActivity;
|
|
16
16
|
|
|
17
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
18
17
|
import com.facebook.react.bridge.ReadableArray;
|
|
19
18
|
import com.facebook.react.bridge.ReadableMap;
|
|
20
19
|
import com.facebook.react.common.MapBuilder;
|
|
@@ -23,6 +22,7 @@ import com.facebook.react.uimanager.ViewGroupManager;
|
|
|
23
22
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
24
23
|
import com.withpersona.sdk2.inquiry.Inquiry;
|
|
25
24
|
import com.withpersona.sdk2.inquiry.InquiryResponse;
|
|
25
|
+
import com.withpersona.sdk2.inquiry.inline_inquiry.InquiryEvent;
|
|
26
26
|
|
|
27
27
|
import java.util.Map;
|
|
28
28
|
|
|
@@ -107,6 +107,12 @@ class PersonaInquiryViewManager extends ViewGroupManager<FrameLayout> {
|
|
|
107
107
|
"phasedRegistrationNames",
|
|
108
108
|
MapBuilder.of("bubbled", "onError")
|
|
109
109
|
)
|
|
110
|
+
).put(
|
|
111
|
+
"onEvent",
|
|
112
|
+
MapBuilder.of(
|
|
113
|
+
"phasedRegistrationNames",
|
|
114
|
+
MapBuilder.of("bubbled", "onEvent")
|
|
115
|
+
)
|
|
110
116
|
).build();
|
|
111
117
|
}
|
|
112
118
|
|
|
@@ -131,12 +137,12 @@ class PersonaInquiryViewManager extends ViewGroupManager<FrameLayout> {
|
|
|
131
137
|
return;
|
|
132
138
|
}
|
|
133
139
|
|
|
134
|
-
Fragment
|
|
140
|
+
Fragment inquiryFragment = inquiry
|
|
135
141
|
.buildInlineInquiry()
|
|
136
142
|
.build()
|
|
137
143
|
.createFragment();
|
|
138
144
|
|
|
139
|
-
if (
|
|
145
|
+
if (inquiryFragment == null) {
|
|
140
146
|
return;
|
|
141
147
|
}
|
|
142
148
|
|
|
@@ -146,15 +152,31 @@ class PersonaInquiryViewManager extends ViewGroupManager<FrameLayout> {
|
|
|
146
152
|
return;
|
|
147
153
|
}
|
|
148
154
|
|
|
155
|
+
final String requestKey = "pi2_rn_inquiry_" + reactNativeViewId;
|
|
156
|
+
InquiryEventEmitter inquiryEventEmitter = new InquiryEventEmitter(reactContext, root.getId());
|
|
157
|
+
|
|
149
158
|
activity.getSupportFragmentManager()
|
|
150
|
-
.setFragmentResultListener(DEFAULT_REQUEST_KEY, activity, (
|
|
159
|
+
.setFragmentResultListener(DEFAULT_REQUEST_KEY, activity, (reqKey, result) -> {
|
|
151
160
|
InquiryResponse response = Inquiry.extractInquiryResponseFromBundle(result, reactContext);
|
|
152
|
-
new
|
|
161
|
+
new InquiryResultEmitter(reactContext).emitResponse(response, root);
|
|
153
162
|
});
|
|
163
|
+
activity.getSupportFragmentManager()
|
|
164
|
+
.setFragmentResultListener(requestKey, activity, (reqKey, result) -> {
|
|
165
|
+
InquiryEvent event = result.getParcelable(ARG_EVENT);
|
|
166
|
+
|
|
167
|
+
if (event != null) {
|
|
168
|
+
inquiryEventEmitter.emitEvent(event);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
Fragment wrapperFragment = InlineInquiryWrapperFragment.Companion.newInstance(
|
|
173
|
+
requestKey,
|
|
174
|
+
inquiryFragment
|
|
175
|
+
);
|
|
154
176
|
|
|
155
177
|
activity.getSupportFragmentManager()
|
|
156
178
|
.beginTransaction()
|
|
157
|
-
.replace(reactNativeViewId,
|
|
179
|
+
.replace(reactNativeViewId, wrapperFragment, String.valueOf(reactNativeViewId))
|
|
158
180
|
.commit();
|
|
159
181
|
parentView.requestLayout();
|
|
160
182
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-persona",
|
|
3
3
|
"title": "React Native Persona",
|
|
4
|
-
"version": "2.32.
|
|
4
|
+
"version": "2.32.2",
|
|
5
5
|
"description": "Launch a mobile native implementation of the Persona inquiry flow from React Native.",
|
|
6
6
|
"homepage": "https://docs.withpersona.com/docs/react-native-sdk-integration",
|
|
7
7
|
"bugs": "https://github.com/persona-id/persona-inquiry-sdk-public",
|