react-native-persona 2.25.2 → 2.26.0

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.
Files changed (54) hide show
  1. package/RNPersonaInquiry2.podspec +1 -1
  2. package/android/build.gradle +3 -2
  3. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  4. package/android/gradle/wrapper/gradle-wrapper.properties +3 -1
  5. package/android/gradlew +174 -108
  6. package/android/gradlew.bat +12 -23
  7. package/android/src/main/java/com/withpersona/sdk2/reactnative/InquiryEventEmitter.java +110 -0
  8. package/android/src/main/java/com/withpersona/sdk2/reactnative/InquiryUtils.java +301 -0
  9. package/android/src/main/java/com/withpersona/sdk2/reactnative/PersonaInquiryModule2.java +12 -353
  10. package/android/src/main/java/com/withpersona/sdk2/reactnative/PersonaInquiryPackage2.java +7 -5
  11. package/android/src/main/java/com/withpersona/sdk2/reactnative/PersonaInquiryViewManager.java +190 -0
  12. package/android/src/main/res/values/ids.xml +4 -0
  13. package/ios/PersonaInquiry-Bridging-Header.h +2 -0
  14. package/ios/PersonaInquiry.xcodeproj/project.pbxproj +4 -0
  15. package/ios/PersonaInquiry2.swift +25 -23
  16. package/ios/PersonaInquiryBridge.m +13 -0
  17. package/ios/PersonaInquiryViewManager.swift +248 -0
  18. package/lib/commonjs/PersonaInquiryView.js +69 -0
  19. package/lib/commonjs/PersonaInquiryView.js.map +1 -0
  20. package/lib/commonjs/PersonaInquiryViewManager.js +10 -0
  21. package/lib/commonjs/PersonaInquiryViewManager.js.map +1 -0
  22. package/lib/commonjs/StepData.js +66 -0
  23. package/lib/commonjs/StepData.js.map +1 -0
  24. package/lib/commonjs/callbacks.js +6 -0
  25. package/lib/commonjs/callbacks.js.map +1 -0
  26. package/lib/commonjs/index.js +115 -143
  27. package/lib/commonjs/index.js.map +1 -1
  28. package/lib/commonjs/util.js +71 -0
  29. package/lib/commonjs/util.js.map +1 -1
  30. package/lib/module/PersonaInquiryView.js +60 -0
  31. package/lib/module/PersonaInquiryView.js.map +1 -0
  32. package/lib/module/PersonaInquiryViewManager.js +5 -0
  33. package/lib/module/PersonaInquiryViewManager.js.map +1 -0
  34. package/lib/module/StepData.js +56 -0
  35. package/lib/module/StepData.js.map +1 -0
  36. package/lib/module/callbacks.js +2 -0
  37. package/lib/module/callbacks.js.map +1 -0
  38. package/lib/module/index.js +38 -142
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/util.js +67 -0
  41. package/lib/module/util.js.map +1 -1
  42. package/lib/typescript/PersonaInquiryView.d.ts +11 -0
  43. package/lib/typescript/PersonaInquiryViewManager.d.ts +1 -0
  44. package/lib/typescript/StepData.d.ts +56 -0
  45. package/lib/typescript/callbacks.d.ts +21 -0
  46. package/lib/typescript/index.d.ts +26 -68
  47. package/lib/typescript/util.d.ts +17 -0
  48. package/package.json +1 -1
  49. package/src/PersonaInquiryView.tsx +109 -0
  50. package/src/PersonaInquiryViewManager.ts +5 -0
  51. package/src/StepData.ts +83 -0
  52. package/src/callbacks.ts +37 -0
  53. package/src/index.ts +98 -221
  54. package/src/util.ts +111 -0
@@ -12,54 +12,23 @@ import com.facebook.react.bridge.Arguments;
12
12
  import com.facebook.react.bridge.ReactApplicationContext;
13
13
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
14
14
  import com.facebook.react.bridge.ReactMethod;
15
- import com.facebook.react.bridge.ReadableArray;
16
15
  import com.facebook.react.bridge.ReadableMap;
17
- import com.facebook.react.bridge.WritableArray;
18
16
  import com.facebook.react.bridge.WritableMap;
19
17
  import com.facebook.react.modules.core.DeviceEventManagerModule;
20
- import com.withpersona.sdk2.reactnative.R;
21
- import com.withpersona.sdk2.inquiry.ClientThemeSource;
22
- import com.withpersona.sdk2.inquiry.Environment;
23
18
  import com.withpersona.sdk2.inquiry.ExperimentalInlineApi;
