@veriff/react-native-sdk 2.7.0 → 2.10.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.
- package/.prettierrc.js +0 -1
- package/.vscode/settings.json +3 -0
- package/android/build.gradle +25 -134
- package/android/src/main/java/com/veriff/sdk/reactnative/ImageLoader.java +119 -0
- package/android/src/main/java/com/veriff/sdk/reactnative/ReactNativeExternalResources.java +105 -0
- package/android/src/main/java/com/veriff/sdk/reactnative/ReactNativeImageProvider.java +5 -16
- package/android/src/main/java/com/veriff/sdk/reactnative/VeriffSdkModule.java +88 -33
- package/android/src/main/java/com/veriff/sdk/reactnative/mapper/ExternalResourcesMapper.java +114 -0
- package/app.plugin.js +1 -1
- package/ios/Podfile +9 -31
- package/ios/VeriffSdk.swift +70 -2
- package/ios/VeriffSdkImageProvider.swift +5 -7
- package/package.json +29 -7
- package/react-native-sdk.podspec +2 -1
package/.prettierrc.js
CHANGED
package/android/build.gradle
CHANGED
|
@@ -1,155 +1,46 @@
|
|
|
1
|
-
|
|
1
|
+
buildscript {
|
|
2
|
+
ext.safeExtGet = { prop, fallback ->
|
|
3
|
+
return rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
4
|
+
}
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
// - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/build.gradle
|
|
8
|
-
//
|
|
9
|
-
// * https://github.com/facebook/react-native/blob/0.60-stable/template/android/app/build.gradle
|
|
10
|
-
// original location:
|
|
11
|
-
// - https://github.com/facebook/react-native/blob/0.58-stable/local-cli/templates/HelloWorld/android/app/build.gradle
|
|
6
|
+
repositories {
|
|
7
|
+
google()
|
|
8
|
+
mavenCentral()
|
|
9
|
+
}
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
dependencies {
|
|
12
|
+
classpath 'com.android.tools.build:gradle:7.0.4'
|
|
13
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${safeExtGet('kotlinVersion', '1.6.10')}"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
17
16
|
|
|
18
17
|
def safeExtGet(prop, fallback) {
|
|
19
18
|
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
apply plugin: 'com.android.library'
|
|
23
|
-
apply plugin: '
|
|
24
|
-
|
|
25
|
-
buildscript {
|
|
26
|
-
// The Android Gradle plugin is only required when opening the android folder stand-alone.
|
|
27
|
-
// This avoids unnecessary downloads and potential conflicts when the library is included as a
|
|
28
|
-
// module dependency in an application project.
|
|
29
|
-
// ref: https://docs.gradle.org/current/userguide/tutorial_using_tasks.html#sec:build_script_external_dependencies
|
|
30
|
-
if (project == rootProject) {
|
|
31
|
-
repositories {
|
|
32
|
-
google()
|
|
33
|
-
jcenter()
|
|
34
|
-
}
|
|
35
|
-
dependencies {
|
|
36
|
-
classpath 'com.android.tools.build:gradle:3.4.1'
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
apply plugin: 'com.android.library'
|
|
42
|
-
apply plugin: 'maven'
|
|
22
|
+
apply plugin: 'kotlin-android'
|
|
23
|
+
apply plugin: 'maven-publish'
|
|
43
24
|
|
|
44
25
|
android {
|
|
45
|
-
compileSdkVersion safeExtGet('compileSdkVersion',
|
|
46
|
-
buildToolsVersion safeExtGet('buildToolsVersion',
|
|
26
|
+
compileSdkVersion safeExtGet('compileSdkVersion', 31)
|
|
27
|
+
buildToolsVersion safeExtGet('buildToolsVersion', '31.0.0')
|
|
28
|
+
|
|
47
29
|
defaultConfig {
|
|
48
|
-
minSdkVersion safeExtGet('minSdkVersion',
|
|
49
|
-
targetSdkVersion safeExtGet('targetSdkVersion',
|
|
50
|
-
versionCode 1
|
|
51
|
-
versionName "1.0"
|
|
52
|
-
}
|
|
53
|
-
compileOptions {
|
|
54
|
-
sourceCompatibility JavaVersion.VERSION_1_8
|
|
55
|
-
targetCompatibility JavaVersion.VERSION_1_8
|
|
56
|
-
}
|
|
57
|
-
lintOptions {
|
|
58
|
-
abortOnError false
|
|
30
|
+
minSdkVersion safeExtGet('minSdkVersion', 21)
|
|
31
|
+
targetSdkVersion safeExtGet('targetSdkVersion', 31)
|
|
59
32
|
}
|
|
60
33
|
}
|
|
61
34
|
|
|
62
35
|
repositories {
|
|
63
|
-
// ref: https://www.baeldung.com/maven-local-repository
|
|
64
36
|
mavenLocal()
|
|
65
|
-
maven {
|
|
66
|
-
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
|
67
|
-
url "$rootDir/../node_modules/react-native/android"
|
|
68
|
-
}
|
|
69
|
-
maven {
|
|
70
|
-
// Android JSC is installed from npm
|
|
71
|
-
url "$rootDir/../node_modules/jsc-android/dist"
|
|
72
|
-
}
|
|
73
|
-
maven { url "https://cdn.veriff.me/android/" } //veriff
|
|
74
37
|
google()
|
|
75
|
-
|
|
38
|
+
mavenCentral()
|
|
39
|
+
maven { url "https://cdn.veriff.me/android/" } //veriff public repo
|
|
76
40
|
}
|
|
77
41
|
|
|
78
42
|
dependencies {
|
|
79
43
|
//noinspection GradleDynamicVersion
|
|
80
|
-
implementation 'com.facebook.react:react-native:+'
|
|
81
|
-
implementation 'com.veriff:veriff-library:4
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
def configureReactNativePom(def pom) {
|
|
85
|
-
def packageJson = new groovy.json.JsonSlurper().parseText(file('../package.json').text)
|
|
86
|
-
|
|
87
|
-
pom.project {
|
|
88
|
-
name packageJson.title
|
|
89
|
-
artifactId packageJson.name
|
|
90
|
-
version = packageJson.version
|
|
91
|
-
group = "com.reactlibrary"
|
|
92
|
-
description packageJson.description
|
|
93
|
-
url = "https://github.com/veriff/react-native-sdk"
|
|
94
|
-
|
|
95
|
-
licenses {
|
|
96
|
-
license {
|
|
97
|
-
name packageJson.license
|
|
98
|
-
url "https://github.com/veriff/react-native-sdk" + '/blob/master/' + packageJson.licenseFilename
|
|
99
|
-
distribution 'repo'
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
developers {
|
|
104
|
-
developer {
|
|
105
|
-
id packageJson.author.username
|
|
106
|
-
name packageJson.author.name
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
afterEvaluate { project ->
|
|
113
|
-
// some Gradle build hooks ref:
|
|
114
|
-
// https://www.oreilly.com/library/view/gradle-beyond-the/9781449373801/ch03.html
|
|
115
|
-
task androidJavadoc(type: Javadoc) {
|
|
116
|
-
source = android.sourceSets.main.java.srcDirs
|
|
117
|
-
classpath += files(android.bootClasspath)
|
|
118
|
-
classpath += files(project.getConfigurations().getByName('compile').asList())
|
|
119
|
-
include '**/*.java'
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
task androidJavadocJar(type: Jar, dependsOn: androidJavadoc) {
|
|
123
|
-
classifier = 'javadoc'
|
|
124
|
-
from androidJavadoc.destinationDir
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
task androidSourcesJar(type: Jar) {
|
|
128
|
-
classifier = 'sources'
|
|
129
|
-
from android.sourceSets.main.java.srcDirs
|
|
130
|
-
include '**/*.java'
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
android.libraryVariants.all { variant ->
|
|
134
|
-
def name = variant.name.capitalize()
|
|
135
|
-
def javaCompileTask = variant.javaCompileProvider.get()
|
|
136
|
-
|
|
137
|
-
task "jar${name}"(type: Jar, dependsOn: javaCompileTask) {
|
|
138
|
-
from javaCompileTask.destinationDir
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
artifacts {
|
|
143
|
-
archives androidSourcesJar
|
|
144
|
-
archives androidJavadocJar
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
task installArchives(type: Upload) {
|
|
148
|
-
configuration = configurations.archives
|
|
149
|
-
repositories.mavenDeployer {
|
|
150
|
-
// Deploy to react-native-event-bridge/maven, ready to publish to npm
|
|
151
|
-
repository url: "file://${projectDir}/../android/maven"
|
|
152
|
-
configureReactNativePom pom
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
44
|
+
implementation 'com.facebook.react:react-native:+'
|
|
45
|
+
implementation 'com.veriff:veriff-library:4.6.1'
|
|
46
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
package com.veriff.sdk.reactnative;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.graphics.Bitmap;
|
|
5
|
+
import android.graphics.drawable.BitmapDrawable;
|
|
6
|
+
import android.graphics.drawable.Drawable;
|
|
7
|
+
import android.os.Handler;
|
|
8
|
+
import android.os.Looper;
|
|
9
|
+
import android.util.Log;
|
|
10
|
+
import com.facebook.common.references.CloseableReference;
|
|
11
|
+
import com.facebook.datasource.DataSource;
|
|
12
|
+
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
13
|
+
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
|
14
|
+
import com.facebook.imagepipeline.image.CloseableImage;
|
|
15
|
+
import com.facebook.imagepipeline.request.ImageRequest;
|
|
16
|
+
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
|
17
|
+
|
|
18
|
+
import java.io.IOException;
|
|
19
|
+
import java.util.concurrent.CountDownLatch;
|
|
20
|
+
import java.util.concurrent.atomic.AtomicReference;
|
|
21
|
+
|
|
22
|
+
public class ImageLoader {
|
|
23
|
+
private static final String TAG = "ImageLoader";
|
|
24
|
+
|
|
25
|
+
private final Handler main = new Handler(Looper.getMainLooper());
|
|
26
|
+
|
|
27
|
+
public Drawable load(Context context, String url) throws IOException {
|
|
28
|
+
if (isAsyncLogoUrl(url)) {
|
|
29
|
+
Log.d(TAG, "Async image" + url);
|
|
30
|
+
return loadAsyncImage(context, url);
|
|
31
|
+
} else {
|
|
32
|
+
Log.d(TAG, "Image from resource" + url);
|
|
33
|
+
int drawableId = getDrawableId(context, url);
|
|
34
|
+
return context.getDrawable(drawableId);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private Drawable loadAsyncImage(Context context, String url) throws IOException {
|
|
39
|
+
ImageRequest request = ImageRequestBuilder.fromRequest(ImageRequest.fromUri(url)).build();
|
|
40
|
+
|
|
41
|
+
if (!Fresco.hasBeenInitialized()) {
|
|
42
|
+
Fresco.initialize(context);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
DataSource<CloseableReference<CloseableImage>> source =
|
|
46
|
+
Fresco.getImagePipeline().fetchDecodedImage(request, null);
|
|
47
|
+
|
|
48
|
+
CountDownLatch imageLoadLatch = new CountDownLatch(1);
|
|
49
|
+
AtomicReference<Result> atomicResult = new AtomicReference<>(null);
|
|
50
|
+
source.subscribe(new BaseBitmapDataSubscriber() {
|
|
51
|
+
@Override
|
|
52
|
+
protected void onNewResultImpl(Bitmap bitmap) {
|
|
53
|
+
if (bitmap == null) {
|
|
54
|
+
Log.w(TAG, "Null bitmap: " + url);
|
|
55
|
+
atomicResult.set(new Result(new IOException("Loaded bitmap was null")));
|
|
56
|
+
} else {
|
|
57
|
+
Log.w(TAG, "Non-Null bitmap: " + url);
|
|
58
|
+
atomicResult.set(new Result(bitmap.copy(bitmap.getConfig(), false)));
|
|
59
|
+
}
|
|
60
|
+
imageLoadLatch.countDown();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@Override
|
|
64
|
+
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
|
|
65
|
+
Throwable failure = dataSource.getFailureCause();
|
|
66
|
+
if (failure == null) {
|
|
67
|
+
atomicResult.set(new Result(new IOException("Provided failure cause was null")));
|
|
68
|
+
} else if (failure instanceof IOException) {
|
|
69
|
+
atomicResult.set(new Result((IOException) failure));
|
|
70
|
+
} else {
|
|
71
|
+
atomicResult.set(new Result(new IOException("Failed loading image", failure)));
|
|
72
|
+
}
|
|
73
|
+
imageLoadLatch.countDown();
|
|
74
|
+
}
|
|
75
|
+
}, main::post);
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
try {
|
|
79
|
+
imageLoadLatch.await();
|
|
80
|
+
Result result = atomicResult.get();
|
|
81
|
+
|
|
82
|
+
if (result.error != null) {
|
|
83
|
+
Log.w(TAG, "[ImageLoader] Loading image from [" + url + "] failed", result.error);
|
|
84
|
+
throw result.error;
|
|
85
|
+
} else {
|
|
86
|
+
Log.w(TAG, "[ImageLoader] Loading image [" + url + "] got a bitmap with size w=" + result.bitmap.getWidth() + " h=" + result.bitmap.getHeight());
|
|
87
|
+
return new BitmapDrawable(context.getResources(), result.bitmap);
|
|
88
|
+
}
|
|
89
|
+
} catch (InterruptedException e) {
|
|
90
|
+
Thread.currentThread().interrupt(); // preserve interrupt status
|
|
91
|
+
throw new IOException("Interrupted while loading image");
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private static int getDrawableId(Context context, String name) {
|
|
96
|
+
return context.getResources().getIdentifier(name, "drawable", context.getPackageName());
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
private boolean isAsyncLogoUrl(String url) {
|
|
100
|
+
return url.startsWith("https://") || url.startsWith("http://") || url.startsWith("file://");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private static class Result {
|
|
104
|
+
private final IOException error;
|
|
105
|
+
|
|
106
|
+
private final Bitmap bitmap;
|
|
107
|
+
|
|
108
|
+
private Result(IOException error) {
|
|
109
|
+
this.error = error;
|
|
110
|
+
this.bitmap = null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private Result(Bitmap bitmap) {
|
|
114
|
+
this.error = null;
|
|
115
|
+
this.bitmap = bitmap;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
package com.veriff.sdk.reactnative;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.graphics.Typeface;
|
|
5
|
+
import android.graphics.drawable.Drawable;
|
|
6
|
+
import android.os.Parcel;
|
|
7
|
+
import android.os.Parcelable;
|
|
8
|
+
import android.util.Log;
|
|
9
|
+
import androidx.annotation.NonNull;
|
|
10
|
+
import androidx.annotation.Nullable;
|
|
11
|
+
import com.veriff.Branding;
|
|
12
|
+
import com.veriff.Branding.ExternalResources.Image;
|
|
13
|
+
import com.veriff.Branding.ExternalResources.Lottie;
|
|
14
|
+
|
|
15
|
+
import java.io.IOException;
|
|
16
|
+
import java.util.HashMap;
|
|
17
|
+
import java.util.Map;
|
|
18
|
+
|
|
19
|
+
import static com.veriff.sdk.reactnative.VeriffSdkModule.TAG;
|
|
20
|
+
|
|
21
|
+
public class ReactNativeExternalResources implements Branding.ExternalResources, Parcelable {
|
|
22
|
+
private final ImageLoader imageLoader = new ImageLoader();
|
|
23
|
+
|
|
24
|
+
private final Map<Image, String> imageUrls;
|
|
25
|
+
private final Map<Lottie, String> lottieJson;
|
|
26
|
+
|
|
27
|
+
protected ReactNativeExternalResources(Parcel in) {
|
|
28
|
+
imageUrls = readMapFromParcel(in, Image.values());
|
|
29
|
+
lottieJson = readMapFromParcel(in, Lottie.values());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public ReactNativeExternalResources(Map<Image, String> imageUrls, Map<Lottie, String> lottieJson) {
|
|
33
|
+
this.imageUrls = imageUrls;
|
|
34
|
+
this.lottieJson = lottieJson;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Nullable
|
|
38
|
+
@Override
|
|
39
|
+
public Drawable loadImage(@NonNull Context context, @NonNull Image target) throws IOException {
|
|
40
|
+
String imageUrl = imageUrls.get(target);
|
|
41
|
+
if (imageUrl != null) {
|
|
42
|
+
return imageLoader.load(context, imageUrl);
|
|
43
|
+
} else {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Nullable
|
|
49
|
+
@Override
|
|
50
|
+
public String getLottieJson(Context context, @NonNull Lottie target) {
|
|
51
|
+
return lottieJson.get(target);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public static final Creator<ReactNativeExternalResources> CREATOR = new Creator<ReactNativeExternalResources>() {
|
|
55
|
+
@Override
|
|
56
|
+
public ReactNativeExternalResources createFromParcel(Parcel in) {
|
|
57
|
+
return new ReactNativeExternalResources(in);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@Override
|
|
61
|
+
public ReactNativeExternalResources[] newArray(int size) {
|
|
62
|
+
return new ReactNativeExternalResources[size];
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
@Override
|
|
67
|
+
public int describeContents() {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@Override
|
|
72
|
+
public void writeToParcel(Parcel dest, int flags) {
|
|
73
|
+
writeMapToParcel(dest, imageUrls);
|
|
74
|
+
writeMapToParcel(dest, lottieJson);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private <E extends Enum<E>> void writeMapToParcel(Parcel dest, Map<E, String> map) {
|
|
78
|
+
dest.writeInt(map.size());
|
|
79
|
+
for (Map.Entry<E, String> entry : map.entrySet()) {
|
|
80
|
+
dest.writeInt(entry.getKey().ordinal());
|
|
81
|
+
dest.writeString(entry.getValue());
|
|
82
|
+
Log.d(TAG, String.format("Write to parcel [%s] -> [%s]", entry.getKey().ordinal(), entry.getValue()));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public <E extends Enum<E>> Map<E, String> readMapFromParcel(Parcel in, E[] values) {
|
|
87
|
+
int count = in.readInt();
|
|
88
|
+
|
|
89
|
+
Map<E, String> map = new HashMap<>(count);
|
|
90
|
+
|
|
91
|
+
int i = 0;
|
|
92
|
+
while (i < count) {
|
|
93
|
+
i++;
|
|
94
|
+
|
|
95
|
+
int ordinal = in.readInt();
|
|
96
|
+
String value = in.readString();
|
|
97
|
+
Log.d(TAG, String.format("Read from parcel [%s] -> [%s]", ordinal, value));
|
|
98
|
+
|
|
99
|
+
E key = values[ordinal];
|
|
100
|
+
map.put(key, value);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return map;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
@@ -10,9 +10,6 @@ import android.os.Parcel;
|
|
|
10
10
|
import android.os.Parcelable;
|
|
11
11
|
import android.util.Log;
|
|
12
12
|
|
|
13
|
-
import androidx.annotation.NonNull;
|
|
14
|
-
import androidx.annotation.WorkerThread;
|
|
15
|
-
|
|
16
13
|
import com.facebook.common.references.CloseableReference;
|
|
17
14
|
import com.facebook.datasource.DataSource;
|
|
18
15
|
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
@@ -22,15 +19,12 @@ import com.facebook.imagepipeline.request.ImageRequest;
|
|
|
22
19
|
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
|
23
20
|
import com.veriff.Branding;
|
|
24
21
|
|
|
25
|
-
import org.jetbrains.annotations.NotNull;
|
|
26
|
-
import org.jetbrains.annotations.Nullable;
|
|
27
|
-
|
|
28
22
|
import java.io.IOException;
|
|
29
23
|
import java.util.concurrent.CountDownLatch;
|
|
30
24
|
import java.util.concurrent.atomic.AtomicReference;
|
|
31
25
|
|
|
32
26
|
public class ReactNativeImageProvider implements Branding.DrawableProvider, Parcelable {
|
|
33
|
-
private static final String TAG = "
|
|
27
|
+
private static final String TAG = "ReactNativeImageProvider";
|
|
34
28
|
|
|
35
29
|
private final String url;
|
|
36
30
|
|
|
@@ -44,11 +38,8 @@ public class ReactNativeImageProvider implements Branding.DrawableProvider, Parc
|
|
|
44
38
|
this(in.readString());
|
|
45
39
|
}
|
|
46
40
|
|
|
47
|
-
@NonNull
|
|
48
|
-
@NotNull
|
|
49
41
|
@Override
|
|
50
|
-
|
|
51
|
-
public Drawable loadImage(@NonNull @NotNull Context context) throws IOException {
|
|
42
|
+
public Drawable loadImage(Context context) throws IOException {
|
|
52
43
|
ImageRequest request = ImageRequestBuilder.fromRequest(ImageRequest.fromUri(this.url)).build();
|
|
53
44
|
DataSource<CloseableReference<CloseableImage>> source =
|
|
54
45
|
Fresco.getImagePipeline().fetchDecodedImage(request, null);
|
|
@@ -58,7 +49,7 @@ public class ReactNativeImageProvider implements Branding.DrawableProvider, Parc
|
|
|
58
49
|
|
|
59
50
|
source.subscribe(new BaseBitmapDataSubscriber() {
|
|
60
51
|
@Override
|
|
61
|
-
protected void onNewResultImpl(
|
|
52
|
+
protected void onNewResultImpl(Bitmap bitmap) {
|
|
62
53
|
if (bitmap == null) {
|
|
63
54
|
atomicResult.set(new Result(new IOException("Loaded bitmap was null")));
|
|
64
55
|
} else {
|
|
@@ -87,10 +78,10 @@ public class ReactNativeImageProvider implements Branding.DrawableProvider, Parc
|
|
|
87
78
|
Result result = atomicResult.get();
|
|
88
79
|
|
|
89
80
|
if (result.error != null) {
|
|
90
|
-
Log.w(TAG, "Loading image from " + this.url + " failed", result.error);
|
|
81
|
+
Log.w(TAG, "[ReactNativeImageProvider] Loading image from [" + this.url + "] failed", result.error);
|
|
91
82
|
throw result.error;
|
|
92
83
|
} else {
|
|
93
|
-
Log.w(TAG, "Loading image got a bitmap with size w=" + result.bitmap.getWidth() + " h=" + result.bitmap.getHeight());
|
|
84
|
+
Log.w(TAG, "[ReactNativeImageProvider] Loading image [" + this.url + "] got a bitmap with size w=" + result.bitmap.getWidth() + " h=" + result.bitmap.getHeight());
|
|
94
85
|
return new BitmapDrawable(context.getResources(), result.bitmap);
|
|
95
86
|
}
|
|
96
87
|
} catch (InterruptedException e) {
|
|
@@ -100,10 +91,8 @@ public class ReactNativeImageProvider implements Branding.DrawableProvider, Parc
|
|
|
100
91
|
}
|
|
101
92
|
|
|
102
93
|
private static class Result {
|
|
103
|
-
@Nullable
|
|
104
94
|
private final IOException error;
|
|
105
95
|
|
|
106
|
-
@Nullable
|
|
107
96
|
private final Bitmap bitmap;
|
|
108
97
|
|
|
109
98
|
private Result(IOException error) {
|
|
@@ -3,6 +3,7 @@ package com.veriff.sdk.reactnative;
|
|
|
3
3
|
import android.app.Activity;
|
|
4
4
|
import android.content.Context;
|
|
5
5
|
import android.content.Intent;
|
|
6
|
+
import android.content.res.Resources;
|
|
6
7
|
import android.graphics.Color;
|
|
7
8
|
import android.text.TextUtils;
|
|
8
9
|
import android.util.Log;
|
|
@@ -19,15 +20,15 @@ import com.facebook.react.bridge.ReadableType;
|
|
|
19
20
|
import com.facebook.react.bridge.WritableMap;
|
|
20
21
|
import com.veriff.Branding;
|
|
21
22
|
import com.veriff.Configuration;
|
|
23
|
+
import com.veriff.Font;
|
|
22
24
|
import com.veriff.Result;
|
|
23
25
|
import com.veriff.Result.Status;
|
|
24
26
|
import com.veriff.Sdk;
|
|
25
27
|
|
|
26
|
-
import java.util
|
|
27
|
-
import java.util.Locale;
|
|
28
|
-
import java.util.Map;
|
|
28
|
+
import java.util.*;
|
|
29
29
|
|
|
30
30
|
import com.veriff.GeneralConfig;
|
|
31
|
+
import com.veriff.sdk.reactnative.mapper.ExternalResourcesMapper;
|
|
31
32
|
import okhttp3.HttpUrl;
|
|
32
33
|
|
|
33
34
|
import static android.app.Activity.RESULT_CANCELED;
|
|
@@ -62,7 +63,7 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
62
63
|
private static final String STATUS_ERROR = "STATUS_ERROR";
|
|
63
64
|
|
|
64
65
|
private static final String DEFAULT_BASE_URL = "https://magic.veriff.me";
|
|
65
|
-
|
|
66
|
+
public static final String TAG = "@veriff/RN-SDK";
|
|
66
67
|
private static final String JS_NAME = "VeriffSdk";
|
|
67
68
|
|
|
68
69
|
private static final int VERIFF_REQUEST_CODE = 47239;
|
|
@@ -86,8 +87,13 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
86
87
|
public static final String KEY_PRIMARY_BUTTON_BACKGROUND_COLOR = "primaryButtonBackgroundColor";
|
|
87
88
|
public static final String KEY_BUTTON_CORNER_RADIUS = "buttonCornerRadius";
|
|
88
89
|
private static final String KEY_CUSTOM_INTRO_SCREEN = "customIntroScreen";
|
|
90
|
+
public static final String KEY_ADVANCED_CONFIGURATIONS = "advancedConfigurations";
|
|
89
91
|
private static final String KEY_RN_IMAGE_URI = "uri";
|
|
90
92
|
|
|
93
|
+
private static final String KEY_FONT = "androidFont";
|
|
94
|
+
private static final String KEY_FONT_NORMAL = "regularFontName";
|
|
95
|
+
private static final String KEY_FONT_BOLD = "boldFontName";
|
|
96
|
+
|
|
91
97
|
private static final String ERROR_UNABLE_TO_ACCESS_CAMERA = "UNABLE_TO_ACCESS_CAMERA";
|
|
92
98
|
private static final String ERROR_UNABLE_TO_RECORD_AUDIO = "UNABLE_TO_RECORD_AUDIO";
|
|
93
99
|
private static final String ERROR_UNABLE_TO_START_CAMERA = "UNABLE_TO_START_CAMERA";
|
|
@@ -159,19 +165,19 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
159
165
|
} else {
|
|
160
166
|
sessionToken = configuration.hasKey(KEY_TOKEN) ? configuration.getString(KEY_TOKEN) : null;
|
|
161
167
|
if (TextUtils.isEmpty(sessionToken)) {
|
|
162
|
-
|
|
163
|
-
|
|
168
|
+
promise.reject(ERROR_INVALID_ARGS, "No sessionToken in Veriff SDK configuration");
|
|
169
|
+
return;
|
|
164
170
|
}
|
|
165
171
|
|
|
166
172
|
String baseUrl = null;
|
|
167
173
|
if (configuration.hasKey(KEY_BASE_URL)) {
|
|
168
|
-
|
|
174
|
+
baseUrl = configuration.getString(KEY_BASE_URL);
|
|
169
175
|
}
|
|
170
176
|
if (TextUtils.isEmpty(baseUrl)) {
|
|
171
|
-
|
|
177
|
+
baseUrl = DEFAULT_BASE_URL;
|
|
172
178
|
}
|
|
173
179
|
if (baseUrl.endsWith("/")) {
|
|
174
|
-
|
|
180
|
+
baseUrl = baseUrl.substring(0, baseUrl.length() - 1);
|
|
175
181
|
}
|
|
176
182
|
startUrl = baseUrl + "/v/" + sessionToken;
|
|
177
183
|
}
|
|
@@ -203,11 +209,11 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
203
209
|
|
|
204
210
|
Status status = resultCode == RESULT_CANCELED ? CANCELED : ERROR;
|
|
205
211
|
if (veriffResult != null) {
|
|
206
|
-
|
|
212
|
+
status = veriffResult.getStatus();
|
|
207
213
|
}
|
|
208
214
|
result.putString(KEY_STATUS, statusToString(status));
|
|
209
|
-
if (veriffResult != null && veriffResult.getError() != null){
|
|
210
|
-
|
|
215
|
+
if (veriffResult != null && veriffResult.getError() != null) {
|
|
216
|
+
result.putString(KEY_ERROR, codeToError(veriffResult.getError()));
|
|
211
217
|
}
|
|
212
218
|
|
|
213
219
|
promise.resolve(result);
|
|
@@ -255,7 +261,15 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
255
261
|
branding.primaryButtonBackgroundColor(parseColor(brandConfig.getString(KEY_PRIMARY_BUTTON_BACKGROUND_COLOR)));
|
|
256
262
|
}
|
|
257
263
|
if (brandConfig.hasKey(KEY_BUTTON_CORNER_RADIUS)) {
|
|
258
|
-
branding.buttonCornerRadius((float)brandConfig.getDouble(KEY_BUTTON_CORNER_RADIUS));
|
|
264
|
+
branding.buttonCornerRadius((float) brandConfig.getDouble(KEY_BUTTON_CORNER_RADIUS));
|
|
265
|
+
}
|
|
266
|
+
handleExternalResources(brandConfig, branding);
|
|
267
|
+
handleAdvancedConfigurations(brandConfig, branding);
|
|
268
|
+
|
|
269
|
+
if (brandConfig.hasKey(KEY_FONT)) {
|
|
270
|
+
ReadableMap srcFont = brandConfig.getMap(KEY_FONT);
|
|
271
|
+
Font font = buildFont(activity, srcFont);
|
|
272
|
+
branding.font(font);
|
|
259
273
|
}
|
|
260
274
|
configBuilder.branding(branding.build());
|
|
261
275
|
}
|
|
@@ -269,13 +283,47 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
269
283
|
activity.startActivityForResult(intent, VERIFF_REQUEST_CODE);
|
|
270
284
|
|
|
271
285
|
} catch (Throwable t) {
|
|
272
|
-
|
|
273
|
-
|
|
286
|
+
Log.e(TAG, "starting verification failed", t);
|
|
287
|
+
promise.reject(t);
|
|
274
288
|
}
|
|
275
289
|
}
|
|
276
290
|
|
|
291
|
+
private Font buildFont(Context context, ReadableMap src) {
|
|
292
|
+
int normalFont = getFontId(context, src.getString(KEY_FONT_NORMAL));
|
|
293
|
+
int boldFont = getFontId(context, src.getString(KEY_FONT_BOLD));
|
|
294
|
+
|
|
295
|
+
Log.v(TAG, String.format("Normal font: [%s], value [%s]",
|
|
296
|
+
src.getString(KEY_FONT_NORMAL), normalFont));
|
|
297
|
+
|
|
298
|
+
Log.v(TAG, String.format("Bold font: [%s], value [%s]",
|
|
299
|
+
src.getString(KEY_FONT_BOLD), boldFont));
|
|
300
|
+
|
|
301
|
+
return new Font.Builder()
|
|
302
|
+
.setNormalAndBold(normalFont, boldFont)
|
|
303
|
+
.build();
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
private void handleExternalResources(ReadableMap brandConfig, Branding.Builder branding) {
|
|
308
|
+
ExternalResourcesMapper mapper = new ExternalResourcesMapper();
|
|
309
|
+
|
|
310
|
+
branding.externalResources(mapper.map(brandConfig));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private void handleAdvancedConfigurations(ReadableMap brandConfig, Branding.Builder branding) {
|
|
314
|
+
Map<String, Object> result = new HashMap<>();
|
|
315
|
+
|
|
316
|
+
if (brandConfig.hasKey(KEY_ADVANCED_CONFIGURATIONS)) {
|
|
317
|
+
ReadableMap config = brandConfig.getMap(KEY_ADVANCED_CONFIGURATIONS);
|
|
318
|
+
result.put("customer", config.getString("customer"));
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
branding.advancedConfigurations(result);
|
|
322
|
+
}
|
|
323
|
+
|
|
277
324
|
private void handleLogo(Context context, String key, Branding.Builder branding, ReadableMap brandConfig) {
|
|
278
325
|
ReadableType type = brandConfig.getType(key);
|
|
326
|
+
Log.d(TAG, "Logo type" + type);
|
|
279
327
|
if (ReadableType.String.equals(type)) {
|
|
280
328
|
branding.toolbarIcon(getDrawableId(context, brandConfig.getString(key)));
|
|
281
329
|
} else if (ReadableType.Map.equals(type)) {
|
|
@@ -287,15 +335,16 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
287
335
|
if (!TextUtils.isEmpty(url)) {
|
|
288
336
|
// check if url has an async scheme
|
|
289
337
|
if (isAsyncLogoUrl(url)) {
|
|
338
|
+
Log.d(TAG, "Async logo" + url);
|
|
290
339
|
branding.toolbarIconProvider(new ReactNativeImageProvider(url));
|
|
291
340
|
} else {
|
|
341
|
+
Log.d(TAG, "Logo from resource" + url);
|
|
292
342
|
branding.toolbarIcon(getDrawableId(context, url));
|
|
293
343
|
}
|
|
294
344
|
} else {
|
|
295
345
|
Log.w(TAG, "Image url is empty: " + url);
|
|
296
346
|
}
|
|
297
347
|
} else {
|
|
298
|
-
Log.w(TAG, "Provided image does not have " + KEY_RN_IMAGE_URI + " key. Keys: ");
|
|
299
348
|
for (String imageKey : image.toHashMap().keySet()) {
|
|
300
349
|
Log.w(TAG, imageKey);
|
|
301
350
|
}
|
|
@@ -304,7 +353,7 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
304
353
|
Log.w(TAG, "Provided image is null");
|
|
305
354
|
}
|
|
306
355
|
} else {
|
|
307
|
-
|
|
356
|
+
Log.w(TAG, "Unexpected image type: " + type);
|
|
308
357
|
}
|
|
309
358
|
}
|
|
310
359
|
|
|
@@ -322,12 +371,12 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
322
371
|
long color = Long.parseLong(hexcolor, 16);
|
|
323
372
|
int a = 255;
|
|
324
373
|
if (hexcolor.length() > 6) {
|
|
325
|
-
a = ((int)color) & 0xff;
|
|
374
|
+
a = ((int) color) & 0xff;
|
|
326
375
|
color = color >>> 8;
|
|
327
376
|
}
|
|
328
|
-
int r = ((int)(color >>> 16)) & 0xff;
|
|
329
|
-
int g = ((int)(color >>> 8)) & 0xff;
|
|
330
|
-
int b = ((int)(color >>> 0)) & 0xff;
|
|
377
|
+
int r = ((int) (color >>> 16)) & 0xff;
|
|
378
|
+
int g = ((int) (color >>> 8)) & 0xff;
|
|
379
|
+
int b = ((int) (color >>> 0)) & 0xff;
|
|
331
380
|
return Color.argb(a, r, g, b);
|
|
332
381
|
}
|
|
333
382
|
|
|
@@ -335,6 +384,10 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
335
384
|
return context.getResources().getIdentifier(name, "drawable", context.getPackageName());
|
|
336
385
|
}
|
|
337
386
|
|
|
387
|
+
private static int getFontId(Context context, String name) {
|
|
388
|
+
return context.getResources().getIdentifier(name, "font", context.getPackageName());
|
|
389
|
+
}
|
|
390
|
+
|
|
338
391
|
private static String codeToError(Result.Error error) {
|
|
339
392
|
switch (error) {
|
|
340
393
|
case UNABLE_TO_ACCESS_CAMERA:
|
|
@@ -344,17 +397,17 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
344
397
|
case UNABLE_TO_START_CAMERA:
|
|
345
398
|
return ERROR_UNABLE_TO_START_CAMERA;
|
|
346
399
|
case UNSUPPORTED_SDK_VERSION:
|
|
347
|
-
|
|
400
|
+
return ERROR_UNSUPPORTED_SDK_VERSION;
|
|
348
401
|
case SESSION_ERROR:
|
|
349
|
-
|
|
402
|
+
return ERROR_SESSION;
|
|
350
403
|
case NETWORK_ERROR:
|
|
351
|
-
|
|
404
|
+
return ERROR_NETWORK;
|
|
352
405
|
case SETUP_ERROR:
|
|
353
|
-
|
|
406
|
+
return ERROR_SETUP;
|
|
354
407
|
case NFC_DISABLED:
|
|
355
|
-
|
|
408
|
+
return ERROR_NFC_DISABLED;
|
|
356
409
|
case DEVICE_HAS_NO_NFC:
|
|
357
|
-
|
|
410
|
+
return ERROR_DEVICE_HAS_NO_NFC;
|
|
358
411
|
case UNKNOWN_ERROR:
|
|
359
412
|
default:
|
|
360
413
|
return ERROR_UNKNOWN;
|
|
@@ -362,11 +415,13 @@ public class VeriffSdkModule extends ReactContextBaseJavaModule {
|
|
|
362
415
|
}
|
|
363
416
|
|
|
364
417
|
private static String statusToString(Status status) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
418
|
+
switch (status) {
|
|
419
|
+
case DONE:
|
|
420
|
+
return STATUS_DONE;
|
|
421
|
+
case CANCELED:
|
|
422
|
+
return STATUS_CANCELED;
|
|
423
|
+
default:
|
|
424
|
+
return STATUS_ERROR;
|
|
425
|
+
}
|
|
370
426
|
}
|
|
371
|
-
|
|
372
427
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
package com.veriff.sdk.reactnative.mapper;
|
|
2
|
+
|
|
3
|
+
import android.graphics.Typeface;
|
|
4
|
+
import android.util.JsonWriter;
|
|
5
|
+
import android.util.Log;
|
|
6
|
+
import androidx.annotation.NonNull;
|
|
7
|
+
import com.facebook.infer.annotation.Assertions;
|
|
8
|
+
import com.facebook.react.bridge.Dynamic;
|
|
9
|
+
import com.facebook.react.bridge.ReadableArray;
|
|
10
|
+
import com.facebook.react.bridge.ReadableMap;
|
|
11
|
+
import com.facebook.react.bridge.ReadableNativeMap;
|
|
12
|
+
import com.veriff.sdk.reactnative.ImageLoader;
|
|
13
|
+
import com.veriff.sdk.reactnative.ReactNativeExternalResources;
|
|
14
|
+
import com.veriff.Branding;
|
|
15
|
+
import com.veriff.Branding.ExternalResources.Image;
|
|
16
|
+
import com.veriff.Branding.ExternalResources.Lottie;
|
|
17
|
+
|
|
18
|
+
import java.util.HashMap;
|
|
19
|
+
import java.util.Iterator;
|
|
20
|
+
import java.util.LinkedHashMap;
|
|
21
|
+
import java.util.Map;
|
|
22
|
+
|
|
23
|
+
import static com.veriff.sdk.reactnative.VeriffSdkModule.KEY_ADVANCED_CONFIGURATIONS;
|
|
24
|
+
import static com.veriff.sdk.reactnative.VeriffSdkModule.TAG;
|
|
25
|
+
|
|
26
|
+
public class ExternalResourcesMapper {
|
|
27
|
+
public ReactNativeExternalResources map(ReadableMap brandConfig) {
|
|
28
|
+
Map<Image, String> images = mapImages(brandConfig);
|
|
29
|
+
Map<Lottie, String> lottie = mapLottie(brandConfig);
|
|
30
|
+
|
|
31
|
+
if (!images.isEmpty() || !lottie.isEmpty()) {
|
|
32
|
+
return new ReactNativeExternalResources(images, lottie);
|
|
33
|
+
} else {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
private Map<Image, String> mapImages(ReadableMap brandConfig) {
|
|
39
|
+
Map<Image, String> images = new HashMap();
|
|
40
|
+
if (brandConfig.hasKey(KEY_ADVANCED_CONFIGURATIONS)) {
|
|
41
|
+
ReadableMap config = brandConfig.getMap(KEY_ADVANCED_CONFIGURATIONS);
|
|
42
|
+
|
|
43
|
+
appendImage(config, KEY_DOCUMENT_FRONT, images, Image.DOCUMENT_FRONT);
|
|
44
|
+
appendImage(config, KEY_DOCUMENT_BACK, images, Image.DOCUMENT_BACK_END);
|
|
45
|
+
appendImage(config, KEY_BANNER_ERROR_ICON, images, Image.BANNER_ICON_ERROR);
|
|
46
|
+
appendImage(config, KEY_CAMERA_ERROR, images, Image.ERROR_CAMERA);
|
|
47
|
+
appendImage(config, KEY_MICROPHONE_ERROR, images, Image.ERROR_MICROPHONE);
|
|
48
|
+
appendImage(config, KEY_SERVER_ERROR, images, Image.ERROR_SYSTEM);
|
|
49
|
+
appendImage(config, KEY_LOCAL_ERROR, images, Image.ERROR_SYSTEM);
|
|
50
|
+
appendImage(config, KEY_NETWORK_ERROR, images, Image.ERROR_NETWORK);
|
|
51
|
+
appendImage(config, KEY_VERSION_ERROR, images, Image.ERROR_VERSION);
|
|
52
|
+
appendImage(config, KEY_UNKNOWN_ERROR, images, Image.ERROR_UNKNOWN);
|
|
53
|
+
appendImage(config, KEY_CONSENT_ICON, images, Image.CONSENT_IMAGE);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return images;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
private void appendImage(
|
|
60
|
+
ReadableMap advancedConfig,
|
|
61
|
+
String configKey,
|
|
62
|
+
Map<Branding.ExternalResources.Image, String> map,
|
|
63
|
+
Branding.ExternalResources.Image mapKey
|
|
64
|
+
) {
|
|
65
|
+
if (advancedConfig.hasKey(configKey)) {
|
|
66
|
+
ReadableMap item = advancedConfig.getMap(configKey);
|
|
67
|
+
String url = item.getString("uri");
|
|
68
|
+
if (url != null) {
|
|
69
|
+
map.put(mapKey, url);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private Map<Lottie, String> mapLottie(ReadableMap brandConfig) {
|
|
75
|
+
Map<Lottie, String> lottie = new HashMap();
|
|
76
|
+
|
|
77
|
+
if (brandConfig.hasKey(KEY_ADVANCED_CONFIGURATIONS)) {
|
|
78
|
+
ReadableMap config = brandConfig.getMap(KEY_ADVANCED_CONFIGURATIONS);
|
|
79
|
+
|
|
80
|
+
appendLottie(config, KEY_LOTTIE_PROGRESS, lottie, Lottie.PROGRESS);
|
|
81
|
+
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return lottie;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private void appendLottie(
|
|
88
|
+
ReadableMap advancedConfig,
|
|
89
|
+
String configKey,
|
|
90
|
+
Map<Lottie, String> map,
|
|
91
|
+
Lottie mapKey
|
|
92
|
+
) {
|
|
93
|
+
if (advancedConfig.hasKey(configKey)) {
|
|
94
|
+
String lottie = advancedConfig.getString(configKey);
|
|
95
|
+
|
|
96
|
+
map.put(mapKey, lottie);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private final String KEY_DOCUMENT_FRONT = "documentFrontIcon";
|
|
101
|
+
private final String KEY_DOCUMENT_BACK = "documentBackIcon";
|
|
102
|
+
private final String KEY_BANNER_ERROR_ICON = "bannerErrorIcon";
|
|
103
|
+
private final String KEY_CONSENT_ICON = "consentIcon";
|
|
104
|
+
|
|
105
|
+
private final String KEY_CAMERA_ERROR = "cameraUnavailableErrorIcon";
|
|
106
|
+
private final String KEY_MICROPHONE_ERROR = "microphoneUnavailableErrorIcon";
|
|
107
|
+
private final String KEY_SERVER_ERROR = "serverErrorIcon";
|
|
108
|
+
private final String KEY_LOCAL_ERROR = "localErrorIcon";
|
|
109
|
+
private final String KEY_NETWORK_ERROR = "networkErrorIcon";
|
|
110
|
+
private final String KEY_VERSION_ERROR = "deprecatedSDKVersionErrorIcon";
|
|
111
|
+
private final String KEY_UNKNOWN_ERROR = "unknownErrorIcon";
|
|
112
|
+
|
|
113
|
+
private final String KEY_LOTTIE_PROGRESS = "loadingAnimation";
|
|
114
|
+
}
|
package/app.plugin.js
CHANGED
|
@@ -18,7 +18,7 @@ function getUpdatedProjectGradle(buildGradle) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
function withVeriffProjectGradle(expoConfig) {
|
|
21
|
-
return withProjectBuildGradle(expoConfig, config => {
|
|
21
|
+
return withProjectBuildGradle(expoConfig, (config) => {
|
|
22
22
|
config.modResults.contents = getUpdatedProjectGradle(
|
|
23
23
|
config.modResults.contents,
|
|
24
24
|
);
|
package/ios/Podfile
CHANGED
|
@@ -1,40 +1,18 @@
|
|
|
1
1
|
platform :ios, '11.0'
|
|
2
|
+
install! 'cocoapods', :deterministic_uuids => false
|
|
3
|
+
require_relative '../node_modules/react-native/scripts/react_native_pods'
|
|
2
4
|
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
|
|
3
5
|
|
|
4
6
|
target 'VeriffSdk' do
|
|
5
7
|
# Pods for VeriffSdk
|
|
6
8
|
pod 'VeriffSDK'
|
|
9
|
+
pod 'lottie-ios'
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
|
|
10
|
-
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
|
|
11
|
-
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
|
|
12
|
-
pod 'React', :path => '../node_modules/react-native/'
|
|
13
|
-
pod 'React-Core', :path => '../node_modules/react-native/'
|
|
14
|
-
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
|
|
15
|
-
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
|
|
16
|
-
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
|
|
17
|
-
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
|
|
18
|
-
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
|
|
19
|
-
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
|
|
20
|
-
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
|
|
21
|
-
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
|
|
22
|
-
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
|
|
23
|
-
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
|
|
24
|
-
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
|
|
25
|
-
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
|
|
11
|
+
config = use_native_modules!
|
|
26
12
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
|
|
33
|
-
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
|
|
34
|
-
|
|
35
|
-
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
|
|
36
|
-
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
|
|
37
|
-
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
|
|
38
|
-
|
|
39
|
-
use_native_modules!
|
|
13
|
+
# Flags change depending on the env values.
|
|
14
|
+
flags = get_default_flags()
|
|
15
|
+
use_react_native!(
|
|
16
|
+
:path => config[:reactNativePath]
|
|
17
|
+
)
|
|
40
18
|
end
|
package/ios/VeriffSdk.swift
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Foundation
|
|
2
2
|
import Veriff
|
|
3
3
|
import UIKit
|
|
4
|
+
import Lottie
|
|
4
5
|
|
|
5
6
|
@objc(VeriffSdkReactWrapper)
|
|
6
7
|
class VeriffSdk: NSObject {
|
|
@@ -28,7 +29,6 @@ class VeriffSdk: NSObject {
|
|
|
28
29
|
private static let BRANDING = "branding"
|
|
29
30
|
private static let LOCALE = "locale"
|
|
30
31
|
private static let THEME_COLOR = "themeColor"
|
|
31
|
-
static let NAVIGATION_BAR_IMAGE = "navigationBarImage"
|
|
32
32
|
static let LOGO = "logo"
|
|
33
33
|
private static let BACKGROUND_COLOR = "backgroundColor"
|
|
34
34
|
private static let STATUS_BAR_COLOR = "statusBarColor"
|
|
@@ -37,6 +37,8 @@ class VeriffSdk: NSObject {
|
|
|
37
37
|
private static let PRIMARY_BUTTON_BACKGROUND_COLOR = "primaryButtonBackgroundColor"
|
|
38
38
|
private static let BUTTON_CORNER_RADIUS = "buttonCornerRadius"
|
|
39
39
|
private static let USE_CUSTOM_INTRO_SCREEN = "customIntroScreen"
|
|
40
|
+
private static let ADVANCED_CONFIGURATIONS = "advancedConfigurations"
|
|
41
|
+
private static let FONT = "iOSFont"
|
|
40
42
|
|
|
41
43
|
private static let STATUS = "status"
|
|
42
44
|
private static let ERROR = "error"
|
|
@@ -69,7 +71,7 @@ class VeriffSdk: NSObject {
|
|
|
69
71
|
if let brandingConfig = (configuration[VeriffSdk.BRANDING] as? [String: AnyObject]) {
|
|
70
72
|
let color = (brandingConfig[VeriffSdk.THEME_COLOR] as? String).map { VeriffSdk.parseColor(hexcolor: $0) }
|
|
71
73
|
|
|
72
|
-
let imageProvider = VeriffSdkImageProvider(
|
|
74
|
+
let imageProvider = VeriffSdkImageProvider(imageSource: brandingConfig[VeriffSdk.LOGO])
|
|
73
75
|
|
|
74
76
|
if let imageURI = brandingConfig[VeriffSdk.LOGO],
|
|
75
77
|
let imageDict = imageURI as? [String: AnyObject],
|
|
@@ -97,6 +99,50 @@ class VeriffSdk: NSObject {
|
|
|
97
99
|
branding?.secondaryTextColor = (brandingConfig[VeriffSdk.SECONDARY_TEXT_COLOR] as? String).map { VeriffSdk.parseColor(hexcolor: $0) }
|
|
98
100
|
branding?.primaryButtonBackgroundColor = (brandingConfig[VeriffSdk.PRIMARY_BUTTON_BACKGROUND_COLOR] as? String).map { VeriffSdk.parseColor(hexcolor: $0) }
|
|
99
101
|
branding?.buttonCornerRadius = (brandingConfig[VeriffSdk.BUTTON_CORNER_RADIUS] as? Double).map { CGFloat($0) }
|
|
102
|
+
if let rnAdvancedConfigurations = brandingConfig[VeriffSdk.ADVANCED_CONFIGURATIONS] as? [String: Any] {
|
|
103
|
+
var advancedConfigurations: [String: Any] = [:]
|
|
104
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "rotateToPortraitIcon"), for: "rotateToPortraitIcon")
|
|
105
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "rotateToLandscapeIcon"), for: "rotateToLandscapeIcon")
|
|
106
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "documentFrontIcon"), for: "documentFrontIcon")
|
|
107
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "documentBackIcon"), for: "documentBackIcon")
|
|
108
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "cameraUnavailableErrorIcon"), for: "cameraUnavailableErrorIcon")
|
|
109
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "microphoneUnavailableErrorIcon"), for: "microphoneUnavailableErrorIcon")
|
|
110
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "serverErrorIcon"), for: "serverErrorIcon")
|
|
111
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "localErrorIcon"), for: "localErrorIcon")
|
|
112
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "networkErrorIcon"), for: "networkErrorIcon")
|
|
113
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "uploadErrorIcon"), for: "uploadErrorIcon")
|
|
114
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "videoFailedErrorIcon"), for: "videoFailedErrorIcon")
|
|
115
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "deprecatedSDKVersionErrorIcon"), for: "deprecatedSDKVersionErrorIcon")
|
|
116
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "unknownErrorIcon"), for: "unknownErrorIcon")
|
|
117
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "bannerErrorIcon"), for: "bannerErrorIcon")
|
|
118
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations.image(for: "consentIcon"), for: "consentIcon")
|
|
119
|
+
advancedConfigurations.addValue(rnAdvancedConfigurations["customer"], for: "customer")
|
|
120
|
+
if let loadingAnimationString = rnAdvancedConfigurations["loadingAnimation"] as? String {
|
|
121
|
+
if
|
|
122
|
+
let jsonData = loadingAnimationString.data(using: .utf8),
|
|
123
|
+
let animation = try? JSONDecoder().decode(Lottie.Animation.self, from: jsonData)
|
|
124
|
+
{
|
|
125
|
+
let animationView: () -> UIView = {
|
|
126
|
+
let animationView = Lottie.AnimationView(animation: animation)
|
|
127
|
+
animationView.backgroundBehavior = .pauseAndRestore
|
|
128
|
+
animationView.loopMode = .loop
|
|
129
|
+
animationView.play(completion: nil)
|
|
130
|
+
return animationView
|
|
131
|
+
}
|
|
132
|
+
advancedConfigurations["loadingAnimation"] = animationView
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
branding?.advancedConfigurations = advancedConfigurations
|
|
136
|
+
}
|
|
137
|
+
if
|
|
138
|
+
let font = brandingConfig[VeriffSdk.FONT] as? [String: Any],
|
|
139
|
+
let regular = font["regularFontName"] as? String,
|
|
140
|
+
let light = font["lightFontName"] as? String,
|
|
141
|
+
let semiBold = font["semiBoldFontName"] as? String,
|
|
142
|
+
let bold = font["boldFontName"] as? String
|
|
143
|
+
{
|
|
144
|
+
branding?.font = Veriff.VeriffSdk.Branding.Font(regularFontName: regular, lightFontName: light, semiBoldFontName: semiBold, boldFontName: bold)
|
|
145
|
+
}
|
|
100
146
|
}
|
|
101
147
|
|
|
102
148
|
if let sUrl = configuration[VeriffSdk.SESSION_URL] as? String {
|
|
@@ -212,3 +258,25 @@ extension VeriffSdk: VeriffSdkDelegate {
|
|
|
212
258
|
self.resolve?(resultDict)
|
|
213
259
|
}
|
|
214
260
|
}
|
|
261
|
+
|
|
262
|
+
private extension Dictionary where Key == String, Value == Any {
|
|
263
|
+
func image(for key: String) -> Any? {
|
|
264
|
+
let imageProvider = VeriffSdkImageProvider(imageSource: self[key])
|
|
265
|
+
if
|
|
266
|
+
let imageDict = self[key] as? [String: AnyObject],
|
|
267
|
+
let urlString = imageDict["uri"] as? String,
|
|
268
|
+
let url = URL(string: urlString),
|
|
269
|
+
!url.isFileURL,
|
|
270
|
+
let data = try? Data(contentsOf: url)
|
|
271
|
+
{
|
|
272
|
+
return UIImage(data: data)
|
|
273
|
+
} else {
|
|
274
|
+
return imageProvider.loadLocalAsset()
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
mutating func addValue(_ value: Any?, for key: String) {
|
|
279
|
+
guard let value = value else { return }
|
|
280
|
+
self[key] = value
|
|
281
|
+
}
|
|
282
|
+
}
|
|
@@ -4,15 +4,15 @@ import UIKit.UIImage
|
|
|
4
4
|
|
|
5
5
|
@objc(VeriffSdkImageProvider)
|
|
6
6
|
final class VeriffSdkImageProvider: NSObject {
|
|
7
|
-
private let
|
|
7
|
+
private let imageSource: Any?
|
|
8
8
|
|
|
9
|
-
init(
|
|
10
|
-
self.
|
|
9
|
+
init(imageSource: Any?) {
|
|
10
|
+
self.imageSource = imageSource
|
|
11
11
|
super.init()
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
func loadLocalAsset() -> UIImage? {
|
|
15
|
-
if let imageURI =
|
|
15
|
+
if let imageURI = imageSource {
|
|
16
16
|
if let imageDict = imageURI as? [String: AnyObject],
|
|
17
17
|
let urlString = imageDict["uri"] as? String {
|
|
18
18
|
if let url = URL(string: urlString),
|
|
@@ -26,9 +26,7 @@ final class VeriffSdkImageProvider: NSObject {
|
|
|
26
26
|
return UIImage(named: imageKey)
|
|
27
27
|
}
|
|
28
28
|
} else {
|
|
29
|
-
|
|
30
|
-
let image = (imageKey as? String).flatMap { UIImage(named: $0) }
|
|
31
|
-
return image
|
|
29
|
+
return UIImage()
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@veriff/react-native-sdk",
|
|
3
3
|
"title": "React Native Veriff SDK",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.10.0",
|
|
5
5
|
"description": "React Native SDK for Veriff identity verification",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"scripts": {
|
|
@@ -25,13 +25,35 @@
|
|
|
25
25
|
"licenseFilename": "LICENSE",
|
|
26
26
|
"readmeFilename": "README.md",
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"react": "
|
|
29
|
-
"react-native": "
|
|
28
|
+
"react": "*",
|
|
29
|
+
"react-native": "*"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"react": "
|
|
33
|
-
"react-native": "
|
|
34
|
-
"@react-native-community/eslint-config": "^
|
|
35
|
-
"eslint": "^
|
|
32
|
+
"react": "18.1.0",
|
|
33
|
+
"react-native": "0.68.1",
|
|
34
|
+
"@react-native-community/eslint-config": "^3.0.1",
|
|
35
|
+
"eslint": "^7.0.0"
|
|
36
|
+
},
|
|
37
|
+
"resolutions": {
|
|
38
|
+
"ansi-regex": "^5.0.1",
|
|
39
|
+
"minimist": "^0.2.1",
|
|
40
|
+
"lodash": "^4.17.21",
|
|
41
|
+
"ua-parser-js": "^0.7.24",
|
|
42
|
+
"path-parse": "^1.0.7",
|
|
43
|
+
"tmpl": "^1.0.5",
|
|
44
|
+
"node-fetch": "^2.6.7",
|
|
45
|
+
"plist": "^3.0.4",
|
|
46
|
+
"ajv": "^6.12.3"
|
|
47
|
+
},
|
|
48
|
+
"resolutionComments": {
|
|
49
|
+
"ansi-regex": "Resolving to 5.0.1 to fix vulnerability (https://github.com/advisories/GHSA-93q8-gq69-wqmw)",
|
|
50
|
+
"minimist": "Resolving to 0.2.1 to fix vulnerability (https://www.npmjs.com/advisories/1066649)",
|
|
51
|
+
"lodash": "Resolving to 4.17.21 to fix vulnerability (https://www.npmjs.com/advisories/1065397)",
|
|
52
|
+
"ua-parser-js": "Resolving to 0.7.24 to fix vulnerability (https://www.npmjs.com/advisories/1065393)",
|
|
53
|
+
"path-parse": "Resolving to 1.0.7 to fix vulnerability (https://www.npmjs.com/advisories/1064972)",
|
|
54
|
+
"tmpl": "Resolving to 1.0.5 to fix vulnerability (https://www.npmjs.com/advisories/1064907)",
|
|
55
|
+
"node-fetch": "Resolving to 2.6.7 to fix vulnerability (https://www.npmjs.com/advisories/1064646)",
|
|
56
|
+
"plist": "Resolving to 3.0.4 to fix vulnerability (https://www.npmjs.com/advisories/1064605)",
|
|
57
|
+
"ajv": "Resolving to 6.12.3 to fix vulnerability (https://www.npmjs.com/advisories/1065159)"
|
|
36
58
|
}
|
|
37
59
|
}
|