@attentive-mobile/attentive-react-native-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +140 -0
  3. package/android/build.gradle +92 -0
  4. package/android/github.properties +2 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +4 -0
  7. package/android/src/main/java/com/attentivereactnativesdk/AttentiveReactNativeSdkModule.java +195 -0
  8. package/android/src/main/java/com/attentivereactnativesdk/AttentiveReactNativeSdkPackage.java +28 -0
  9. package/attentive-react-native-sdk.podspec +36 -0
  10. package/ios/AttentiveReactNativeSdk.h +18 -0
  11. package/ios/AttentiveReactNativeSdk.mm +85 -0
  12. package/ios/AttentiveReactNativeSdk.xcodeproj/project.pbxproj +276 -0
  13. package/ios/AttentiveReactNativeSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
  14. package/ios/AttentiveReactNativeSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  15. package/ios/AttentiveReactNativeSdk.xcodeproj/project.xcworkspace/xcuserdata/wdavis.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  16. package/ios/AttentiveReactNativeSdk.xcodeproj/xcuserdata/wdavis.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
  17. package/ios/attentive-sdk-umbrella.h +23 -0
  18. package/lib/commonjs/eventTypes.js +2 -0
  19. package/lib/commonjs/eventTypes.js.map +1 -0
  20. package/lib/commonjs/index.js +50 -0
  21. package/lib/commonjs/index.js.map +1 -0
  22. package/lib/module/eventTypes.js +2 -0
  23. package/lib/module/eventTypes.js.map +1 -0
  24. package/lib/module/index.js +42 -0
  25. package/lib/module/index.js.map +1 -0
  26. package/lib/typescript/eventTypes.d.ts +36 -0
  27. package/lib/typescript/eventTypes.d.ts.map +1 -0
  28. package/lib/typescript/index.d.ts +30 -0
  29. package/lib/typescript/index.d.ts.map +1 -0
  30. package/package.json +162 -0
  31. package/src/eventTypes.tsx +42 -0
  32. package/src/index.tsx +77 -0