24
19
  import com.withpersona.sdk2.inquiry.ExperimentalInquiryApi;
25
- import com.withpersona.sdk2.inquiry.Fields;
26
20
  import com.withpersona.sdk2.inquiry.Inquiry;
27
- import com.withpersona.sdk2.inquiry.InquiryBuilder;
28
- import com.withpersona.sdk2.inquiry.InquiryField;
29
21
  import com.withpersona.sdk2.inquiry.InquiryResponse;
30
- import com.withpersona.sdk2.inquiry.InquiryTemplateBuilder;
31
22
  import com.withpersona.sdk2.inquiry.OnInquiryEventListener;
32
- import com.withpersona.sdk2.inquiry.ServerThemeSource;
33
23
  import com.withpersona.sdk2.inquiry.inline_inquiry.InquiryEvent;
34
- import com.withpersona.sdk2.inquiry.types.collected_data.CollectedData;
35
- import com.withpersona.sdk2.inquiry.types.collected_data.DocumentFile;
36
- import com.withpersona.sdk2.inquiry.types.collected_data.GovernmentIdCapture;
37
- import com.withpersona.sdk2.inquiry.types.collected_data.SelfieCapture;
38
- import com.withpersona.sdk2.inquiry.types.collected_data.StepData;
39
24
 
40
25
  import java.util.HashMap;
41
- import java.util.List;
42
26
  import java.util.Map;
43
- import java.util.Objects;
44
27
 
45
28
  public class PersonaInquiryModule2 extends ReactContextBaseJavaModule
46
29
  implements ActivityEventListener {
47
30
 
48
31
  private static final int PERSONA_INQUIRY_REQUEST_CODE = 31416;
49
- private static final String INQUIRY_ID = "inquiryId";
50
- private static final String TEMPLATE_ID = "templateId";
51
- private static final String TEMPLATE_VERSION = "templateVersion";
52
- private static final String ACCOUNT_ID = "accountId";
53
- private static final String REFERENCE_ID = "referenceId";
54
- private static final String ACCESS_TOKEN = "sessionToken";
55
- private static final String ENVIRONMENT = "environment";
56
- private static final String ENVIRONMENT_ID = "environmentId";
57
- private static final String FIELDS = "fields";
58
- private static final String FIELD_ADDITIONAL_FIELDS = "additionalFields";
59
- private static final String RETURN_COLLECTED_DATA = "returnCollectedData";
60
- private static final String THEME_SOURCE = "themeSource";
61
- private static final String THEME_SET_ID = "themeSetId";
62
- private static final String LOCALE = "locale";
63
32
  private static final String DISABLE_PRESENTATION_ANIMATION = "disablePresentationAnimation";
64
33
 
65
34
  private boolean disablePresentationAnimation = false;
@@ -74,214 +43,25 @@ public class PersonaInquiryModule2 extends ReactContextBaseJavaModule
74
43
  }
75
44
 
76
45
  @Override
