react-native-nami-sdk 1.0.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/build.gradle +12 -5
- package/android/gradle/wrapper/gradle-wrapper.properties +3 -3
- package/android/src/main/java/com/nami/reactlibrary/NamiPaywallManagerBridgeModule.kt +78 -4
- package/android/src/main/java/com/nami/reactlibrary/NamiUtil.kt +2 -3
- package/ios/NamiBridgeUtil.m +4 -0
- package/ios/NamiEmitter.m +45 -1
- package/ios/NamiPaywallManagerBridge.m +37 -1
- package/ios/Podfile +1 -1
- package/package.json +1 -1
- package/react-native-nami-sdk.podspec +1 -1
package/android/build.gradle
CHANGED
|
@@ -20,9 +20,8 @@ def safeExtGet(prop, fallback) {
|
|
|
20
20
|
apply plugin: 'com.android.library'
|
|
21
21
|
apply plugin: 'maven'
|
|
22
22
|
apply plugin: "kotlin-android"
|
|
23
|
-
apply plugin: "kotlin-android-extensions"
|
|
24
23
|
buildscript {
|
|
25
|
-
ext.kotlin_version = '1.4.
|
|
24
|
+
ext.kotlin_version = '1.4.31'
|
|
26
25
|
// The Android Gradle plugin is only required when opening the android folder stand-alone.
|
|
27
26
|
// This avoids unnecessary downloads and potential conflicts when the library is included as a
|
|
28
27
|
// module dependency in an application project.
|
|
@@ -33,7 +32,7 @@ buildscript {
|
|
|
33
32
|
jcenter()
|
|
34
33
|
}
|
|
35
34
|
dependencies {
|
|
36
|
-
classpath 'com.android.tools.build:gradle:4.1
|
|
35
|
+
classpath 'com.android.tools.build:gradle:4.2.1'
|
|
37
36
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
38
37
|
}
|
|
39
38
|
}
|
|
@@ -47,9 +46,16 @@ android {
|
|
|
47
46
|
versionCode 1
|
|
48
47
|
versionName "1.0"
|
|
49
48
|
}
|
|
49
|
+
compileOptions {
|
|
50
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
51
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
52
|
+
}
|
|
50
53
|
lintOptions {
|
|
51
54
|
abortOnError false
|
|
52
55
|
}
|
|
56
|
+
kotlinOptions {
|
|
57
|
+
jvmTarget = "1.8"
|
|
58
|
+
}
|
|
53
59
|
}
|
|
54
60
|
repositories {
|
|
55
61
|
// ref: https://www.baeldung.com/maven-local-repository
|
|
@@ -65,12 +71,13 @@ repositories {
|
|
|
65
71
|
google()
|
|
66
72
|
jcenter()
|
|
67
73
|
}
|
|
74
|
+
|
|
68
75
|
dependencies {
|
|
69
76
|
//noinspection GradleDynamicVersion
|
|
70
77
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
71
|
-
implementation "org.jetbrains.kotlin:kotlin-stdlib-
|
|
78
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
|
72
79
|
|
|
73
|
-
implementation "com.namiml:sdk-android:1.
|
|
80
|
+
implementation "com.namiml:sdk-android:1.2.1"
|
|
74
81
|
|
|
75
82
|
implementation 'com.facebook.react:react-native:+' // From node_modules
|
|
76
83
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
#Wed May 26 17:12:26 EDT 2021
|
|
2
2
|
distributionBase=GRADLE_USER_HOME
|
|
3
|
+
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip
|
|
3
4
|
distributionPath=wrapper/dists
|
|
4
|
-
zipStoreBase=GRADLE_USER_HOME
|
|
5
5
|
zipStorePath=wrapper/dists
|
|
6
|
-
|
|
6
|
+
zipStoreBase=GRADLE_USER_HOME
|
|
@@ -12,6 +12,7 @@ import com.facebook.react.bridge.ReactMethod
|
|
|
12
12
|
import com.facebook.react.bridge.WritableNativeMap
|
|
13
13
|
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
14
14
|
import com.namiml.paywall.NamiPaywallManager
|
|
15
|
+
import com.namiml.paywall.PreparePaywallResult
|
|
15
16
|
|
|
16
17
|
class NamiPaywallManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
17
18
|
ReactContextBaseJavaModule(reactContext), ActivityEventListener {
|
|
@@ -46,7 +47,7 @@ class NamiPaywallManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
fun emitBockedPaywallClosed() {
|
|
50
|
+
private fun emitBockedPaywallClosed() {
|
|
50
51
|
val map = Arguments.createMap().apply {
|
|
51
52
|
putBoolean("blockingPaywallClosed", true)
|
|
52
53
|
}
|
|
@@ -99,9 +100,6 @@ class NamiPaywallManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
99
100
|
|
|
100
101
|
@ReactMethod
|
|
101
102
|
fun canRaisePaywall(successCallback: Callback) {
|
|
102
|
-
// BOOL canRaise = [[NamiPaywallManager shared] canRaisePaywall];
|
|
103
|
-
// completion(@[[NSNumber numberWithBool:canRaise]]);
|
|
104
|
-
|
|
105
103
|
reactApplicationContext.runOnUiQueueThread {
|
|
106
104
|
val canRaiseResult = NamiPaywallManager.canRaisePaywall()
|
|
107
105
|
successCallback.invoke(canRaiseResult)
|
|
@@ -124,4 +122,80 @@ class NamiPaywallManagerBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
124
122
|
fun paywallImpression(developerPaywallID: String) {
|
|
125
123
|
// TODO: Android SDK paywall impression call.
|
|
126
124
|
}
|
|
125
|
+
|
|
126
|
+
@ReactMethod
|
|
127
|
+
fun preparePaywallForDisplay(backgroundImageRequired: Boolean, imageFetchTimeout: Double) {
|
|
128
|
+
val imageFetchTimeoutConvertedToLong: Long = imageFetchTimeout.toLong()
|
|
129
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
130
|
+
|
|
131
|
+
NamiPaywallManager.preparePaywallForDisplay(
|
|
132
|
+
backgroundImageRequired,
|
|
133
|
+
imageFetchTimeoutConvertedToLong
|
|
134
|
+
) { result ->
|
|
135
|
+
when (result) {
|
|
136
|
+
is PreparePaywallResult.Success -> {
|
|
137
|
+
emitPreparePaywallFinished(true, null, null)
|
|
138
|
+
}
|
|
139
|
+
is PreparePaywallResult.Failure -> {
|
|
140
|
+
emitPreparePaywallFinished(false, null, result.error)
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
@ReactMethod
|
|
148
|
+
fun preparePaywallForDisplayByDeveloperPaywallId(
|
|
149
|
+
developerPaywallID: String,
|
|
150
|
+
backgroundImageRequired: Boolean,
|
|
151
|
+
imageFetchTimeout: Double
|
|
152
|
+
) {
|
|
153
|
+
val imageFetchTimeoutConvertedToLong: Long = imageFetchTimeout.toLong()
|
|
154
|
+
reactApplicationContext.runOnUiQueueThread {
|
|
155
|
+
NamiPaywallManager.preparePaywallForDisplay(
|
|
156
|
+
developerPaywallID,
|
|
157
|
+
backgroundImageRequired,
|
|
158
|
+
imageFetchTimeoutConvertedToLong
|
|
159
|
+
) { result ->
|
|
160
|
+
when (result) {
|
|
161
|
+
is PreparePaywallResult.Success -> {
|
|
162
|
+
emitPreparePaywallFinished(true, developerPaywallID, null)
|
|
163
|
+
}
|
|
164
|
+
is PreparePaywallResult.Failure -> {
|
|
165
|
+
emitPreparePaywallFinished(false, developerPaywallID, result.error)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private fun emitPreparePaywallFinished(
|
|
173
|
+
success: Boolean,
|
|
174
|
+
developerPaywallID: String?,
|
|
175
|
+
error: com.namiml.paywall.PreparePaywallError?
|
|
176
|
+
) {
|
|
177
|
+
val prepareContentMap = Arguments.createMap()
|
|
178
|
+
prepareContentMap.putBoolean("success", success)
|
|
179
|
+
|
|
180
|
+
if (developerPaywallID != null) {
|
|
181
|
+
prepareContentMap.putString("developerPaywallID", developerPaywallID)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (error != null) {
|
|
185
|
+
prepareContentMap.putInt("errorCode", error.ordinal)
|
|
186
|
+
prepareContentMap.putString("errorMessage", error.toString())
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
Log.i(
|
|
190
|
+
LOG_TAG,
|
|
191
|
+
"Emitting preparePaywallForDisplay finished with result " + success + "error: " + error.toString()
|
|
192
|
+
)
|
|
193
|
+
try {
|
|
194
|
+
reactApplicationContext
|
|
195
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
196
|
+
.emit("PreparePaywallFinished", prepareContentMap)
|
|
197
|
+
} catch (e: Exception) {
|
|
198
|
+
Log.e(LOG_TAG, "Caught Exception: " + e.message)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
127
201
|
}
|
|
@@ -196,6 +196,8 @@ fun NamiSKU.toSkuDict(): WritableMap {
|
|
|
196
196
|
productDict.putString("localizedDescription", skuDetails.description)
|
|
197
197
|
productDict.putString("localizedPrice", skuDetails.price)
|
|
198
198
|
productDict.putString("localizedMultipliedPrice", skuDetails.price)
|
|
199
|
+
productDict.putString("displayText", displayText)
|
|
200
|
+
productDict.putString("displaySubText", displaySubText)
|
|
199
201
|
productDict.putString("price", skuDetails.getFormattedPrice().toString())
|
|
200
202
|
productDict.putString("priceLanguage", Locale.getDefault().language)
|
|
201
203
|
productDict.putString("priceCountry", Locale.getDefault().country)
|
|
@@ -208,9 +210,6 @@ fun NamiSKU.toSkuDict(): WritableMap {
|
|
|
208
210
|
SubscriptionPeriod.HALF_YEAR -> {
|
|
209
211
|
"half_year"
|
|
210
212
|
}
|
|
211
|
-
SubscriptionPeriod.DAY -> {
|
|
212
|
-
"day"
|
|
213
|
-
}
|
|
214
213
|
SubscriptionPeriod.WEEKLY -> {
|
|
215
214
|
"week"
|
|
216
215
|
}
|
package/ios/NamiBridgeUtil.m
CHANGED
|
@@ -28,6 +28,10 @@
|
|
|
28
28
|
productDict[@"priceLanguage"] = productInt.priceLocale.languageCode;
|
|
29
29
|
productDict[@"priceCountry"] = productInt.priceLocale.countryCode;
|
|
30
30
|
productDict[@"priceCurrency"] = productInt.priceLocale.currencyCode;
|
|
31
|
+
|
|
32
|
+
// Add smart text processed values for sku buttons to sku dictionary
|
|
33
|
+
productDict[@"displayText"] = [sku namiDisplayText];
|
|
34
|
+
productDict[@"displaySubText"] = [sku namiSubDisplayText];
|
|
31
35
|
|
|
32
36
|
if (@available(iOS 12.0, *)) {
|
|
33
37
|
if (productInt != nil && productInt.subscriptionGroupIdentifier != nil) {
|
package/ios/NamiEmitter.m
CHANGED
|
@@ -23,6 +23,8 @@ RCT_EXTERN_METHOD(allPurchasedProducts)
|
|
|
23
23
|
RCT_EXTERN_METHOD(getPurchasedProducts: (RCTResponseSenderBlock)callback)
|
|
24
24
|
@end
|
|
25
25
|
|
|
26
|
+
static NamiEmitter *namiEmitter;
|
|
27
|
+
|
|
26
28
|
@implementation NamiEmitter : RCTEventEmitter
|
|
27
29
|
|
|
28
30
|
- (instancetype)init
|
|
@@ -54,9 +56,19 @@ RCT_EXTERN_METHOD(getPurchasedProducts: (RCTResponseSenderBlock)callback)
|
|
|
54
56
|
}];
|
|
55
57
|
|
|
56
58
|
}
|
|
59
|
+
namiEmitter = self;
|
|
57
60
|
return self;
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
- (void)dealloc {
|
|
64
|
+
namiEmitter = nil;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
+ (NamiEmitter *) reactInstance {
|
|
69
|
+
return namiEmitter;
|
|
70
|
+
}
|
|
71
|
+
|
|
60
72
|
- (void) getPurchasedProducts : (RCTResponseSenderBlock) callback {
|
|
61
73
|
NSArray *allProducts = [self allPurchasedProducts];
|
|
62
74
|
callback(allProducts);
|
|
@@ -77,7 +89,7 @@ RCT_EXTERN_METHOD(getPurchasedProducts: (RCTResponseSenderBlock)callback)
|
|
|
77
89
|
}
|
|
78
90
|
|
|
79
91
|
- (NSArray<NSString *> *)supportedEvents {
|
|
80
|
-
return @[@"PurchasesChanged", @"SignInActivate", @"AppPaywallActivate", @"EntitlementsChanged", @"BlockingPaywallClosed" ];
|
|
92
|
+
return @[@"PurchasesChanged", @"SignInActivate", @"AppPaywallActivate", @"EntitlementsChanged", @"BlockingPaywallClosed", @"PreparePaywallFinished" ];
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
- (NSDictionary<NSString *, NSObject *> *)constantsToExport {
|
|
@@ -150,6 +162,30 @@ bool hasNamiEmitterListeners;
|
|
|
150
162
|
}
|
|
151
163
|
}
|
|
152
164
|
|
|
165
|
+
- (void)sendEventPreparePaywallForDisplayFinishedWithResult:(BOOL)success developerPaywallID: (NSString * _Nullable) developerPaywallID error:(NSError * _Nullable) error {
|
|
166
|
+
if (hasNamiEmitterListeners) {
|
|
167
|
+
|
|
168
|
+
NSMutableDictionary *sendDict = [NSMutableDictionary dictionaryWithDictionary: @{ @"success": @(success) }];
|
|
169
|
+
|
|
170
|
+
if (developerPaywallID != nil) {
|
|
171
|
+
[sendDict addEntriesFromDictionary:@{
|
|
172
|
+
@"developerPaywallID": developerPaywallID
|
|
173
|
+
}];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (error != nil) {
|
|
177
|
+
[sendDict addEntriesFromDictionary:@{
|
|
178
|
+
@"errorCode": @(error.code),
|
|
179
|
+
@"errorMessage": [error localizedDescription]
|
|
180
|
+
}
|
|
181
|
+
];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
NSLog(@"NamiBridge: Info: attempting to send result of preparePaywallForDisplay with result dictionary: %@", sendDict);
|
|
185
|
+
[self sendEventWithName:@"PreparePaywallFinished" body:sendDict];
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
153
189
|
- (void)sendEventPurchaseMadeWithPurchases:(NSArray<NamiPurchase *>*)purchases withState:(NamiPurchaseState)purchaseState error:(NSError *)error {
|
|
154
190
|
if (hasNamiEmitterListeners) {
|
|
155
191
|
|
|
@@ -200,6 +236,14 @@ bool hasNamiEmitterListeners;
|
|
|
200
236
|
NSMutableDictionary *paywallMeta = [NSMutableDictionary dictionaryWithDictionary:paywallMetadata.namiPaywallInfoDict];
|
|
201
237
|
// This part is really meant to be internally facing, scrub from dictionary
|
|
202
238
|
|
|
239
|
+
NSMutableDictionary *marketingContentDictionary = [NSMutableDictionary dictionaryWithDictionary:paywallMeta[@"marketing_content"]];
|
|
240
|
+
|
|
241
|
+
// Populated SmartText formatted values in dictioanry to send
|
|
242
|
+
marketingContentDictionary[@"body"] = [paywallMetadata body];
|
|
243
|
+
marketingContentDictionary[@"title"] = [paywallMetadata title];
|
|
244
|
+
paywallMeta[@"marketing_content"] = marketingContentDictionary;
|
|
245
|
+
paywallMeta[@"purchase_terms"] = [paywallMetadata purchaseTerms];
|
|
246
|
+
|
|
203
247
|
// Strip out presention_position from all listed sku items
|
|
204
248
|
NSArray *cleanedOrderdMetadata = [NamiBridgeUtil stripPresentationPositionFromOrderedMetadataForPaywallMetaDict:paywallMeta];
|
|
205
249
|
[paywallMeta setObject:cleanedOrderdMetadata forKey:@"formatted_skus"];
|
|
@@ -15,7 +15,10 @@
|
|
|
15
15
|
|
|
16
16
|
#import "React/RCTViewManager.h"
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
@interface NamiEmitter : RCTEventEmitter
|
|
19
|
+
- (void)sendEventPreparePaywallForDisplayFinishedWithResult:(BOOL)success developerPaywallID: (NSString * _Nullable) developerPaywallID error:(NSError * _Nullable) error;
|
|
20
|
+
+ (NamiEmitter *) reactInstance;
|
|
21
|
+
@end
|
|
19
22
|
|
|
20
23
|
@interface NamiPaywallManagerBridge : NSObject <RCTBridgeModule>
|
|
21
24
|
@property (atomic) BOOL blockPaywallRaise;
|
|
@@ -58,6 +61,7 @@ RCT_EXPORT_METHOD(canRaisePaywall:(RCTResponseSenderBlock)completion)
|
|
|
58
61
|
completion(@[[NSNumber numberWithBool:canRaise]]);
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
|
|
61
65
|
RCT_EXPORT_METHOD(presentNamiPaywall:(NSArray *)skuIDs metapaywallDefinition:(NSDictionary *)paywallDict)
|
|
62
66
|
{
|
|
63
67
|
NSString *paywallDeveloperID = paywallDict[@"developerPaywallID"];
|
|
@@ -104,6 +108,38 @@ RCT_EXPORT_METHOD(paywallImpression:(NSString *)developerPaywallID)
|
|
|
104
108
|
[NamiPaywallManager paywallImpressionWithDeveloperID:developerPaywallID];
|
|
105
109
|
}
|
|
106
110
|
|
|
111
|
+
RCT_EXPORT_METHOD( preparePaywallForDisplay:(BOOL)backgroundImageRequired
|
|
112
|
+
imageFetchTimeout:(double)imageFetchTimeout )
|
|
113
|
+
{
|
|
114
|
+
[NamiPaywallManager preparePaywallForDisplayWithBackgroundImageRequired:backgroundImageRequired imageFetchTimeout:imageFetchTimeout prepareHandler:^(BOOL success, NSError * _Nullable error) {
|
|
115
|
+
[[NamiEmitter reactInstance] sendEventPreparePaywallForDisplayFinishedWithResult:success developerPaywallID:nil error:error];
|
|
116
|
+
}];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
RCT_EXPORT_METHOD(preparePaywallForDisplayByDeveloperPaywallId:(NSString *)developerPaywallID
|
|
120
|
+
backgroundImageRequired: (BOOL)backgroundImageRequired
|
|
121
|
+
imageFetchTimeout:(double)imageFetchTimeout )
|
|
122
|
+
{
|
|
123
|
+
[NamiPaywallManager preparePaywallForDisplayWithDeveloperPaywallID:developerPaywallID backgroundImageRequired:backgroundImageRequired imageFetchTimeout:imageFetchTimeout prepareHandler:^(BOOL success, NSError * _Nullable error) {
|
|
124
|
+
[[NamiEmitter reactInstance] sendEventPreparePaywallForDisplayFinishedWithResult:success developerPaywallID:developerPaywallID error:error];
|
|
125
|
+
}];
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
RCT_EXPORT_METHOD(processSmartTextForProducts:(NSString *)smartText skuIDs:(NSArray<NSString *> *)skuIDs completion:(RCTResponseSenderBlock)completion)
|
|
130
|
+
{
|
|
131
|
+
[NamiPurchaseManager skusForSKUIDsWithSkuIDs:skuIDs productHandler:^(BOOL success, NSArray<NamiSKU *> * _Nullable skus, NSArray<NSString *> * _Nullable invalidSkuIDs, NSError * _Nullable error) {
|
|
132
|
+
if (skus != NULL) {
|
|
133
|
+
// Found some of the skus they were looking for, process text
|
|
134
|
+
NSString *processedText = [NamiPaywallManager processSmartTextWithText:smartText dataStores:skus];
|
|
135
|
+
completion(@[processedText]);
|
|
136
|
+
} else {
|
|
137
|
+
// No products found so cannot process smart text, just send back.
|
|
138
|
+
completion(@[smartText]);
|
|
139
|
+
}
|
|
140
|
+
}];
|
|
141
|
+
}
|
|
142
|
+
|
|
107
143
|
|
|
108
144
|
@end
|
|
109
145
|
|
package/ios/Podfile
CHANGED
|
@@ -5,7 +5,7 @@ source 'https://cdn.cocoapods.org/'
|
|
|
5
5
|
|
|
6
6
|
target 'RNNami' do
|
|
7
7
|
# Pods for RNNami
|
|
8
|
-
pod 'Nami', '2.
|
|
8
|
+
pod 'Nami', '2.7.1'
|
|
9
9
|
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
|
|
10
10
|
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
|
|
11
11
|
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
|
package/package.json
CHANGED