package/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Attentive Mobile
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # attentive-react-native-sdk
2
+
3
+ # Attentive React Native SDK
4
+ The Attentive React Native SDK provides the functionality to render Attentive creative units and collect Attentive events in React Native mobile applications.
5
+
6
+ ## Installation
7
+
8
+ TODO
9
+
10
+ ## Usage
11
+ See the [Example Project](https://github.com/attentive-mobile/attentive-react-native-sdk/blob/main/example)
12
+ for a sample of how the Attentive React Native SDK is used.
13
+
14
+ __*** NOTE: Please refrain from using any private or undocumented classes or methods as they may change between releases. ***__
15
+
16
+ ### Import the SDK
17
+
18
+ ```typescript
19
+ import { Attentive, <other types you need here> } from 'attentive-react-native-sdk';
20
+ ```
21
+
22
+ ### Create the AttentiveConfig
23
+
24
+ ```typescript
25
+ // Create an AttentiveConfiguration with your attentive domain, in production mode
26
+ const config : AttentiveConfiguration = {
27
+ attentiveDomain: 'YOUR_ATTENTIVE_DOMAIN',
28
+ mode: Mode.Production,
29
+ }
30
+ ```
31
+ ```typescript
32
+ // Alternatively, use "debug" mode. When in debug mode, the Creative will not be shown, but instead a popup will show with debug information about your creative and any reason the Creative wouldn't show.
33
+ const config : AttentiveConfiguration = {
34
+ attentiveDomain: 'YOUR_ATTENTIVE_DOMAIN',
35
+ mode: Mode.Debug,
36
+ }
37
+ ```
38
+
39
+ ### Initialize the SDK
40
+
41
+ ```typescript
42
+ // 'initialize' should be called as soon as possible after the app starts (see the example app for an example of initializing the SDK in the App element)
43
+ // Note: 'initialize' should only be called once per app session - if you call it multiple times it will throw an exception
44
+ Attentive.initialize(config);
45
+ ```
46
+
47
+
48
+ ### Identify the current user
49
+ ```typescript
50
+ // Before loading the creative or sending events, if you have any user identifiers, they will need to be registered. Each identifier is optional. It is okay to skip this step if you have no identifiers about the user yet.
51
+ const identifiers : UserIdentifiers = {
52
+ 'phone': '+15556667777',
53
+ 'email': 'some_email@gmailfake.com',
54
+ 'klaviyoId': 'userKlaviyoId',
55
+ 'shopifyId': 'userShopifyId',
56
+ 'clientUserId': 'userClientUserId',
57
+ 'customIdentifiers': { 'customIdKey': 'customIdValue' }
58
+ };
59
+ Attentive.identify(identifiers);
60
+ ```
61
+
62
+ The more identifiers that are passed to `identify`, the better the SDK will function. Here is the list of possible identifiers:
63
+ | Identifier Name | Type | Description |
64
+ | ------------------ | --------------------- | ----------------------------------------------------------------------------------------------------------------------- |
65
+ | Client User ID | String | Your unique identifier for the user. This should be consistent across the user's lifetime. For example, a database id. |
66
+ | Phone | String | The users's phone number in E.164 format |
67
+ | Email | String | The users's email |
68
+ | Shopify ID | String | The users's Shopify ID |
69
+ | Klaviyo ID | String | The users's Klaviyo ID |
70
+ | Custom Identifiers | Map<String,String> | Key-value pairs of custom identifier names and values. The values should be unique to this user. |
71
+
72
+ ### Load the Creative
73
+ #### 1. Create the Creative
74
+ ```typescript
75
+ // Trigger the Creative. This will show the Creative as a pop-up over the rest of the app.
76
+ Attentive.triggerCreative();
77
+ ```
78
+
79
+ #### 3. Destroy the Creative
80
+
81
+ TODO
82
+
83
+ __*** NOTE: You must call the destroy method when the creative is no longer in use to properly clean up the WebView and it's resources ***__
84
+
85
+
86
+ ### Record user events
87
+
88
+ The SDK currently supports `PurchaseEvent`, `AddToCartEvent`, `ProductViewEvent`, and `CustomEvent`.
89
+
90
+ ```typescript
91
+ // Construct one or more "Item"s, which represents the product(s) purchased
92
+ const items : Item[] = [
93
+ {
94
+ productId: '555',
95
+ productVariantId: '777',
96
+ price: {
97
+ price: '14.99',
98
+ currency: 'USD',
99
+ },
100
+ },
101
+ ];
102
+
103
+ // Construct an "Order", which represents the order for the purchase
104
+ const order : Order = {
105
+ orderId: '88888'
106
+ }
107
+
108
+ // (Optional) Construct a "Cart", which represents the cart this Purchase was made from
109
+ const cart : Cart = {
110
+ cartId: '555555',
111
+ cartCoupon: 'SOME-DISCOUNT'
112
+ }
113
+
114
+ // Construct a PurchaseEvent, which ties together the preceding objects
115
+ const purchaseEvent : PurchaseEvent = {
116
+ items: items,
117
+ order: order,
118
+ cart: cart
119
+ }
120
+
121
+ // Record the PurchaseEvent
122
+ Attentive.recordPurchaseEvent(purchaseEvent);
123
+ ```
124
+
125
+ The process is similar for the other events. See [eventTypes.tsx](https://github.com/attentive-mobile/attentive-react-native-sdk/blob/main/src/eventTypes.tsx) for all events.
126
+
127
+ ### Update the current user when new identifiers are available
128
+
129
+ ```typescript
130
+ // If new identifiers are available for the user, register them
131
+ Attentive.identify({email: 'theusersemail@gmail.com'});
132
+ ```
133
+
134
+ ```typescript
135
+ Attentive.identify({email: 'theusersemail@gmail.com'});
136
+ Attentive.identify({phone: '+15556667777'};)
137
+ // The SDK will have these two identifiers:
138
+ // email: 'theusersemail@gmail.com'
139
+ // phone: '+15556667777'
140
+ ```
@@ -0,0 +1,92 @@
1
+ buildscript {
2
+ repositories {
3
+ google()
4
+ mavenCentral()
5
+ }
6
+
7
+ dependencies {
8
+ classpath "com.android.tools.build:gradle:7.2.1"
9
+ }
10
+ }
11
+
12
+ def isNewArchitectureEnabled() {
13
+ return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
14
+ }
15
+
16
+ apply plugin: "com.android.library"
17
+
18
+
19
+ def appProject = rootProject.allprojects.find { it.plugins.hasPlugin('com.android.application') }
20
+
21
+ if (isNewArchitectureEnabled()) {
22
+ apply plugin: "com.facebook.react"
23
+ }
24
+
25
+ def getExtOrDefault(name) {
26
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["AttentiveReactNativeSdk_" + name]
27
+ }
28
+
29
+ def getExtOrIntegerDefault(name) {
30
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["AttentiveReactNativeSdk_" + name]).toInteger()
31
+ }
32
+
33
+ android {
34
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
35
+
36
+ defaultConfig {
37
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
38
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
39
+ buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
40
+ }
41
+ buildTypes {
42
+ release {
43
+ minifyEnabled false
44
+ }
45
+ }
46
+
47
+ lintOptions {
48
+ disable "GradleCompatible"
49
+ }
50
+
51
+ compileOptions {
52
+ sourceCompatibility JavaVersion.VERSION_1_8
53
+ targetCompatibility JavaVersion.VERSION_1_8
54
+ }
55
+
56
+ }
57
+
58
+ Properties ghProperties = new Properties()
59
+ File ghPropertiesFile = file("github.properties")
60
+ if (!ghPropertiesFile.exists()) {
61
+ throw new GradleException('Could not find github.properties file.')
62
+ }
63
+ ghProperties.load(ghPropertiesFile.newDataInputStream())
64
+
65
+ repositories {
66
+ mavenCentral()
67
+ google()
68
+ maven {
69
+ url = uri("https://maven.pkg.github.com/attentive-mobile/attentive-android-sdk")
70
+ credentials {
71
+ username = ghProperties.getProperty('gpr.user')
72
+ password = ghProperties.getProperty('gpr.key')
73
+ }
74
+ }
75
+ }
76
+
77
+
78
+ dependencies {
79
+ // For < 0.71, this will be from the local maven repo
80
+ // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
81
+ //noinspection GradleDynamicVersion
82
+ implementation "com.facebook.react:react-native:+"
83
+ implementation 'com.attentive:attentive-android-sdk:0.4.0'
84
+ }
85
+
86
+ if (isNewArchitectureEnabled()) {
87
+ react {
88
+ jsRootDir = file("../src/")
89
+ libraryName = "AttentiveReactNativeSdk"
90
+ codegenJavaPackageName = "com.attentivereactnativesdk"
91
+ }
92
+ }
@@ -0,0 +1,2 @@
1
+ gpr.user=wyattjoe40
2
+ gpr.key=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
@@ -0,0 +1,5 @@
1
+ AttentiveReactNativeSdk_kotlinVersion=1.7.0
2
+ AttentiveReactNativeSdk_minSdkVersion=21
3
+ AttentiveReactNativeSdk_targetSdkVersion=31
4
+ AttentiveReactNativeSdk_compileSdkVersion=31
5
+ AttentiveReactNativeSdk_ndkversion=21.4.7075529
@@ -0,0 +1,4 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.attentivereactnativesdk">
3
+
4
+ </manifest>
@@ -0,0 +1,195 @@
1
+ package com.attentivereactnativesdk;
2
+
3
+ import android.app.Activity;
4
+ import android.util.Log;
5
+ import android.view.ViewGroup;
6
+ import androidx.annotation.NonNull;
7
+
8
+ import com.attentive.androidsdk.AttentiveConfig;
9
+ import com.attentive.androidsdk.AttentiveEventTracker;
10
+ import com.attentive.androidsdk.UserIdentifiers;
11
+ import com.attentive.androidsdk.creatives.Creative;
12
+ import com.attentive.androidsdk.events.AddToCartEvent;
13
+ import com.attentive.androidsdk.events.CustomEvent;
14
+ import com.attentive.androidsdk.events.Item;
15
+ import com.attentive.androidsdk.events.Order;
16
+ import com.attentive.androidsdk.events.Price;
17
+ import com.attentive.androidsdk.events.ProductViewEvent;
18
+ import com.attentive.androidsdk.events.PurchaseEvent;
19
+ import com.facebook.react.bridge.ReactApplicationContext;
20
+ import com.facebook.react.bridge.ReactContextBaseJavaModule;
21
+ import com.facebook.react.bridge.ReactMethod;
22
+ import com.facebook.react.bridge.ReadableArray;
23
+ import com.facebook.react.bridge.ReadableMap;
24
+ import com.facebook.react.bridge.UiThreadUtil;
25
+ import com.facebook.react.module.annotations.ReactModule;
26
+ import java.math.BigDecimal;
27
+ import java.security.InvalidParameterException;
28
+ import java.util.ArrayList;
29
+ import java.util.Arrays;
30
+ import java.util.Currency;
31
+ import java.util.HashMap;
32
+ import java.util.List;
33
+ import java.util.Locale;
34
+ import java.util.Map;
35
+
36
+ @ReactModule(name = AttentiveReactNativeSdkModule.NAME)
37
+ public class AttentiveReactNativeSdkModule extends ReactContextBaseJavaModule {
38
+ public static final String NAME = "AttentiveReactNativeSdk";
39
+ private static final String TAG = NAME;
40
+
41
+ private AttentiveConfig attentiveConfig;
42
+
43
+ public AttentiveReactNativeSdkModule(ReactApplicationContext reactContext) {
44
+ super(reactContext);
45
+ }
46
+
47
+ @Override
48
+ @NonNull
49
+ public String getName() {
50
+ return NAME;
51
+ }
52
+
53
+ @ReactMethod
54
+ public void initialize(ReadableMap config) {
55
+ final String rawMode = config.getString("mode");
56
+ if (rawMode == null) {
57
+ throw new IllegalArgumentException("The 'mode' parameter cannot be null.");
58
+ }
59
+ final String domain = config.getString("attentiveDomain");
60
+ attentiveConfig = new AttentiveConfig(domain, AttentiveConfig.Mode.valueOf(rawMode.toUpperCase(Locale.ROOT)), this.getReactApplicationContext());
61
+ AttentiveEventTracker.getInstance().initialize(attentiveConfig);
62
+ }
63
+
64
+ @ReactMethod
65
+ public void triggerCreative() {
66
+ Log.i(TAG, "Native Attentive module was called to trigger the creative.");
67
+ try {
68
+ Activity currentActivity = getReactApplicationContext().getCurrentActivity();
69
+ if (currentActivity != null) {
70
+ ViewGroup rootView =
71
+ (ViewGroup) currentActivity.getWindow().getDecorView().getRootView();
72
+ // The following calls edit the view hierarchy so they must run on the UI thread
73
+ UiThreadUtil.runOnUiThread(() -> {
74
+ Creative creative = new Creative(attentiveConfig, rootView);
75
+ creative.trigger();
76
+ });
77
+ } else {
78
+ Log.w(TAG, "Could not trigger the Attentive Creative because the current Activity was null");
79
+ }
80
+ } catch (Exception e) {
81
+ Log.e(TAG, "Exception when triggering the creative: " + e);
82
+ }
83
+ }
84
+
85
+ @ReactMethod
86
+ public void clearUser() {
87
+ attentiveConfig.clearUser();
88
+ }
89
+
90
+ @ReactMethod
91
+ public void identify(ReadableMap identifiers) {
92
+ UserIdentifiers.Builder idsBuilder = new UserIdentifiers.Builder();
93
+ if (identifiers.hasKey("phone")) {
94
+ idsBuilder.withPhone(identifiers.getString("phone"));
95
+ }
96
+ if (identifiers.hasKey("email")) {
97
+ idsBuilder.withEmail(identifiers.getString("email"));
98
+ }
99
+ if (identifiers.hasKey("klaviyoId")) {
100
+ idsBuilder.withKlaviyoId(identifiers.getString("klaviyoId"));
101
+ }
102
+ if (identifiers.hasKey("shopifyId")) {
103
+ idsBuilder.withShopifyId(identifiers.getString("shopifyId"));
104
+ }
105
+ if (identifiers.hasKey("clientUserId")) {
106
+ idsBuilder.withClientUserId(identifiers.getString("clientUserId"));
107
+ }
108
+ if (identifiers.hasKey("customIdentifiers")) {
109
+ Map<String, String> customIds = new HashMap<>();
110
+ Map<String, Object> rawCustomIds = identifiers.getMap("customIdentifiers").toHashMap();
111
+ for (Map.Entry<String, Object> entry : rawCustomIds.entrySet()) {
112
+ if (entry.getValue() instanceof String) {
113
+ customIds.put(entry.getKey(), (String) entry.getValue());
114
+ }
115
+ }
116
+ idsBuilder.withCustomIdentifiers(customIds);
117
+ }
118
+
119
+ attentiveConfig.identify(idsBuilder.build());
120
+ }
121
+
122
+ @ReactMethod
123
+ public void recordProductViewEvent(ReadableMap productViewAttrs) {
124
+ Log.i(TAG, "Sending product viewed event");
125
+
126
+ List<Item> items = buildItems(productViewAttrs.getArray("items"));
127
+ ProductViewEvent productViewEvent = new ProductViewEvent.Builder(items).build();
128
+
129
+ AttentiveEventTracker.getInstance().recordEvent(productViewEvent);
130
+ }
131
+
132
+ @ReactMethod
133
+ public void recordPurchaseEvent(ReadableMap purchaseAttrs) {
134
+ Log.i(TAG, "Sending purchase event");
135
+ Order order = new Order.Builder(purchaseAttrs.getMap("order").getString("orderId")).build();
136
+
137
+ List<Item> items = buildItems(purchaseAttrs.getArray("items"));
138
+ PurchaseEvent purchaseEvent = new PurchaseEvent.Builder(items, order).build();
139
+
140
+ AttentiveEventTracker.getInstance().recordEvent(purchaseEvent);
141
+ }
142
+
143
+ @ReactMethod
144
+ public void recordAddToCartEvent(ReadableMap addToCartAttrs) {
145
+ Log.i(TAG, "Sending add to cart event");
146
+
147
+ List<Item> items = buildItems(addToCartAttrs.getArray("items"));
148
+ AddToCartEvent addToCartEvent = new AddToCartEvent.Builder(items).build();
149
+
150
+ AttentiveEventTracker.getInstance().recordEvent(addToCartEvent);
151
+ }
152
+
153
+ @ReactMethod
154
+ public void recordCustomEvent(ReadableMap customEventAttrs) {
155
+ Log.i(TAG, "Sending custom event");
156
+ ReadableMap propertiesRawMap = customEventAttrs.getMap("properties");
157
+ if (propertiesRawMap == null) {
158
+ throw new IllegalArgumentException("The CustomEvent 'properties' field cannot be null.");
159
+ }
160
+ Map<String, String> properties = convertToStringMap(propertiesRawMap.toHashMap());
161
+ CustomEvent customEvent = new CustomEvent.Builder(customEventAttrs.getString("type"), properties).build();
162
+
163
+ AttentiveEventTracker.getInstance().recordEvent(customEvent);
164
+ }
165
+
166
+ private Map<String, String> convertToStringMap(Map<String, Object> inputMap) {
167
+ Map<String, String> outputMap = new HashMap<>();
168
+ for (Map.Entry<String, Object> entry : inputMap.entrySet()) {
169
+ Object entryValue = entry.getValue();
170
+ if (entryValue == null) {
171
+ throw new InvalidParameterException(String.format("The key '%s' has a null value.", entry.getKey()));
172
+ }
173
+ if (entryValue instanceof String) {
174
+ outputMap.put(entry.getKey(), (String) entry.getValue());
175
+ }
176
+ }
177
+
178
+ return outputMap;
179
+ }
180
+
181
+ private List<Item> buildItems(ReadableArray rawItems) {
182
+ List<Item> items = new ArrayList<>();
183
+ for (int i = 0; i < rawItems.size(); i++) {
184
+ ReadableMap rawItem = rawItems.getMap(i);
185
+
186
+ ReadableMap priceMap = rawItem.getMap("price");
187
+ Price price = new Price.Builder(new BigDecimal(priceMap.getString("price")), Currency.getInstance(priceMap.getString("currency"))).build();
188
+
189
+ Item item = new Item.Builder(rawItem.getString("productId"), rawItem.getString("productVariantId"), price).build();
190
+ items.add(item);
191
+ }
192
+
193
+ return items;
194
+ }
195
+ }
@@ -0,0 +1,28 @@
1
+ package com.attentivereactnativesdk;
2
+
3
+ import androidx.annotation.NonNull;
4
+
5
+ import com.facebook.react.ReactPackage;
6
+ import com.facebook.react.bridge.NativeModule;
7
+ import com.facebook.react.bridge.ReactApplicationContext;
8
+ import com.facebook.react.uimanager.ViewManager;
9
+
10
+ import java.util.ArrayList;
11
+ import java.util.Collections;
12
+ import java.util.List;
13
+
14
+ public class AttentiveReactNativeSdkPackage implements ReactPackage {
15
+ @NonNull
16
+ @Override
17
+ public List<NativeModule> createNativeModules(@NonNull ReactApplicationContext reactContext) {
18
+ List<NativeModule> modules = new ArrayList<>();
19
+ modules.add(new AttentiveReactNativeSdkModule(reactContext));
20
+ return modules;
21
+ }
22
+
23
+ @NonNull
24
+ @Override
25
+ public List<ViewManager> createViewManagers(@NonNull ReactApplicationContext reactContext) {
26
+ return Collections.emptyList();
27
+ }
28
+ }
@@ -0,0 +1,36 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+ folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
5
+
6
+ Pod::Spec.new do |s|
7
+ s.name = "attentive-react-native-sdk"
8
+ s.version = package["version"]
9
+ s.summary = package["description"]
10
+ s.homepage = package["homepage"]
11
+ s.license = package["license"]
12
+ s.authors = package["author"]
13
+
14
+ s.platforms = { :ios => "11.0" }
15
+ s.source = { :git => "https://github.com/attentive-mobile/attentive-react-native-sdk.git", :tag => "#{s.version}" }
16
+
17
+ s.source_files = "ios/**/*.{h,m,mm}"
18
+
19
+ s.dependency 'attentive-ios-sdk', '0.4.0'
20
+ s.dependency "React-Core"
21
+
22
+ # Don't install the dependencies when we run `pod install` in the old architecture.
23
+ if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
24
+ s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
25
+ s.pod_target_xcconfig = {
26
+ "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
27
+ "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
28
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
29
+ }
30
+ s.dependency "React-Codegen"
31
+ s.dependency "RCT-Folly"
32
+ s.dependency "RCTRequired"
33
+ s.dependency "RCTTypeSafety"
34
+ s.dependency "ReactCommon/turbomodule/core"
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ //
2
+ // AttentiveReactNativeSdk.h
3
+ // AttentiveReactNativeSdk
4
+ //
5
+ // Created by Wyatt Davis on 2/13/23.
6
+ //
7
+
8
+ #ifdef RCT_NEW_ARCH_ENABLED
9
+ #import "RNAttentiveReactNativeSdkSpec.h"
10
+
11
+ @interface AttentiveReactNativeSdk : NSObject <NativeAttentiveReactNativeSdkSpec>
12
+ #else
13
+ #import <React/RCTBridgeModule.h>
14
+
15
+ @interface AttentiveReactNativeSdk : NSObject <RCTBridgeModule>
16
+ #endif
17
+
18
+ @end
@@ -0,0 +1,85 @@
1
+ //
2
+ // AttentiveReactNativeSdk.m
3
+ // AttentiveReactNativeSdk
4
+ //
5
+ // Created by Wyatt Davis on 2/13/23.
6
+ //
7
+
8
+ #import "AttentiveReactNativeSdk.h"
9
+ #import "attentive-sdk-umbrella.h"
10
+
11
+ @implementation AttentiveReactNativeSdk {
12
+ ATTNSDK* _sdk;
13
+ }
14
+
15
+ RCT_EXPORT_MODULE()
16
+
17
+ RCT_EXPORT_METHOD(initialize:(NSDictionary*)configuration) {
18
+ _sdk = [[ATTNSDK alloc] initWithDomain:configuration[@"attentiveDomain"] mode:configuration[@"mode"]];
19
+ [ATTNEventTracker setupWithSdk:_sdk];
20
+ }
21
+
22
+ RCT_EXPORT_METHOD(triggerCreative) {
23
+ dispatch_async(dispatch_get_main_queue(), ^{
24
+ UIWindow *window = [[UIApplication sharedApplication] keyWindow];
25
+ UIView *topView = window.rootViewController.view;
26
+ [self->_sdk trigger:topView];
27
+ });
28
+ }
29
+
30
+ RCT_EXPORT_METHOD(identify:(NSDictionary*)identifiers) {
31
+ // The dictionary already has the correct keys from the React code, so no translating necessary
32
+ [_sdk identify:identifiers];
33
+ }
34
+
35
+ RCT_EXPORT_METHOD(clearUser) {
36
+ [_sdk clearUser];
37
+ }
38
+
39
+ RCT_EXPORT_METHOD(recordAddToCartEvent:(NSDictionary*)attrs) {
40
+ NSArray* items = [self parseItems:attrs[@"items"]];
41
+ ATTNAddToCartEvent* event = [[ATTNAddToCartEvent alloc] initWithItems:items];
42
+ [[ATTNEventTracker sharedInstance] recordEvent:event];
43
+ }
44
+
45
+ RCT_EXPORT_METHOD(recordProductViewEvent:(NSDictionary*)attrs) {
46
+ NSArray* items = [self parseItems:attrs[@"items"]];
47
+ ATTNProductViewEvent* event = [[ATTNProductViewEvent alloc] initWithItems:items];
48
+ [[ATTNEventTracker sharedInstance] recordEvent:event];
49
+ }
50
+
51
+ RCT_EXPORT_METHOD(recordPurchaseEvent:(NSDictionary*)attrs) {
52
+ NSArray* items = [self parseItems:attrs[@"items"]];
53
+ ATTNOrder* order = [[ATTNOrder alloc] initWithOrderId:attrs[@"order"][@"id"]];
54
+ ATTNPurchaseEvent* event = [[ATTNPurchaseEvent alloc] initWithItems:items order:order];
55
+ [[ATTNEventTracker sharedInstance] recordEvent:event];
56
+ }
57
+
58
+ RCT_EXPORT_METHOD(recordCustomEvent:(NSDictionary*)attrs) {
59
+ ATTNCustomEvent* customEvent = [[ATTNCustomEvent alloc] initWithType:attrs[@"type"] properties:attrs[@"properties"]];
60
+ [[ATTNEventTracker sharedInstance] recordEvent:customEvent];
61
+ }
62
+
63
+ - (NSArray*)parseItems:(NSArray*)rawItems {
64
+ NSMutableArray* itemsToReturn = [[NSMutableArray alloc] init];
65
+ for (NSDictionary* rawItem in rawItems) {
66
+ NSDictionary* rawPrice = rawItem[@"price"];
67
+ ATTNPrice* price = [[ATTNPrice alloc] initWithPrice:[[NSDecimalNumber alloc] initWithString:rawPrice[@"price"]] currency:rawPrice[@"currency"]];
68
+
69
+ ATTNItem* item = [[ATTNItem alloc] initWithProductId:rawItem[@"productId"] productVariantId:rawItem[@"productVariantId"] price:price];
70
+
71
+ [itemsToReturn addObject:item];
72
+ }
73
+ return itemsToReturn;
74
+ }
75
+
76
+ // Don't compile this code when we build for the old architecture.
77
+ #ifdef RCT_NEW_ARCH_ENABLED
78
+ - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
79
+ (const facebook::react::ObjCTurboModule::InitParams &)params
80
+ {
81
+ return std::make_shared<facebook::react::NativeAttentiveReactNativeSdkSpecJSI>(params);
82
+ }
83
+ #endif
84
+
85
+ @end