77
- public void onNewIntent(Intent intent) {
46
+ public void onNewIntent(@NonNull Intent intent) {
78
47
  // Do nothing
79
48
  }
80
49
 
81
50
  @Override
82
51
  public void onActivityResult(
83
- final Activity activity,
84
- final int requestCode,
85
- final int resultCode,
86
- @Nullable Intent data) {
52
+ @NonNull final Activity activity,
53
+ final int requestCode,
54
+ final int resultCode,
55
+ @Nullable Intent data) {
87
56
  if (this.disablePresentationAnimation) {
88
57
  getCurrentActivity().overridePendingTransition(0, 0);
89
58
  }
90
59
 
91
60
  if (requestCode == PERSONA_INQUIRY_REQUEST_CODE) {
92
61
  InquiryResponse response = Inquiry.onActivityResult(data);
93
- DeviceEventManagerModule.RCTDeviceEventEmitter jsModule =
94
- this.reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
95
62
 
96
- if (response instanceof InquiryResponse.Complete) {
97
- InquiryResponse.Complete complete = ((InquiryResponse.Complete) response);
98
-
99
- // Build event params
100
- WritableMap params = Arguments.createMap();
101
- params.putString("inquiryId", complete.getInquiryId());
102
- params.putString("status", complete.getStatus());
103
-
104
- WritableMap fields = Arguments.createMap();
105
- Map<String, InquiryField> rawFields = complete.getFields();
106
- for (String fieldName : rawFields.keySet()) {
107
- InquiryField rawField = rawFields.get(fieldName);
108
- if (rawField instanceof InquiryField.StringField) {
109
- fields.putMap(fieldName,
110
- wrapField("string", ((InquiryField.StringField) rawField).getValue()));
111
- } else if (rawField instanceof InquiryField.IntegerField) {
112
- Integer value = ((InquiryField.IntegerField) rawField).getValue();
113
- fields.putMap(fieldName,
114
- wrapField("integer", (value == null) ? null : value.toString()));
115
- } else if (rawField instanceof InquiryField.BooleanField) {
116
- Boolean value = ((InquiryField.BooleanField) rawField).getValue();
117
- fields.putMap(fieldName,
118
- wrapField("boolean", (value == null) ? null : value.toString()));
119
- } else if (rawField instanceof InquiryField.UnknownField) {
120
- String type = ((InquiryField.UnknownField) rawField).getType();
121
- fields.putMap(fieldName, wrapField("unknown", type));
122
- } else {
123
- fields.putMap(fieldName, wrapField("unknown", null));
124
- }
125
- }
126
- params.putMap("fields", fields);
127
-
128
- params.putMap("collectedData", collectedDataToMap(complete.getCollectedData()));
129
-
130
- jsModule.emit("onComplete", params);
131
- } else if (response instanceof InquiryResponse.Cancel) {
132
- InquiryResponse.Cancel cancel = (InquiryResponse.Cancel) response;
133
-
134
- // Build event params
135
- WritableMap params = Arguments.createMap();
136
- params.putString("inquiryId", cancel.getInquiryId());
137
- params.putString("sessionToken", cancel.getSessionToken());
138
- jsModule.emit("onCanceled", params);
139
- } else if (response instanceof InquiryResponse.Error) {
140
- InquiryResponse.Error error = (InquiryResponse.Error) response;
141
-
142
- WritableMap params = Arguments.createMap();
143
- params.putString("debugMessage", error.getDebugMessage());
144
- params.putString("errorCode", error.getErrorCode().name());
145
- jsModule.emit("onError", params);
146
- }
147
- }
148
- }
149
-
150
- @Nullable
151
- private ReadableMap collectedDataToMap(@Nullable CollectedData collectedData) {
152
- if (collectedData == null) {
153
- return null;
154
- }
155
-
156
- WritableMap collectedDataMap = Arguments.createMap();
157
-
158
- WritableArray stepDataMap = Arguments.createArray();
159
- for (StepData stepDatum : collectedData.getStepData()) {
160
- WritableMap stepDatumMap = Arguments.createMap();
161
- stepDatumMap.putString("stepName", stepDatum.getStepName());
162
-
163
- if (stepDatum instanceof StepData.DocumentStepData) {
164
- WritableArray documentsArr = Arguments.createArray();
165
-
166
- for (DocumentFile document : ((StepData.DocumentStepData) stepDatum).getDocuments()) {
167
- WritableMap documentMap = Arguments.createMap();
168
- documentMap.putString("absoluteFilePath", document.getData().getAbsolutePath());
169
- documentsArr.pushMap(documentMap);
170
- }
171
-
172
- stepDatumMap.putArray("documents", documentsArr);
173
- stepDatumMap.putString("type", "DocumentStepData");
174
- } else if (stepDatum instanceof StepData.GovernmentIdStepData) {
175
- WritableArray capturesArr = Arguments.createArray();
176
-
177
- for (GovernmentIdCapture capture : ((StepData.GovernmentIdStepData) stepDatum).getCaptures()) {
178
- WritableMap captureMap = Arguments.createMap();
179
- captureMap.putString("idClass", capture.getIdClass());
180
- captureMap.putString("captureMethod", capture.getCaptureMethod().name());
181
- captureMap.putString("side", capture.getSide().name());
182
-
183
- WritableArray framesArr = Arguments.createArray();
184
- for (GovernmentIdCapture.Frame frame : capture.getFrames()) {
185
- WritableMap frameMap = Arguments.createMap();
186
- frameMap.putString("absoluteFilePath", frame.getData().getAbsolutePath());
187
-
188
- framesArr.pushMap(frameMap);
189
- }
190
- captureMap.putArray("frames", framesArr);
191
-
192
- capturesArr.pushMap(captureMap);
193
- }
194
-
195
- stepDatumMap.putArray("captures", capturesArr);
196
- stepDatumMap.putString("type", "GovernmentIdStepData");
197
- } else if (stepDatum instanceof StepData.SelfieStepData) {
198
- StepData.SelfieStepData selfieStepData = (StepData.SelfieStepData) stepDatum;
199
- ReadableMap centerCaptureMap = selfieCaptureToMap(selfieStepData.getCenterCapture());
200
- ReadableMap leftCaptureMap = selfieCaptureToMap(selfieStepData.getLeftCapture());
201
- ReadableMap rightCaptureMap = selfieCaptureToMap(selfieStepData.getRightCapture());
202
-
203
- stepDatumMap.putMap("centerCapture", centerCaptureMap);
204
- stepDatumMap.putMap("leftCapture", leftCaptureMap);
205
- stepDatumMap.putMap("rightCapture", rightCaptureMap);
206
- stepDatumMap.putString("type", "SelfieStepData");
207
- } else if (stepDatum instanceof StepData.UiStepData) {
208
- Map<String, Object> componentParams = ((StepData.UiStepData) stepDatum).getComponentParams();
209
-
210
- stepDatumMap.putMap("componentParams", uiStepParamsMapToMap(componentParams));
211
- stepDatumMap.putString("type", "UiStepData");
212
- } else {
213
- // do nothing
214
- }
215
-
216
- stepDataMap.pushMap(stepDatumMap);
63
+ new InquiryEventEmitter(reactContext).emitResponse(response);
217
64
  }
218
-
219
- collectedDataMap.putArray("stepData", stepDataMap);
220
-
221
- return collectedDataMap;
222
- }
223
-
224
- private ReadableMap uiStepParamsMapToMap(Map<?, ?> map) {
225
- WritableMap resultMap = Arguments.createMap();
226
- for (Map.Entry<?, ?> param : map.entrySet()) {
227
- Object key = param.getKey();
228
- Object value = param.getValue();
229
-
230
- if (!(key instanceof String)) {
231
- continue; // All ui step params should have string keys.
232
- }
233
-
234
- String keyStr = (String) key;
235
-
236
- if (value instanceof Map<?, ?>) {
237
- resultMap.putMap(keyStr, uiStepParamsMapToMap((Map<?, ?>) value));
238
- } else if (value instanceof List<?>) {
239
- resultMap.putArray(keyStr, uiStepParamsArrToArr((List<?>) value));
240
- } else if (value instanceof String) {
241
- resultMap.putString(keyStr, (String) value);
242
- } else if (value instanceof Boolean) {
243
- resultMap.putBoolean(keyStr, (Boolean) value);
244
- } else if (value instanceof Number) {
245
- resultMap.putDouble(keyStr, (Double) value);
246
- }
247
- }
248
-
249
- return resultMap;
250
- }
251
-
252
- private ReadableArray uiStepParamsArrToArr(List<?> arr) {
253
- WritableArray resultArr = Arguments.createArray();
254
-
255
- for (Object element : arr) {
256
- if (element instanceof String) {
257
- resultArr.pushString((String) element);
258
- } else if (element instanceof Boolean) {
259
- resultArr.pushBoolean((Boolean) element);
260
- } else if (element instanceof Number) {
261
- resultArr.pushDouble((Double) element);
262
- }
263
- }
264
-
265
- return resultArr;
266
- }
267
-
268
- private ReadableMap selfieCaptureToMap(@Nullable SelfieCapture selfieCapture) {
269
- if (selfieCapture == null) {
270
- return null;
271
- }
272
-
273
- WritableMap captureMap = Arguments.createMap();
274
- captureMap.putString("captureMethod", selfieCapture.getCaptureMethod().name());
275
- captureMap.putString("absoluteFilePath", selfieCapture.getData().getAbsolutePath());
276
- return captureMap;
277
- }
278
-
279
-
280
- private static ReadableMap wrapField(String type, String value) {
281
- WritableMap map = Arguments.createMap();
282
- map.putString("type", type);
283
- map.putString("value", value);
284
- return map;
285
65
  }
286
66
 
287
67
  @NonNull
@@ -296,124 +76,19 @@ public class PersonaInquiryModule2 extends ReactContextBaseJavaModule
296
76
  * the React Native bridge.
297
77
  */
298
78
  @ReactMethod
299
- @SuppressWarnings("unchecked")
79
+ @SuppressWarnings("unused") // react uses this
300
80
  public void startInquiry(
301
81
  ReadableMap options
302
82
  ) {
303
83
  Activity currentActivity = reactContext.getCurrentActivity();
304
-
305
- String inquiryId = options.hasKey(INQUIRY_ID) ? options.getString(INQUIRY_ID) : null;
306
- String templateId = options.hasKey(TEMPLATE_ID) ? options.getString(TEMPLATE_ID) : null;
307
- String templateVersion = options.hasKey(TEMPLATE_VERSION) ? options.getString(TEMPLATE_VERSION) : null;
84
+ Inquiry inquiry = InquiryUtils.newInquiryFromMap(options);
308
85
 
309
86
  this.disablePresentationAnimation = options.hasKey(DISABLE_PRESENTATION_ANIMATION) ? options.getBoolean(DISABLE_PRESENTATION_ANIMATION) : false;
310
87
 
311
- if (inquiryId != null) {
312
- InquiryBuilder builder = Inquiry.fromInquiry(inquiryId);
313
-
314
- String themeSource = options.hasKey(THEME_SOURCE) ? options.getString(THEME_SOURCE) : null;
315
- builder = builder.theme(themeSource != null && themeSource.equals("server") ?
316
- new ServerThemeSource(R.style.Persona_Inquiry2_Theme) : new ClientThemeSource(R.style.Persona_Inquiry2_Theme));
317
-
318
- String sessionToken = options.hasKey(ACCESS_TOKEN) ? options.getString(ACCESS_TOKEN) : null;
319
- if (sessionToken != null) {
320
- builder = builder.sessionToken(sessionToken);
321
- }
322
-
323
- String locale = options.hasKey(LOCALE) ? options.getString(LOCALE) : null;
324
- if (locale != null) {
325
- builder = builder.locale(locale);
326
- }
327
-
328
- if (currentActivity != null) {
329
- builder.build().start(currentActivity, PERSONA_INQUIRY_REQUEST_CODE);
330
- if (this.disablePresentationAnimation) {
331
- currentActivity.overridePendingTransition(0, 0);
332
- }
333
- }
334
- }
335
-
336
- if (templateId != null || templateVersion != null) {
337
- InquiryTemplateBuilder builder;
338
- if (templateId != null) {
339
- builder = Inquiry.fromTemplate(templateId);
340
- } else {
341
- builder = Inquiry.fromTemplateVersion(templateVersion);
342
- }
343
-
344
- String themeSource = options.hasKey(THEME_SOURCE) ? options.getString(THEME_SOURCE) : null;
345
- builder = builder.theme(themeSource != null && themeSource.equals("server") ?
346
- new ServerThemeSource(R.style.Persona_Inquiry2_Theme) : new ClientThemeSource(R.style.Persona_Inquiry2_Theme));
347
-
348
- String referenceId = options.hasKey(REFERENCE_ID) ? options.getString(REFERENCE_ID) : null;
349
- if (referenceId != null) {
350
- builder = builder.referenceId(referenceId);
351
- }
352
-
353
- String accountId = options.hasKey(ACCOUNT_ID) ? options.getString(ACCOUNT_ID) : null;
354
- if (accountId != null) {
355
- builder = builder.accountId(accountId);
356
- }
357
-
358
- Environment environment = environmentFromString(
359
- options.hasKey(ENVIRONMENT) ? options.getString(ENVIRONMENT) : null
360
- );
361
- if (environment != null) {
362
- builder = builder.environment(environment);
363
- }
364
-
365
- String environmentId = options.hasKey(ENVIRONMENT_ID) ? options.getString(ENVIRONMENT_ID) : null;
366
- if (environmentId != null) {
367
- builder = builder.environmentId(environmentId);
368
- }
369
-
370
- String themeSetId = options.hasKey(THEME_SET_ID) ? options.getString(THEME_SET_ID) : null;
371
- if (themeSetId != null) {
372
- builder = builder.themeSetId(themeSetId);
373
- }
374
-
375
- String locale = options.hasKey(LOCALE) ? options.getString(LOCALE) : null;
376
- if (locale != null) {
377
- builder = builder.locale(locale);
378
- }
379
-
380
- ReadableMap fields = options.hasKey(FIELDS) ? options.getMap(FIELDS) : null;
381
-
382
- if (fields != null) {
383
- Fields.Builder fieldsBuilder = new Fields.Builder();
384
-
385
- for (HashMap.Entry<String, Object> entry : fields.toHashMap().entrySet()) {
386
- String key = entry.getKey();
387
- Map<String, Object> wrappedValue = (Map<String, Object>) entry.getValue();
388
- String type = (String) wrappedValue.get("type");
389
- Object value = wrappedValue.get("value");
390
-
391
- if (value == null) {
392
- continue;
393
- }
394
-
395
- if (Objects.equals(type, "string")) {
396
- fieldsBuilder.field(key, (String) value);
397
- } else if (Objects.equals(type, "integer")) {
398
- fieldsBuilder.field(key, ((Double) value).intValue());
399
- } else if (Objects.equals(type, "boolean")) {
400
- fieldsBuilder.field(key, (Boolean) value);
401
- }
402
- }
403
-
404
- builder = builder.fields(fieldsBuilder.build());
405
- }
406
-
407
- Boolean returnCollectedData = options.hasKey(RETURN_COLLECTED_DATA) ? options.getBoolean(RETURN_COLLECTED_DATA) : null;
408
- if (returnCollectedData != null) {
409
- builder = builder.returnCollectedData(returnCollectedData);
410
- }
411
-
412
- if (currentActivity != null) {
413
- builder.build().start(currentActivity, PERSONA_INQUIRY_REQUEST_CODE);
414
- if (this.disablePresentationAnimation) {
415
- currentActivity.overridePendingTransition(0, 0);
416
- }
88
+ if (currentActivity != null && inquiry != null) {
89
+ inquiry.start(currentActivity, PERSONA_INQUIRY_REQUEST_CODE);
90
+ if (this.disablePresentationAnimation) {
91
+ currentActivity.overridePendingTransition(0, 0);
417
92
  }
418
93
  }
419
94
  }
@@ -425,22 +100,6 @@ public class PersonaInquiryModule2 extends ReactContextBaseJavaModule
425
100
  return constants;
426
101
  }
427
102
 
428
- private Environment environmentFromString(@Nullable String environment) {
429
- if (environment == null) {
430
- return null;
431
- }
432
-
433
- switch (environment) {
434
- case "production":
435
- return Environment.PRODUCTION;
436
- case "sandbox":
437
- return Environment.SANDBOX;
438
- default:
439
- return null;
440
- }
441
- }
442
-
443
-
444
103
  @OptIn(markerClass = ExperimentalInquiryApi.class)
445
104
  private void registerOnInquiryEventListener() {
446
105
  Inquiry.Companion.setOnEventListener(new OnInquiryEventListener() {
@@ -1,14 +1,14 @@
1
1
  package com.withpersona.sdk2.reactnative;
2
2
 
3
- import java.util.Arrays;
4
- import java.util.Collections;
5
- import java.util.List;
6
-
7
3
  import com.facebook.react.ReactPackage;
8
4
  import com.facebook.react.bridge.NativeModule;
9
5
  import com.facebook.react.bridge.ReactApplicationContext;
10
6
  import com.facebook.react.uimanager.ViewManager;
11
7
 
8
+ import java.util.Arrays;
9
+ import java.util.List;
10
+
11
+ @SuppressWarnings("unused") // react uses this
12
12
  public class PersonaInquiryPackage2 implements ReactPackage {
13
13
  @Override
14
14
  public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
@@ -17,6 +17,8 @@ public class PersonaInquiryPackage2 implements ReactPackage {
17
17
 
18
18
  @Override
19
19
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
20
- return Collections.emptyList();
20
+ return Arrays.<ViewManager>asList(
21
+ new PersonaInquiryViewManager()
22
+ );
21
23
  }
22
24
  }
@@ -0,0 +1,190 @@
1
+ package com.withpersona.sdk2.reactnative;
2
+
3
+ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
4
+ import static com.withpersona.sdk2.inquiry.types.ConstsKt.DEFAULT_REQUEST_KEY;
5
+
6
+ import android.graphics.Color;
7
+ import android.view.Choreographer;
8
+ import android.view.View;
9
+ import android.view.ViewGroup;
10
+ import android.widget.FrameLayout;
11
+
12
+ import androidx.annotation.NonNull;
13
+ import androidx.annotation.Nullable;
14
+ import androidx.fragment.app.Fragment;
15
+ import androidx.fragment.app.FragmentActivity;
16
+
17
+ import com.facebook.react.bridge.ReactApplicationContext;
18
+ import com.facebook.react.bridge.ReadableArray;
19
+ import com.facebook.react.bridge.ReadableMap;
20
+ import com.facebook.react.common.MapBuilder;
21
+ import com.facebook.react.uimanager.ThemedReactContext;
22
+ import com.facebook.react.uimanager.ViewGroupManager;
23
+ import com.facebook.react.uimanager.annotations.ReactProp;
24
+ import com.withpersona.sdk2.inquiry.Inquiry;
25
+ import com.withpersona.sdk2.inquiry.InquiryResponse;
26
+
27
+ import java.util.Map;
28
+
29
+ class PersonaInquiryViewManager extends ViewGroupManager<FrameLayout> {
30
+ public static final String REACT_CLASS = "PersonaInquiryView";
31
+ public final int COMMAND_CREATE = 1;
32
+
33
+ @Nullable
34
+ ThemedReactContext reactContext;
35
+
36
+ @NonNull
37
+ @Override
38
+ public String getName() {
39
+ return REACT_CLASS;
40
+ }
41
+
42
+ /**
43
+ * Return a FrameLayout which will later hold the Fragment
44
+ */
45
+ @NonNull
46
+ @Override
47
+ public FrameLayout createViewInstance(@NonNull ThemedReactContext reactContext) {
48
+ this.reactContext = reactContext;
49
+ FrameLayout frameLayout = new FrameLayout(reactContext);
50
+ frameLayout.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
51
+ return frameLayout;
52
+ }
53
+
54
+ /**
55
+ * Map the "create" command to an integer
56
+ */
57
+ @Nullable
58
+ @Override
59
+ public Map<String, Integer> getCommandsMap() {
60
+ return MapBuilder.of("create", COMMAND_CREATE);
61
+ }
62
+
63
+ /**
64
+ * Handle "create" command (called from JS) and call createFragment method
65
+ */
66
+ @Override
67
+ public void receiveCommand(
68
+ @NonNull FrameLayout root,
69
+ int commandId,
70
+ @Nullable ReadableArray args
71
+ ) {
72
+ super.receiveCommand(root, commandId, args);
73
+ int reactNativeViewId = args.getInt(0);
74
+
75
+ switch (commandId) {
76
+ case COMMAND_CREATE:
77
+ createFragment(root, reactNativeViewId);
78
+ break;
79
+ default: {}
80
+ }
81
+ }
82
+
83
+ @ReactProp(name = "inquiry")
84
+ public void setInquiry(FrameLayout view, @Nullable ReadableMap options) {
85
+ view.setTag(R.id.pi2_rn_inquiry_options, options);
86
+ }
87
+
88
+ @Override
89
+ @NonNull
90
+ public Map getExportedCustomBubblingEventTypeConstants() {
91
+ return MapBuilder.builder()
92
+ .put(
93
+ "onComplete",
94
+ MapBuilder.of(
95
+ "phasedRegistrationNames",
96
+ MapBuilder.of("bubbled", "onComplete")
97
+ )
98
+ ).put(
99
+ "onCanceled",
100
+ MapBuilder.of(
101
+ "phasedRegistrationNames",
102
+ MapBuilder.of("bubbled", "onCanceled")
103
+ )
104
+ ).put(
105
+ "onError",
106
+ MapBuilder.of(
107
+ "phasedRegistrationNames",
108
+ MapBuilder.of("bubbled", "onError")
109
+ )
110
+ ).build();
111
+ }
112
+
113
+ /**
114
+ * Replace your React Native view with a custom fragment
115
+ */
116
+ public void createFragment(FrameLayout root, int reactNativeViewId) {
117
+ if (reactContext == null) {
118
+ return;
119
+ }
120
+
121
+ ViewGroup parentView = root.findViewById(reactNativeViewId);
122
+ setupLayout(parentView);
123
+
124
+ Object inquiryOptions = root.getTag(R.id.pi2_rn_inquiry_options);
125
+ Inquiry inquiry = null;
126
+ if (inquiryOptions instanceof ReadableMap) {
127
+ inquiry = InquiryUtils.newInquiryFromMap((ReadableMap) inquiryOptions);
128
+ }
129
+
130
+ if (inquiry == null) {
131
+ return;
132
+ }
133
+
134
+ Fragment fragment = inquiry
135
+ .buildInlineInquiry()
136
+ .build()
137
+ .createFragment();
138
+
139
+ if (fragment == null) {
140
+ return;
141
+ }
142
+
143
+ FragmentActivity activity = (FragmentActivity) reactContext.getCurrentActivity();
144
+
145
+ if (activity == null) {
146
+ return;
147
+ }
148
+
149
+ activity.getSupportFragmentManager()
150
+ .setFragmentResultListener(DEFAULT_REQUEST_KEY, activity, (requestKey, result) -> {
151
+ InquiryResponse response = Inquiry.extractInquiryResponseFromBundle(result, reactContext);
152
+ new InquiryEventEmitter(reactContext).emitResponse(response, root);
153
+ });
154
+
155
+ activity.getSupportFragmentManager()
156
+ .beginTransaction()
157
+ .replace(reactNativeViewId, fragment, String.valueOf(reactNativeViewId))
158
+ .commit();
159
+ parentView.requestLayout();
160
+ }
161
+
162
+ public void setupLayout(View view) {
163
+ Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
164
+ @Override
165
+ public void doFrame(long frameTimeNanos) {
166
+ manuallyLayoutChildren(view);
167
+ view.getViewTreeObserver().dispatchOnGlobalLayout();
168
+ Choreographer.getInstance().postFrameCallback(this);
169
+ }
170
+ });
171
+ }
172
+
173
+ /**
174
+ * Layout all children properly
175
+ */
176
+ public void manuallyLayoutChildren(View view) {
177
+ if (view instanceof ViewGroup) {
178
+ ViewGroup viewGroup = (ViewGroup) view;
179
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
180
+ View child = viewGroup.getChildAt(i);
181
+
182
+ child.measure(
183
+ View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
184
+ View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
185
+
186
+ child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
187
+ }
188
+ }
189
+ }
190
+ }
@@ -0,0 +1,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <item name="pi2_rn_inquiry_options" type="id" />
4
+ </resources>
@@ -1,2 +1,4 @@
1
1
  #import "React/RCTBridgeModule.h"
2
2
  #import "React/RCTEventEmitter.h"
3
+ #import "React/RCTViewManager.h"
4
+ #import "React/RCTUIManager.h"
@@ -9,6 +9,7 @@
9
9
  /* Begin PBXBuildFile section */
10
10
  16D866A42A1575D800721E31 /* PersonaInquiryBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 16D866A22A1575D800721E31 /* PersonaInquiryBridge.m */; };
11
11
  16D866A52A1575D800721E31 /* PersonaInquiry2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 16D866A32A1575D800721E31 /* PersonaInquiry2.swift */; };
12
+ 7CE7D6FB2EE2307C0038CF67 /* PersonaInquiryViewManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7CE7D6FA2EE230730038CF67 /* PersonaInquiryViewManager.swift */; };
12
13
  /* End PBXBuildFile section */
