react-native-nami-sdk 2.0.5 → 3.0.8
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/.github/workflows/app_stg.yaml +203 -0
- package/.pre-commit-config.yaml +1 -1
- package/android/build.gradle +24 -13
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -1
- package/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt +6 -50
- package/android/src/main/java/com/nami/reactlibrary/NamiBridgePackage.java +1 -0
- package/android/src/main/java/com/nami/reactlibrary/NamiCampaignManagerBridge.kt +133 -0
- package/android/src/main/java/com/nami/reactlibrary/NamiCustomerManagerBridge.kt +88 -19
- package/android/src/main/java/com/nami/reactlibrary/NamiEmitter.kt +24 -24
- package/android/src/main/java/com/nami/reactlibrary/NamiEntitlementManagerBridgeModule.kt +30 -129
- package/android/src/main/java/com/nami/reactlibrary/NamiPaywallManagerBridgeModule.kt +36 -147
- package/android/src/main/java/com/nami/reactlibrary/NamiPurchaseManagerBridge.kt +36 -38
- package/android/src/main/java/com/nami/reactlibrary/NamiUtil.kt +50 -180
- package/build-utils/get_version_code.py +140 -0
- package/index.d.ts +20 -0
- package/index.js +7 -6
- package/ios/Nami.m +9 -63
- package/ios/NamiBridgeUtil.h +4 -6
- package/ios/NamiBridgeUtil.m +16 -78
- package/ios/NamiCampaignManagerBridge.m +26 -0
- package/ios/NamiCampaignManagerBridge.swift +107 -0
- package/ios/NamiCustomerManager.m +18 -23
- package/ios/NamiCustomerManager.swift +122 -0
- package/ios/NamiEmitter.m +55 -65
- package/ios/NamiEntitlementManagerBridge.m +7 -107
- package/ios/NamiEntitlementManagerBridge.swift +74 -0
- package/ios/NamiMLManagerBridge.m +2 -2
- package/ios/NamiPaywallManagerBridge.m +22 -94
- package/ios/NamiPaywallManagerBridge.swift +93 -0
- package/ios/NamiPurchaseManagerBridge.m +38 -69
- package/ios/NamiPurchaseManagerBridge.swift +174 -0
- package/ios/Podfile +2 -2
- package/ios/RNNami-Bridging-Header.h +5 -0
- package/ios/RNNami.h +0 -1
- package/ios/RNNami.m +1 -1
- package/ios/RNNami.xcodeproj/project.pbxproj +84 -8
- package/ios/RNNami.xcodeproj/xcshareddata/xcschemes/RNNami.xcscheme +67 -0
- package/package.json +1 -1
- package/react-native-nami-sdk.podspec +3 -3
- package/src/Nami.d.ts +112 -0
- package/src/Nami.js +10 -0
- package/src/NamiCampaignManager.d.ts +54 -0
- package/src/NamiCampaignManager.js +43 -0
- package/src/NamiCustomerManager.d.ts +39 -0
- package/src/NamiCustomerManager.js +43 -0
- package/src/NamiEntitlementManager.d.ts +24 -0
- package/src/NamiEntitlementManager.js +23 -0
- package/src/NamiMLManager.d.ts +5 -0
- package/src/NamiMLManager.js +7 -0
- package/src/NamiPaywallManager.d.ts +57 -0
- package/src/NamiPaywallManager.js +28 -0
- package/src/NamiPurchaseManager.d.ts +57 -0
- package/src/NamiPurchaseManager.js +37 -0
- package/src/types.ts +36 -0
- package/android/src/main/java/com/nami/reactlibrary/NamiAnalyticsEmitter.kt +0 -121
- package/ios/NamiAnalyticsEmitter.m +0 -146
package/ios/NamiEmitter.m
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
// NamiEmitter.m
|
|
3
3
|
// namiReactNative
|
|
4
4
|
//
|
|
5
|
-
// Created by Kendall Helmstetter Gelner on 12/11/19.
|
|
6
5
|
// Copyright © 2019 Nami ML Inc. All rights reserved.
|
|
7
6
|
//
|
|
8
7
|
|
|
9
8
|
#import <Foundation/Foundation.h>
|
|
10
9
|
|
|
11
|
-
#import <
|
|
10
|
+
#import <NamiApple/NamiApple.h>
|
|
12
11
|
|
|
13
12
|
#import <React/RCTBridgeModule.h>
|
|
14
13
|
#import <React/RCTEventEmitter.h>
|
|
@@ -38,31 +37,25 @@ static NamiEmitter *namiEmitter;
|
|
|
38
37
|
[self sendEventPurchaseMadeWithPurchases:purchases withState:purchaseState error:error];
|
|
39
38
|
}];
|
|
40
39
|
|
|
41
|
-
[NamiEntitlementManager
|
|
40
|
+
[NamiEntitlementManager registerActiveEntitlementsHandler:^(NSArray<NamiEntitlement *> * _Nonnull entitlements) {
|
|
42
41
|
[self sendEventEntitlementsChangedWithEntitlements:entitlements];
|
|
43
42
|
}];
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
[self sendSignInActivateFromVC:fromVC forPaywall:developerPaywallID paywallMetadata:paywallMetadata];
|
|
48
|
-
}];
|
|
49
|
-
|
|
50
|
-
[NamiPaywallManager registerPaywallRaiseHandler:^(UIViewController * _Nullable fromVC, NSArray<NamiSKU *> * _Nullable products, NSString * _Nonnull developerPaywallID, NamiPaywall * _Nonnull paywallMetadata) {
|
|
51
|
-
[self sendPaywallActivatedFromVC:fromVC forPaywall:developerPaywallID withProducts:products paywallMetadata:paywallMetadata];
|
|
44
|
+
[NamiPaywallManager registerSignInHandler:^(UIViewController * _Nullable fromVC) {
|
|
45
|
+
[self sendSignInActivateFromVC:fromVC];
|
|
52
46
|
}];
|
|
53
47
|
|
|
54
|
-
[NamiPaywallManager
|
|
55
|
-
[self sendBlockingPaywallClosed];
|
|
56
|
-
}];
|
|
48
|
+
// [NamiPaywallManager registerCloseHandler:^(UIViewController * _Nullable fromVC) {
|
|
49
|
+
// [self sendBlockingPaywallClosed];
|
|
50
|
+
// }];
|
|
57
51
|
|
|
58
52
|
[NamiPurchaseManager registerRestorePurchasesHandlerWithRestorePurchasesStateHandler:^(enum NamiRestorePurchasesState state, NSArray<NamiPurchase *> * _Nonnull newPurchases, NSArray<NamiPurchase *> * _Nonnull oldPurchases, NSError * _Nullable error) {
|
|
59
53
|
[self sendRestorePurchasesStateChanged:state newPurchases:newPurchases oldPurchases:oldPurchases error:error];
|
|
60
54
|
}];
|
|
61
55
|
|
|
62
|
-
[NamiCustomerManager
|
|
56
|
+
[NamiCustomerManager registerJourneyStateHandler:^(CustomerJourneyState * _Nonnull journeyState) {
|
|
63
57
|
[self sendEventCustomerJourneyStateChanged:journeyState];
|
|
64
58
|
}];
|
|
65
|
-
|
|
66
59
|
}
|
|
67
60
|
namiEmitter = self;
|
|
68
61
|
return self;
|
|
@@ -86,7 +79,7 @@ static NamiEmitter *namiEmitter;
|
|
|
86
79
|
NSArray<NamiPurchase *> *purchases = NamiPurchaseManager.allPurchases;
|
|
87
80
|
NSMutableArray<NSString *> *productIDs = [NSMutableArray new];
|
|
88
81
|
for (NamiPurchase *purchase in purchases) {
|
|
89
|
-
[productIDs addObject:purchase.
|
|
82
|
+
[productIDs addObject:purchase.skuId];
|
|
90
83
|
}
|
|
91
84
|
|
|
92
85
|
return productIDs;
|
|
@@ -157,7 +150,7 @@ bool hasNamiEmitterListeners;
|
|
|
157
150
|
|
|
158
151
|
NSMutableArray *convertedEntitlementDicts = [NSMutableArray new];
|
|
159
152
|
for ( NamiEntitlement *entitlementRecord in entitlements ) {
|
|
160
|
-
if ( entitlementRecord.
|
|
153
|
+
if ( entitlementRecord.referenceId != nil ) {
|
|
161
154
|
NSDictionary *entitlementDict = [NamiBridgeUtil entitlementToEntitlementDict:entitlementRecord];
|
|
162
155
|
[convertedEntitlementDicts addObject:entitlementDict];
|
|
163
156
|
}
|
|
@@ -209,7 +202,7 @@ bool hasNamiEmitterListeners;
|
|
|
209
202
|
|
|
210
203
|
NSMutableArray *convertedPurchaseDicts = [NSMutableArray new];
|
|
211
204
|
for ( NamiPurchase *purchaseRecord in purchases ) {
|
|
212
|
-
if ( purchaseRecord.
|
|
205
|
+
if ( purchaseRecord.skuId != nil ) {
|
|
213
206
|
NSDictionary *purchaseDict = [NamiBridgeUtil purchaseToPurchaseDict:purchaseRecord];
|
|
214
207
|
[convertedPurchaseDicts addObject:purchaseDict];
|
|
215
208
|
}
|
|
@@ -229,56 +222,53 @@ bool hasNamiEmitterListeners;
|
|
|
229
222
|
}
|
|
230
223
|
|
|
231
224
|
|
|
232
|
-
- (void) sendSignInActivateFromVC:(UIViewController * _Nullable) fromVC
|
|
233
|
-
forPaywall:(NSString * _Nonnull) developerPaywallID
|
|
234
|
-
paywallMetadata:(NamiPaywall * _Nonnull) paywallMetadata {
|
|
225
|
+
- (void) sendSignInActivateFromVC:(UIViewController * _Nullable) fromVC {
|
|
235
226
|
if (hasNamiEmitterListeners) {
|
|
236
227
|
// Pass along paywall ID use in sign-in provider.
|
|
237
|
-
[self sendEventWithName:@"SignInActivate" body:@{
|
|
228
|
+
[self sendEventWithName:@"SignInActivate" body:@{ }];
|
|
238
229
|
}
|
|
239
230
|
}
|
|
240
231
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
marketingContentDictionary[@"
|
|
258
|
-
|
|
259
|
-
paywallMeta[@"
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
[paywallMeta removeObjectForKey:@"
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
[paywallMeta removeObjectForKey:@"
|
|
274
|
-
[paywallMeta removeObjectForKey:@"
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
@"
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
232
|
+
//- (void)sendPaywallActivatedForPaywall:(NSString * _Nonnull) developerPaywallID
|
|
233
|
+
// withProducts:(NSArray<NamiSKU *> * _Nullable) products
|
|
234
|
+
// paywallMetadata:(NamiPaywall * _Nonnull) paywallMetadata {
|
|
235
|
+
// if (hasNamiEmitterListeners) {
|
|
236
|
+
// NSMutableArray<NSDictionary<NSString *,NSString *> *> *skuDicts = [NSMutableArray new];
|
|
237
|
+
// for (NamiSKU *sku in products) {
|
|
238
|
+
// [skuDicts addObject:[NamiBridgeUtil skuToSKUDict:sku]];
|
|
239
|
+
// }
|
|
240
|
+
//
|
|
241
|
+
// NSMutableDictionary *paywallMeta = [NSMutableDictionary dictionaryWithDictionary:paywallMetadata.namiPaywallInfoDict];
|
|
242
|
+
// // This part is really meant to be internally facing, scrub from dictionary
|
|
243
|
+
//
|
|
244
|
+
// NSMutableDictionary *marketingContentDictionary = [NSMutableDictionary dictionaryWithDictionary:paywallMeta[@"marketing_content"]];
|
|
245
|
+
//
|
|
246
|
+
// // Populated SmartText formatted values in dictioanry to send
|
|
247
|
+
// marketingContentDictionary[@"body"] = [paywallMetadata body];
|
|
248
|
+
// marketingContentDictionary[@"title"] = [paywallMetadata title];
|
|
249
|
+
// paywallMeta[@"marketing_content"] = marketingContentDictionary;
|
|
250
|
+
// paywallMeta[@"purchase_terms"] = [paywallMetadata purchaseTerms];
|
|
251
|
+
//
|
|
252
|
+
// // Strip out presention_position from all listed sku items
|
|
253
|
+
// NSArray *cleanedOrderdMetadata = [NamiBridgeUtil stripPresentationPositionFromOrderedMetadataForPaywallMetaDict:paywallMeta];
|
|
254
|
+
// [paywallMeta setObject:cleanedOrderdMetadata forKey:@"formatted_skus"];
|
|
255
|
+
//
|
|
256
|
+
// [paywallMeta removeObjectForKey:@"sku_ordered_metadata"];
|
|
257
|
+
// [paywallMeta removeObjectForKey:@"skus"];
|
|
258
|
+
//
|
|
259
|
+
// NSDictionary *paywallStylingDict = [NamiBridgeUtil paywallStylingToPaywallStylingDict:[paywallMetadata styleData]];
|
|
260
|
+
// paywallMeta[@"styleData"] = paywallStylingDict;
|
|
261
|
+
//
|
|
262
|
+
// // remove keys that are inconsistent with android
|
|
263
|
+
// [paywallMeta removeObjectForKey:@"body"];
|
|
264
|
+
// [paywallMeta removeObjectForKey:@"title"];
|
|
265
|
+
// [paywallMeta removeObjectForKey:@"style"];
|
|
266
|
+
//
|
|
267
|
+
// [self sendEventWithName:@"AppPaywallActivate" body:@{ @"namiSkus": skuDicts,
|
|
268
|
+
// @"developerPaywallID": developerPaywallID,
|
|
269
|
+
// @"paywallMetadata": paywallMeta }];
|
|
270
|
+
// }
|
|
271
|
+
//}
|
|
282
272
|
|
|
283
273
|
- (NSDictionary *)buildRestorePurchasesStateChangedDict: (enum NamiRestorePurchasesState) state
|
|
284
274
|
newPurchases: (NSArray<NamiPurchase *> * _Nonnull) newPurchases
|
|
@@ -297,7 +287,7 @@ bool hasNamiEmitterListeners;
|
|
|
297
287
|
|
|
298
288
|
NSMutableArray *newPurchaseDicts = [NSMutableArray array];
|
|
299
289
|
for ( NamiPurchase *purchaseRecord in newPurchases ) {
|
|
300
|
-
if ( purchaseRecord.
|
|
290
|
+
if ( purchaseRecord.skuId == nil ) {
|
|
301
291
|
}
|
|
302
292
|
NSDictionary *purchaseDict = [NamiBridgeUtil purchaseToPurchaseDict:purchaseRecord];
|
|
303
293
|
[newPurchaseDicts addObject:purchaseDict];
|
|
@@ -305,7 +295,7 @@ bool hasNamiEmitterListeners;
|
|
|
305
295
|
|
|
306
296
|
NSMutableArray *oldPurchaseDicts = [NSMutableArray array];
|
|
307
297
|
for ( NamiPurchase *purchaseRecord in oldPurchases ) {
|
|
308
|
-
if ( purchaseRecord.
|
|
298
|
+
if ( purchaseRecord.skuId == nil ) {
|
|
309
299
|
}
|
|
310
300
|
NSDictionary *purchaseDict = [NamiBridgeUtil purchaseToPurchaseDict:purchaseRecord];
|
|
311
301
|
[oldPurchaseDicts addObject:purchaseDict];
|
|
@@ -3,123 +3,23 @@
|
|
|
3
3
|
// RNNami
|
|
4
4
|
//
|
|
5
5
|
// Created by Kendall Gelner on 4/8/20.
|
|
6
|
-
// Copyright © 2020
|
|
6
|
+
// Copyright © 2020-2023 Nami ML Inc. All rights reserved.
|
|
7
7
|
//
|
|
8
8
|
|
|
9
|
-
#import <Foundation/Foundation.h>
|
|
10
|
-
#import <Nami/Nami.h>
|
|
11
|
-
#import "NamiBridgeUtil.h"
|
|
12
|
-
|
|
13
9
|
#import <React/RCTBridgeModule.h>
|
|
14
|
-
#import <React/RCTEventEmitter.h>
|
|
15
|
-
|
|
16
|
-
#import "React/RCTViewManager.h"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@interface NamiEntitlementManagerBridge : NSObject <RCTBridgeModule>
|
|
22
|
-
@end
|
|
23
|
-
@implementation NamiEntitlementManagerBridge (RCTExternModule)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
RCT_EXPORT_METHOD(isEntitlementActive:(nonnull NSString*)entitlementRefID completion:(RCTResponseSenderBlock)completion)
|
|
27
|
-
{
|
|
28
|
-
BOOL active = [NamiEntitlementManager isEntitlementActive:entitlementRefID];
|
|
29
|
-
NSLog(@"Checking for %@ entitlement active, result was %@", entitlementRefID, [NSNumber numberWithBool:active] );
|
|
30
|
-
completion(@[[NSNumber numberWithBool:active]]);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
RCT_EXPORT_METHOD(getEntitlements:(RCTResponseSenderBlock)completion)
|
|
35
|
-
{
|
|
36
|
-
NSArray<NamiEntitlement *> *entitlements = [NamiEntitlementManager getEntitlements];
|
|
37
|
-
|
|
38
|
-
NSMutableArray *entitlementDicts = [NSMutableArray new];
|
|
39
|
-
|
|
40
|
-
for (NamiEntitlement *entitlement in entitlements) {
|
|
41
|
-
NSDictionary *entitlementDict = [NamiBridgeUtil entitlementToEntitlementDict:entitlement];
|
|
42
|
-
if ([entitlementDict count] > 0) {
|
|
43
|
-
[entitlementDicts addObject:entitlementDict];
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
completion(@[entitlementDicts]);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
RCT_EXPORT_METHOD(activeEntitlements:(RCTResponseSenderBlock)completion)
|
|
52
|
-
{
|
|
53
|
-
NSArray<NamiEntitlement *> *entitlements = [NamiEntitlementManager activeEntitlements];
|
|
54
10
|
|
|
55
|
-
|
|
11
|
+
@interface RCT_EXTERN_MODULE(RNNamiEntitlementManager, NSObject)
|
|
56
12
|
|
|
57
|
-
|
|
58
|
-
NSDictionary *entitlementDict = [NamiBridgeUtil entitlementToEntitlementDict:entitlement];
|
|
59
|
-
if ([entitlementDict count] > 0) {
|
|
60
|
-
[entitlementDicts addObject:entitlementDict];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
13
|
+
RCT_EXTERN_METHOD(isEntitlementActive:(nullable NSString *)referenceId resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
63
14
|
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
RCT_EXPORT_METHOD(setEntitlements:(NSArray *)entitlementSetterDicts)
|
|
68
|
-
{
|
|
69
|
-
|
|
70
|
-
NSMutableArray<NamiEntitlementSetter *> *entitlementSetters = [NSMutableArray array];
|
|
71
|
-
|
|
72
|
-
for (NSDictionary *entitlementSetterDict in entitlementSetterDicts) {
|
|
73
|
-
NSString *referenceID = entitlementSetterDict[@"referenceID"];
|
|
74
|
-
NSLog(@"Entitlement to set, referenceID is %@, whole entitlement %@", referenceID, entitlementSetterDict);
|
|
75
|
-
if (referenceID != NULL && [referenceID length] > 0) {
|
|
76
|
-
NSString *purchasedSKUid = entitlementSetterDict[@"purchasedSKUid"];
|
|
77
|
-
NSString *expiresStr = entitlementSetterDict[@"expires"];
|
|
78
|
-
// TODO: figure out reverse parsing of date string passed in
|
|
79
|
-
NSDate* expires = NULL;
|
|
80
|
-
|
|
81
|
-
NSString *platormStr = entitlementSetterDict[@"platform"];
|
|
82
|
-
|
|
83
|
-
NamiPlatformType platform = NamiPlatformTypeOther;
|
|
84
|
-
if ([platormStr isEqualToString:@"android"]) {
|
|
85
|
-
platform = NamiPlatformTypeAndroid;
|
|
86
|
-
} else if ([platormStr isEqualToString:@"apple"]) {
|
|
87
|
-
platform = NamiPlatformTypeApple;
|
|
88
|
-
} else if ([platormStr isEqualToString:@"roku"]) {
|
|
89
|
-
platform = NamiPlatformTypeRoku;
|
|
90
|
-
} else if ([platormStr isEqualToString:@"web"]) {
|
|
91
|
-
platform = NamiPlatformTypeWeb;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
NamiEntitlementSetter *setter = [NamiEntitlementSetter alloc];
|
|
95
|
-
setter = [setter initWithId:referenceID platform:platform purchasedSKUid:purchasedSKUid expires:expires];
|
|
96
|
-
|
|
97
|
-
[entitlementSetters addObject:setter];
|
|
98
|
-
} else {
|
|
99
|
-
NSLog(@"Warning, entitlement to set had empty referenceID, whole entitlement is \n %@", entitlementSetterDict);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
[NamiEntitlementManager setEntitlements:entitlementSetters];
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
RCT_EXPORT_METHOD(clearAllEntitlements) {
|
|
107
|
-
[NamiEntitlementManager clearAllEntitlements];
|
|
108
|
-
}
|
|
15
|
+
RCT_EXTERN_METHOD(active:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
109
16
|
|
|
17
|
+
RCT_EXTERN_METHOD(refresh)
|
|
110
18
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
@implementation NamiEntitlementManagerBridge
|
|
115
|
-
RCT_EXPORT_MODULE_NO_LOAD(NamiEntitlementManagerBridge, NamiEntitlementManagerBridge)
|
|
116
|
-
|
|
117
|
-
- (dispatch_queue_t)methodQueue
|
|
118
|
-
{
|
|
119
|
-
return dispatch_get_main_queue();
|
|
120
|
-
}
|
|
19
|
+
RCT_EXTERN_METHOD(registerActiveEntitlementsHandler)
|
|
121
20
|
|
|
122
21
|
+ (BOOL)requiresMainQueueSetup {
|
|
123
22
|
return YES;
|
|
124
23
|
}
|
|
24
|
+
|
|
125
25
|
@end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NamiEntitlementManagerBridge.swift
|
|
3
|
+
// RNNami
|
|
4
|
+
//
|
|
5
|
+
// Copyright © 2023 Nami ML Inc.. All rights reserved.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import NamiApple
|
|
10
|
+
import React
|
|
11
|
+
|
|
12
|
+
@objc(RNNamiEntitlementManager)
|
|
13
|
+
class RNNamiEntitlementManager: RCTEventEmitter {
|
|
14
|
+
override func supportedEvents() -> [String]! {
|
|
15
|
+
return ["EntitlementsChanged"]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
private func entitlementInToDictionary(_ entitlement: NamiEntitlement) -> NSDictionary {
|
|
19
|
+
let activePurchasesDict: [NSDictionary] = entitlement.activePurchases.map { purchase in
|
|
20
|
+
let dictionary = RNNamiPurchaseManager.purchaseToPurchaseDict(purchase)
|
|
21
|
+
return dictionary
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let purchasedSkusDict: [NSDictionary] = entitlement.purchasedSkus.map { sku in
|
|
25
|
+
let dictionary = RNNamiPurchaseManager.skuToSKUDict(sku)
|
|
26
|
+
return dictionary
|
|
27
|
+
}
|
|
28
|
+
let relatedSkusDict: [NSDictionary] = entitlement.relatedSkus.map { sku in
|
|
29
|
+
let dictionary = RNNamiPurchaseManager.skuToSKUDict(sku)
|
|
30
|
+
return dictionary
|
|
31
|
+
}
|
|
32
|
+
let dictionary: [String: Any?] = [
|
|
33
|
+
"name": entitlement.name,
|
|
34
|
+
"desc": entitlement.desc,
|
|
35
|
+
"namiId": entitlement.namiId,
|
|
36
|
+
"referenceId": entitlement.referenceId,
|
|
37
|
+
"activePurchases": activePurchasesDict,
|
|
38
|
+
"relatedSkus": relatedSkusDict,
|
|
39
|
+
"purchasedSkus": purchasedSkusDict,
|
|
40
|
+
]
|
|
41
|
+
return NSDictionary(dictionary: dictionary.compactMapValues { $0 })
|
|
42
|
+
}
|
|
43
|
+
@objc(isEntitlementActive:resolver:rejecter:)
|
|
44
|
+
func isEntitlementActive(referenceId: String, resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) {
|
|
45
|
+
let isEntitlementActive = NamiEntitlementManager.isEntitlementActive(referenceId)
|
|
46
|
+
resolve(isEntitlementActive)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@objc(active:rejecter:)
|
|
50
|
+
func active(resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) {
|
|
51
|
+
let entitlements = NamiEntitlementManager.active()
|
|
52
|
+
let dictionaries: [NSDictionary] = entitlements.map { entitlement in
|
|
53
|
+
let dictionary = self.entitlementInToDictionary(entitlement)
|
|
54
|
+
return dictionary
|
|
55
|
+
}
|
|
56
|
+
resolve(dictionaries)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@objc(refresh)
|
|
60
|
+
func refresh() {
|
|
61
|
+
NamiEntitlementManager.refresh()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@objc(registerActiveEntitlementsHandler)
|
|
65
|
+
func registerActiveEntitlementsHandler() {
|
|
66
|
+
NamiEntitlementManager.registerActiveEntitlementsHandler { activeEntitlements in
|
|
67
|
+
let dictionaries: [NSDictionary] = activeEntitlements.map { entitlement in
|
|
68
|
+
let dictionary = self.entitlementInToDictionary(entitlement)
|
|
69
|
+
return dictionary
|
|
70
|
+
}
|
|
71
|
+
self.sendEvent(withName: "EntitlementsChanged", body: dictionaries)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
// RNNami
|
|
4
4
|
//
|
|
5
5
|
// Created by Kendall Gelner on 4/6/20.
|
|
6
|
-
// Copyright © 2020
|
|
6
|
+
// Copyright © 2020-2023 Nami ML Inc. All rights reserved.
|
|
7
7
|
//
|
|
8
8
|
#import <Foundation/Foundation.h>
|
|
9
|
-
#import <
|
|
9
|
+
#import <NamiApple/NamiApple.h>
|
|
10
10
|
#import "NamiBridgeUtil.h"
|
|
11
11
|
|
|
12
12
|
#import <React/RCTBridgeModule.h>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#import <Foundation/Foundation.h>
|
|
10
|
-
#import <
|
|
10
|
+
#import <NamiApple/NamiApple.h>
|
|
11
11
|
#import "NamiBridgeUtil.h"
|
|
12
12
|
|
|
13
13
|
#import <React/RCTBridgeModule.h>
|
|
@@ -15,6 +15,24 @@
|
|
|
15
15
|
|
|
16
16
|
#import "React/RCTViewManager.h"
|
|
17
17
|
|
|
18
|
+
@interface RCT_EXTERN_MODULE(RNNamiPaywallManager, NSObject)
|
|
19
|
+
|
|
20
|
+
RCT_EXTERN_METHOD(buySkuComplete:(NSDictionary)dict)
|
|
21
|
+
|
|
22
|
+
RCT_EXTERN_METHOD(registerBuySkuHandler)
|
|
23
|
+
|
|
24
|
+
RCT_EXTERN_METHOD(registerCloseHandler:(BOOL)blockDismiss)
|
|
25
|
+
|
|
26
|
+
RCT_EXTERN_METHOD(dismiss:(BOOL)animated completion:(RCTResponseSenderBlock)callback)
|
|
27
|
+
|
|
28
|
+
RCT_EXTERN_METHOD(displayedViewController)
|
|
29
|
+
|
|
30
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
31
|
+
return YES;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@end
|
|
35
|
+
|
|
18
36
|
@interface NamiEmitter : RCTEventEmitter
|
|
19
37
|
- (void)sendEventPreparePaywallForDisplayFinishedWithResult:(BOOL)success developerPaywallID: (NSString * _Nullable) developerPaywallID error:(NSError * _Nullable) error;
|
|
20
38
|
+ (NamiEmitter *) reactInstance;
|
|
@@ -32,22 +50,18 @@
|
|
|
32
50
|
self = [super init];
|
|
33
51
|
if (self) {
|
|
34
52
|
[self setBlockPaywallRaise:false];
|
|
35
|
-
[NamiPaywallManager registerAllowAutoRaisePaywallHandler:^BOOL{
|
|
36
|
-
NSLog(@"Block paywall raise set to %d", [self blockPaywallRaise]);
|
|
37
|
-
return ![self blockPaywallRaise];
|
|
38
|
-
}];
|
|
39
53
|
}
|
|
40
54
|
return self;
|
|
41
55
|
}
|
|
42
56
|
|
|
43
57
|
RCT_EXTERN_METHOD(raisePaywall)
|
|
44
58
|
- (void)raisePaywall {
|
|
45
|
-
|
|
59
|
+
[NamiCampaignManager launch];
|
|
46
60
|
}
|
|
47
61
|
|
|
48
|
-
RCT_EXPORT_METHOD(raisePaywallByDeveloperPaywallId
|
|
62
|
+
RCT_EXPORT_METHOD(raisePaywallByDeveloperPaywallId)
|
|
49
63
|
{
|
|
50
|
-
[
|
|
64
|
+
[NamiCampaignManager launch];
|
|
51
65
|
}
|
|
52
66
|
|
|
53
67
|
RCT_EXPORT_METHOD(blockPaywallRaise:(BOOL)blockRaise)
|
|
@@ -55,92 +69,6 @@ RCT_EXPORT_METHOD(blockPaywallRaise:(BOOL)blockRaise)
|
|
|
55
69
|
[self setBlockPaywallRaise:blockRaise];
|
|
56
70
|
}
|
|
57
71
|
|
|
58
|
-
RCT_EXPORT_METHOD(canRaisePaywall:(RCTResponseSenderBlock)completion)
|
|
59
|
-
{
|
|
60
|
-
BOOL canRaise = [NamiPaywallManager canRaisePaywall];
|
|
61
|
-
completion(@[[NSNumber numberWithBool:canRaise]]);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
RCT_EXPORT_METHOD(presentNamiPaywall:(NSArray *)skuIDs metapaywallDefinition:(NSDictionary *)paywallDict)
|
|
66
|
-
{
|
|
67
|
-
NSString *paywallDeveloperID = paywallDict[@"developerPaywallID"];
|
|
68
|
-
if ( paywallDeveloperID != nil ) {
|
|
69
|
-
[NamiPaywallManager fetchCustomPaywallMetaForDeveloperID:paywallDeveloperID :^(NSArray<NamiSKU *> * _Nullable products, NSString * _Nonnull paywallDevloperID, NamiPaywall * _Nullable namiMetaPaywall) {
|
|
70
|
-
[NamiPaywallManager presentNamiPaywallFromVC:nil products:products paywallMetadata:namiMetaPaywall backgroundImage:namiMetaPaywall.backgroundImage forNami:false];
|
|
71
|
-
}];
|
|
72
|
-
} else {
|
|
73
|
-
// No way to handle this case for now as we cannot cretae a NamiMetaPaywall
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
RCT_EXPORT_METHOD(fetchCustomPaywallMetaForDeveloperID:(NSString *)developerPaywallID completion:(RCTResponseSenderBlock)completion)
|
|
78
|
-
{
|
|
79
|
-
[NamiPaywallManager fetchCustomPaywallMetaForDeveloperID:developerPaywallID :^(NSArray<NamiSKU *> * _Nullable products, NSString * _Nonnull developerPaywallID, NamiPaywall * _Nullable paywallMetadata) {
|
|
80
|
-
NSMutableArray<NSDictionary<NSString *,NSString *> *> *productDicts = [NSMutableArray new];
|
|
81
|
-
for (NamiSKU *product in products) {
|
|
82
|
-
[productDicts addObject:[NamiBridgeUtil skuToSKUDict:product]];
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
NSMutableDictionary *paywallMeta = [NSMutableDictionary dictionaryWithDictionary:paywallMetadata.namiPaywallInfoDict];
|
|
86
|
-
// This part is really meant to be internally facing, scrub from dictionary
|
|
87
|
-
// Strip out presention_position from all listed sku items
|
|
88
|
-
NSArray *cleanedOrderdMetadata = [NamiBridgeUtil stripPresentationPositionFromOrderedMetadataForPaywallMetaDict:paywallMeta];
|
|
89
|
-
[paywallMeta setObject:cleanedOrderdMetadata forKey:@"formatted_skus"];
|
|
90
|
-
|
|
91
|
-
[paywallMeta removeObjectForKey:@"sku_ordered_metadata"];
|
|
92
|
-
[paywallMeta removeObjectForKey:@"skus"];
|
|
93
|
-
|
|
94
|
-
NSDictionary *paywallStylingDict = [NamiBridgeUtil paywallStylingToPaywallStylingDict:[paywallMetadata styleData]];
|
|
95
|
-
paywallMeta[@"styleData"] = paywallStylingDict;
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
NSArray *wrapperArray = @[@{ @"namiSkus": productDicts,
|
|
99
|
-
@"developerPaywallID": developerPaywallID,
|
|
100
|
-
@"paywallMetadata": paywallMeta }];
|
|
101
|
-
completion(wrapperArray);
|
|
102
|
-
}];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
RCT_EXPORT_METHOD(paywallImpression:(NSString *)developerPaywallID)
|
|
107
|
-
{
|
|
108
|
-
[NamiPaywallManager paywallImpressionWithDeveloperID:developerPaywallID];
|
|
109
|
-
}
|
|
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
|
-
|
|
143
|
-
|
|
144
72
|
@end
|
|
145
73
|
|
|
146
74
|
@implementation NamiPaywallManagerBridge
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NamiPaywallManagerBridge.swift
|
|
3
|
+
// RNNami
|
|
4
|
+
//
|
|
5
|
+
// Created by macbook on 07.04.2023.
|
|
6
|
+
// Copyright © 2023 Nami ML INc.. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import NamiApple
|
|
11
|
+
import React
|
|
12
|
+
|
|
13
|
+
@objc(RNNamiPaywallManager)
|
|
14
|
+
class RNNamiPaywallManager: RCTEventEmitter {
|
|
15
|
+
override func supportedEvents() -> [String]! {
|
|
16
|
+
return ["RegisterBuySKU", "BlockingPaywallClosed"]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@objc(buySkuComplete:)
|
|
20
|
+
func buySkuComplete(dict: NSDictionary) {
|
|
21
|
+
guard let jsonData = try? JSONSerialization.data(withJSONObject: dict["product"] as Any, options: []) else {
|
|
22
|
+
print("Error converting dictionary to JSON data")
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
do {
|
|
26
|
+
let decoder = JSONDecoder()
|
|
27
|
+
let product = try decoder.decode(NamiSKU.self, from: jsonData)
|
|
28
|
+
|
|
29
|
+
let dateFormatter = DateFormatter()
|
|
30
|
+
dateFormatter.locale = .init(identifier: "en_US_POSIX")
|
|
31
|
+
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
|
|
32
|
+
|
|
33
|
+
if
|
|
34
|
+
let transactionID = dict["transactionID"] as? String,
|
|
35
|
+
let originalTransactionID = dict["originalTransactionID"] as? String,
|
|
36
|
+
let priceDecimal = Decimal(string: dict["price"] as! String),
|
|
37
|
+
let currencyCode = dict["currencyCode"] as? String,
|
|
38
|
+
let localeString = dict["locale"] as? String
|
|
39
|
+
{
|
|
40
|
+
let expiresDate = Date(timeIntervalSince1970: dict["purchaseDate"] as! Double? ?? 0)
|
|
41
|
+
let originalPurchaseDate = Date(timeIntervalSince1970: dict["originalPurchaseDate"] as! Double)
|
|
42
|
+
let purchaseDate = Date(timeIntervalSince1970: dict["purchaseDate"] as! Double)
|
|
43
|
+
let locale = Locale(identifier: localeString)
|
|
44
|
+
let purchaseSuccess = NamiPurchaseSuccess(
|
|
45
|
+
product: product,
|
|
46
|
+
transactionID: transactionID,
|
|
47
|
+
originalTransactionID: originalTransactionID,
|
|
48
|
+
originalPurchaseDate: originalPurchaseDate,
|
|
49
|
+
purchaseDate: purchaseDate,
|
|
50
|
+
expiresDate: expiresDate,
|
|
51
|
+
price: priceDecimal,
|
|
52
|
+
currencyCode: currencyCode,
|
|
53
|
+
locale: locale
|
|
54
|
+
)
|
|
55
|
+
NamiPaywallManager.buySkuComplete(purchaseSuccess: purchaseSuccess)
|
|
56
|
+
}
|
|
57
|
+
} catch {
|
|
58
|
+
print("Error decoding JSON: \(error)")
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@objc(registerBuySkuHandler)
|
|
63
|
+
func registerBuySkuHandler() {
|
|
64
|
+
NamiPaywallManager.registerBuySkuHandler { sku in
|
|
65
|
+
let dictionary = RNNamiPurchaseManager.skuToSKUDict(sku)
|
|
66
|
+
self.sendEvent(withName: "RegisterBuySKU", body: dictionary)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@objc(registerCloseHandler:)
|
|
71
|
+
func registerCloseHandler(blockDismiss: Bool) {
|
|
72
|
+
NamiPaywallManager.registerCloseHandler { _ in
|
|
73
|
+
let dictionary = NSDictionary(dictionary: ["blockingPaywallClosed": true].compactMapValues { $0 })
|
|
74
|
+
self.sendEvent(withName: "BlockingPaywallClosed", body: dictionary)
|
|
75
|
+
if (blockDismiss) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
NamiPaywallManager.dismiss(animated: true, completion: {})
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@objc(dismiss:callback:)
|
|
83
|
+
func dismiss(animated: Bool, callback: @escaping RCTResponseSenderBlock) {
|
|
84
|
+
NamiPaywallManager.dismiss(animated: animated) {
|
|
85
|
+
callback([])
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@objc(displayedViewController)
|
|
90
|
+
func displayedViewController() {
|
|
91
|
+
_ = NamiPaywallManager.displayedViewController()
|
|
92
|
+
}
|
|
93
|
+
}
|