13
14
 
14
15
  /* Begin PBXCopyFilesBuildPhase section */
@@ -27,6 +28,7 @@
27
28
  134814201AA4EA6300B7C361 /* libPersonaInquiry.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPersonaInquiry.a; sourceTree = BUILT_PRODUCTS_DIR; };
28
29
  16D866A22A1575D800721E31 /* PersonaInquiryBridge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PersonaInquiryBridge.m; sourceTree = "<group>"; };
29
30
  16D866A32A1575D800721E31 /* PersonaInquiry2.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PersonaInquiry2.swift; sourceTree = "<group>"; };
31
+ 7CE7D6FA2EE230730038CF67 /* PersonaInquiryViewManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonaInquiryViewManager.swift; sourceTree = "<group>"; };
30
32
  F618109E242AD27000CF7049 /* PersonaInquiry-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PersonaInquiry-Bridging-Header.h"; sourceTree = "<group>"; };
31
33
  /* End PBXFileReference section */
32
34
 
@@ -52,6 +54,7 @@
52
54
  58B511D21A9E6C8500147676 = {
53
55
  isa = PBXGroup;
54
56
  children = (
57
+ 7CE7D6FA2EE230730038CF67 /* PersonaInquiryViewManager.swift */,
55
58
  16D866A32A1575D800721E31 /* PersonaInquiry2.swift */,
56
59
  16D866A22A1575D800721E31 /* PersonaInquiryBridge.m */,
57
60
  134814211AA4EA7D00B7C361 /* Products */,
@@ -117,6 +120,7 @@
117
120
  isa = PBXSourcesBuildPhase;
118
121
  buildActionMask = 2147483647;
119
122
  files = (
123
+ 7CE7D6FB2EE2307C0038CF67 /* PersonaInquiryViewManager.swift in Sources */,
120
124
  16D866A42A1575D800721E31 /* PersonaInquiryBridge.m in Sources */,
121
125
  16D866A52A1575D800721E31 /* PersonaInquiry2.swift in Sources */,
122
126
  );