react-native-mparticle 2.8.1 → 2.9.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.
Files changed (38) hide show
  1. package/README.md +252 -94
  2. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  3. package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
  4. package/android/gradle.properties +26 -0
  5. package/android/gradlew +160 -0
  6. package/android/gradlew.bat +90 -0
  7. package/android/libs/java-json.jar +0 -0
  8. package/android/src/main/java/com/mparticle/react/MParticleModule.kt +1 -1
  9. package/android/src/test/java/com/mparticle/react/IdentityApiTest.java +230 -0
  10. package/android/src/test/java/com/mparticle/react/MParticleUserTest.java +173 -0
  11. package/android/src/test/java/com/mparticle/react/testutils/MockMParticleUser.java +109 -0
  12. package/android/src/test/java/com/mparticle/react/testutils/MockMap.java +203 -0
  13. package/android/src/test/java/com/mparticle/react/testutils/MockReadableArray.java +68 -0
  14. package/android/src/test/java/com/mparticle/react/testutils/MockWritableMap.java +4 -0
  15. package/android/src/test/java/com/mparticle/react/testutils/Mutable.java +13 -0
  16. package/app.plugin.js +1 -0
  17. package/ios/RNMParticle/RNMPRokt.mm +93 -20
  18. package/ios/RNMParticle/RNMParticle.mm +2 -1
  19. package/ios/RNMParticle/RoktEventManager.m +24 -0
  20. package/js/codegenSpecs/NativeMParticle.ts +3 -4
  21. package/js/rokt/rokt-layout-view.android.tsx +2 -1
  22. package/lib/codegenSpecs/NativeMParticle.d.ts +3 -4
  23. package/lib/codegenSpecs/NativeMParticle.js.map +1 -1
  24. package/lib/rokt/rokt-layout-view.android.js +1 -0
  25. package/lib/rokt/rokt-layout-view.android.js.map +1 -1
  26. package/package.json +28 -4
  27. package/plugin/build/withMParticle.d.ts +60 -0
  28. package/plugin/build/withMParticle.js +30 -0
  29. package/plugin/build/withMParticleAndroid.d.ts +6 -0
  30. package/plugin/build/withMParticleAndroid.js +266 -0
  31. package/plugin/build/withMParticleIOS.d.ts +6 -0
  32. package/plugin/build/withMParticleIOS.js +362 -0
  33. package/plugin/src/withMParticle.ts +106 -0
  34. package/plugin/src/withMParticleAndroid.ts +359 -0
  35. package/plugin/src/withMParticleIOS.ts +459 -0
  36. package/plugin/tsconfig.json +8 -0
  37. package/react-native-mparticle.podspec +11 -0
  38. package/SECURITY.md +0 -9
@@ -0,0 +1,109 @@
1
+ package com.mparticle.react.testutils;
2
+
3
+ import androidx.annotation.NonNull;
4
+ import androidx.annotation.Nullable;
5
+
6
+ import com.mparticle.MParticle;
7
+ import com.mparticle.UserAttributeListenerType;
8
+ import com.mparticle.consent.ConsentState;
9
+ import com.mparticle.identity.MParticleUser;
10
+ import com.mparticle.audience.AudienceTask;
11
+ import com.mparticle.audience.AudienceResponse;
12
+
13
+ import java.util.Map;
14
+
15
+ public class MockMParticleUser implements MParticleUser {
16
+ Long mpid = 0L;
17
+
18
+ public MockMParticleUser() {}
19
+
20
+ public MockMParticleUser(Long mpid) {
21
+ this.mpid = mpid;
22
+ }
23
+
24
+ @NonNull
25
+ @Override
26
+ public long getId() {
27
+ return mpid;
28
+ }
29
+
30
+ @NonNull
31
+ @Override
32
+ public Map<String, Object> getUserAttributes() {
33
+ return null;
34
+ }
35
+
36
+ @Nullable
37
+ @Override
38
+ public Map<String, Object> getUserAttributes(@Nullable UserAttributeListenerType userAttributeListener) {
39
+ return null;
40
+ }
41
+
42
+ @Override
43
+ public boolean setUserAttributes(@NonNull Map<String, Object> map) {
44
+ return false;
45
+ }
46
+
47
+ @NonNull
48
+ @Override
49
+ public Map<MParticle.IdentityType, String> getUserIdentities() {
50
+ return null;
51
+ }
52
+
53
+ @Override
54
+ public boolean setUserAttribute(@NonNull String s, @NonNull Object o) {
55
+ return false;
56
+ }
57
+
58
+ @Override
59
+ public boolean setUserAttributeList(@NonNull String s, @NonNull Object o) {
60
+ return false;
61
+ }
62
+
63
+ @Override
64
+ public boolean incrementUserAttribute(@NonNull String s, Number i) {
65
+ return false;
66
+ }
67
+
68
+ @Override
69
+ public boolean removeUserAttribute(@NonNull String s) {
70
+ return false;
71
+ }
72
+
73
+ @Override
74
+ public boolean setUserTag(@NonNull String s) {
75
+ return false;
76
+ }
77
+
78
+ @NonNull
79
+ @Override
80
+ public ConsentState getConsentState() {
81
+ return null;
82
+ }
83
+
84
+ @Override
85
+ public void setConsentState(@Nullable ConsentState consentState) {
86
+
87
+ }
88
+
89
+ @Override
90
+ public boolean isLoggedIn() {
91
+ return false;
92
+ }
93
+
94
+ @Override
95
+ public long getFirstSeenTime() {
96
+ return 0;
97
+ }
98
+
99
+ @Override
100
+ public long getLastSeenTime() {
101
+ return 0;
102
+ }
103
+
104
+ @Override
105
+ public AudienceTask<AudienceResponse> getUserAudiences() {
106
+ return null;
107
+ }
108
+ }
109
+
@@ -0,0 +1,203 @@
1
+ package com.mparticle.react.testutils;
2
+
3
+ import androidx.annotation.NonNull;
4
+
5
+ import com.facebook.react.bridge.Dynamic;
6
+ import com.facebook.react.bridge.DynamicFromObject;
7
+ import com.facebook.react.bridge.ReadableArray;
8
+ import com.facebook.react.bridge.ReadableMap;
9
+ import com.facebook.react.bridge.ReadableMapKeySetIterator;
10
+ import com.facebook.react.bridge.ReadableType;
11
+ import com.facebook.react.bridge.WritableMap;
12
+
13
+ import org.json.JSONException;
14
+ import org.json.JSONObject;
15
+
16
+ import java.util.ArrayList;
17
+ import java.util.Collection;
18
+ import java.util.HashMap;
19
+ import java.util.Iterator;
20
+ import java.util.List;
21
+ import java.util.Map;
22
+
23
+ public class MockMap implements WritableMap {
24
+ private Map map = new HashMap();
25
+
26
+ public MockMap() {}
27
+
28
+ public MockMap(JSONObject jsonObject) throws JSONException {
29
+ Map map = new HashMap();
30
+ Iterator<String> keys = jsonObject.keys();
31
+ while(keys.hasNext()) {
32
+ String key = keys.next();
33
+ map.put(key, jsonObject.get(key));
34
+ }
35
+ this.map = map;
36
+ }
37
+
38
+ public MockMap(Map map) {
39
+ this.map = map;
40
+ }
41
+
42
+ @Override
43
+ public boolean hasKey(String name) {
44
+ return map.containsKey(name);
45
+ }
46
+
47
+ @Override
48
+ public boolean isNull(String name) {
49
+ return map.get(name) == null;
50
+ }
51
+
52
+ @Override
53
+ public boolean getBoolean(String name) {
54
+ return (boolean) map.get(name);
55
+ }
56
+
57
+ @Override
58
+ public double getDouble(String name) {
59
+ return (double) map.get(name);
60
+ }
61
+
62
+ @Override
63
+ public int getInt(String name) {
64
+ return (int) map.get(name);
65
+ }
66
+
67
+ @Override
68
+ public long getLong(String name) {
69
+ return (long) map.get(name);
70
+ }
71
+
72
+ @Override
73
+ public String getString(String name) {
74
+ return (String) map.get(name);
75
+ }
76
+
77
+ @Override
78
+ public ReadableArray getArray(String name) {
79
+ return null;
80
+ }
81
+
82
+ @Override
83
+ public ReadableMap getMap(String name) {
84
+ return new MockMap((Map) map.get(name));
85
+ }
86
+
87
+ @Override
88
+ public ReadableType getType(String name) {
89
+ Object obj = map.get(name);
90
+ if (obj instanceof String) {
91
+ return ReadableType.String;
92
+ }
93
+ if (obj instanceof Number) {
94
+ return ReadableType.Number;
95
+ }
96
+ if (obj instanceof Collection) {
97
+ return ReadableType.Array;
98
+ }
99
+ if (obj instanceof Map) {
100
+ return ReadableType.Map;
101
+ }
102
+ if (obj instanceof Boolean) {
103
+ return ReadableType.Boolean;
104
+ }
105
+ if (obj == null) {
106
+ return ReadableType.Null;
107
+ }
108
+ return null;
109
+ }
110
+
111
+ @Override
112
+ public ReadableMapKeySetIterator keySetIterator() {
113
+ return new MockReadableMapKeySetIterator(map.keySet());
114
+ }
115
+
116
+ @Override
117
+ public java.util.HashMap<String, Object> toHashMap() {
118
+ return new java.util.HashMap<>(map);
119
+ }
120
+
121
+ @Override
122
+ public void putNull(String key) {
123
+ map.put(key, null);
124
+ }
125
+
126
+ @Override
127
+ public void putBoolean(String key, boolean value) {
128
+ map.put(key, value);
129
+ }
130
+
131
+ @Override
132
+ public void putDouble(String key, double value) {
133
+ map.put(key, value);
134
+ }
135
+
136
+ @Override
137
+ public void putInt(String key, int value) {
138
+ map.put(key, value);
139
+ }
140
+
141
+ @Override
142
+ public void putLong(String key, long value) {
143
+ map.put(key, value);
144
+ }
145
+
146
+ @Override
147
+ public void putString(String key, String value) {
148
+ map.put(key, value);
149
+ }
150
+
151
+ @Override
152
+ public void putArray(String key, ReadableArray value) {
153
+ map.put(key, value);
154
+ }
155
+
156
+ @Override
157
+ public void putMap(String key, ReadableMap value) {
158
+ map.put(key, value);
159
+ }
160
+
161
+ @Override
162
+ public void merge(ReadableMap source) {
163
+ throw new RuntimeException("Not Implemented");
164
+ }
165
+
166
+ @Override
167
+ public WritableMap copy() {
168
+ return new MockMap(new java.util.HashMap<>(map));
169
+ }
170
+
171
+ @NonNull
172
+ @Override
173
+ public Iterator<Map.Entry<String, Object>> getEntryIterator() {
174
+ return map.entrySet().iterator();
175
+ }
176
+
177
+ @NonNull
178
+ @Override
179
+ public Dynamic getDynamic(@NonNull String s) {
180
+ return new DynamicFromObject(map.get(s));
181
+ }
182
+
183
+ class MockReadableMapKeySetIterator implements ReadableMapKeySetIterator {
184
+ List<String> keys;
185
+ int index = 0;
186
+
187
+ MockReadableMapKeySetIterator(Collection<String> keys) {
188
+ this.keys = new ArrayList(keys);
189
+ }
190
+
191
+ @Override
192
+ public boolean hasNextKey() {
193
+ return index < keys.size();
194
+ }
195
+
196
+ @Override
197
+ public String nextKey() {
198
+ String val = keys.get(index);
199
+ index++;
200
+ return val;
201
+ }
202
+ }
203
+ }
@@ -0,0 +1,68 @@
1
+ package com.mparticle.react.testutils;
2
+
3
+ import com.facebook.react.bridge.ReadableArray;
4
+ import com.facebook.react.bridge.ReadableMap;
5
+ import com.facebook.react.bridge.ReadableType;
6
+
7
+ public class MockReadableArray implements ReadableArray {
8
+
9
+ @Override
10
+ public int size() {
11
+ return 0;
12
+ }
13
+
14
+ @Override
15
+ public boolean isNull(int index) {
16
+ return false;
17
+ }
18
+
19
+ @Override
20
+ public boolean getBoolean(int index) {
21
+ return false;
22
+ }
23
+
24
+ @Override
25
+ public double getDouble(int index) {
26
+ return 0;
27
+ }
28
+
29
+ @Override
30
+ public int getInt(int index) {
31
+ return 0;
32
+ }
33
+
34
+ @Override
35
+ public long getLong(int index) {
36
+ return 0;
37
+ }
38
+
39
+ @Override
40
+ public String getString(int index) {
41
+ return null;
42
+ }
43
+
44
+ @Override
45
+ public ReadableArray getArray(int index) {
46
+ return null;
47
+ }
48
+
49
+ @Override
50
+ public ReadableMap getMap(int index) {
51
+ return null;
52
+ }
53
+
54
+ @Override
55
+ public ReadableType getType(int index) {
56
+ return null;
57
+ }
58
+
59
+ @Override
60
+ public com.facebook.react.bridge.Dynamic getDynamic(int index) {
61
+ return null;
62
+ }
63
+
64
+ @Override
65
+ public java.util.ArrayList<Object> toArrayList() {
66
+ return new java.util.ArrayList<>();
67
+ }
68
+ }
@@ -0,0 +1,4 @@
1
+ package com.mparticle.react.testutils;
2
+
3
+ public class MockWritableMap {
4
+ }
@@ -0,0 +1,13 @@
1
+ package com.mparticle.react.testutils;
2
+
3
+ public class Mutable<T> {
4
+ public T value;
5
+
6
+ public Mutable() {
7
+ value = null;
8
+ }
9
+
10
+ public Mutable(T t) {
11
+ this.value = t;
12
+ }
13
+ }
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require('./plugin/build/withMParticle');
@@ -19,6 +19,7 @@
19
19
  #import <React/RCTViewManager.h>
20
20
  #import <React/RCTUIManager.h>
21
21
  #import <React/RCTBridge.h>
22
+ #import <os/log.h>
22
23
  #import "RoktEventManager.h"
23
24
 
24
25
  #ifdef RCT_NEW_ARCH_ENABLED
@@ -26,6 +27,25 @@
26
27
  #import <RNMParticle/RNMParticle.h>
27
28
  #endif // RCT_NEW_ARCH_ENABLED
28
29
 
30
+ // os_log for [mParticle-Rokt] diagnostics: visible in production (Console.app, device logs)
31
+ // and does not trigger RCT LogBox/warning UI in debug.
32
+ static os_log_t _rokt_os_log(void) {
33
+ static os_log_t log;
34
+ static dispatch_once_t once;
35
+ dispatch_once(&once, ^{
36
+ log = os_log_create("com.mparticle.react-native", "rokt");
37
+ });
38
+ return log;
39
+ }
40
+
41
+ static void _rokt_log(NSString *format, ...) {
42
+ va_list args;
43
+ va_start(args, format);
44
+ NSString *msg = [[NSString alloc] initWithFormat:format arguments:args];
45
+ va_end(args);
46
+ os_log_with_type(_rokt_os_log(), OS_LOG_TYPE_INFO, "%{public}s", [msg UTF8String]);
47
+ }
48
+
29
49
  @interface RNMPRokt ()
30
50
 
31
51
  @property (nonatomic, nullable) RoktEventManager *eventManager;
@@ -43,11 +63,15 @@ RCT_EXTERN void RCTRegisterModule(Class);
43
63
  }
44
64
 
45
65
  + (void)load {
66
+ _rokt_log(@"[mParticle-Rokt] RNMPRokt module load");
46
67
  RCTRegisterModule(self);
47
68
  }
48
69
 
49
70
  - (dispatch_queue_t)methodQueue
50
71
  {
72
+ BOOL bridgeNil = (self.bridge == nil);
73
+ BOOL uiManagerNil = (self.bridge.uiManager == nil);
74
+ _rokt_log(@"[mParticle-Rokt] methodQueue called, bridge %@, uiManager %@", bridgeNil ? @"nil" : @"non-nil", uiManagerNil ? @"nil" : @"non-nil");
51
75
  return self.bridge.uiManager.methodQueue;
52
76
  }
53
77
 
@@ -58,18 +82,19 @@ RCT_EXTERN void RCTRegisterModule(Class);
58
82
  }
59
83
 
60
84
  #ifdef RCT_NEW_ARCH_ENABLED
61
- // New Architecture Implementation
62
- - (void)selectPlacements:(NSString *)identifer
63
- attributes:(NSDictionary *)attributes
64
- placeholders:(NSDictionary *)placeholders
65
- roktConfig:(JS::NativeMPRokt::RoktConfigType &)roktConfig
66
- fontFilesMap:(NSDictionary *)fontFilesMap
67
- {
68
- NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];
69
-
70
- // Convert JS struct to NSDictionary for internal use
85
+ // Extracts roktConfig fields into an NSDictionary, returning nil when the
86
+ // TurboModule bridge passes a null C++ reference for an omitted optional param.
87
+ // __attribute__((optnone)) is required: &ref != nullptr is UB in C++ and the
88
+ // compiler removes the check at -O2, causing a SIGSEGV in Release builds.
89
+ static NSDictionary * __attribute__((optnone)) safeExtractRoktConfigDict(
90
+ JS::NativeMPRokt::RoktConfigType &roktConfig) {
91
+ if (&roktConfig == nullptr) {
92
+ _rokt_log(@"[mParticle-Rokt] safeExtractRoktConfigDict: roktConfig ref is nullptr, returning nil");
93
+ return nil;
94
+ }
95
+ _rokt_log(@"[mParticle-Rokt] safeExtractRoktConfigDict: extracting config");
71
96
  NSMutableDictionary *roktConfigDict = [[NSMutableDictionary alloc] init];
72
- if (&roktConfig != nullptr && roktConfig.cacheConfig().has_value()) {
97
+ if (roktConfig.cacheConfig().has_value()) {
73
98
  NSMutableDictionary *cacheConfigDict = [[NSMutableDictionary alloc] init];
74
99
  auto cacheConfig = roktConfig.cacheConfig().value();
75
100
  if (cacheConfig.cacheDurationInSeconds().has_value()) {
@@ -79,55 +104,97 @@ RCT_EXTERN void RCTRegisterModule(Class);
79
104
  cacheConfigDict[@"cacheAttributes"] = cacheConfig.cacheAttributes();
80
105
  }
81
106
  roktConfigDict[@"cacheConfig"] = cacheConfigDict;
107
+ _rokt_log(@"[mParticle-Rokt] safeExtractRoktConfigDict: cacheConfig present, keys: %lu", (unsigned long)roktConfigDict.count);
108
+ } else {
109
+ _rokt_log(@"[mParticle-Rokt] safeExtractRoktConfigDict: cacheConfig has no value");
82
110
  }
111
+ _rokt_log(@"[mParticle-Rokt] safeExtractRoktConfigDict: returning dict with %lu keys", (unsigned long)roktConfigDict.count);
112
+ return roktConfigDict;
113
+ }
83
114
 
115
+ // New Architecture Implementation
116
+ - (void)selectPlacements:(NSString *)identifer
117
+ attributes:(NSDictionary *)attributes
118
+ placeholders:(NSDictionary *)placeholders
119
+ roktConfig:(JS::NativeMPRokt::RoktConfigType &)roktConfig
120
+ fontFilesMap:(NSDictionary *)fontFilesMap
121
+ {
122
+ _rokt_log(@"[mParticle-Rokt] New Architecture Implementation");
123
+ NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];
124
+
125
+ NSDictionary *roktConfigDict = safeExtractRoktConfigDict(roktConfig);
84
126
  MPRoktConfig *config = [self buildRoktConfigFromDict:roktConfigDict];
85
127
  #else
86
128
  // Old Architecture Implementation
87
129
  RCT_EXPORT_METHOD(selectPlacements:(NSString *) identifer attributes:(NSDictionary *)attributes placeholders:(NSDictionary * _Nullable)placeholders roktConfig:(NSDictionary * _Nullable)roktConfig fontFilesMap:(NSDictionary * _Nullable)fontFilesMap)
88
130
  {
131
+ _rokt_log(@"[mParticle-Rokt] Old Architecture Implementation");
89
132
  NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];
90
133
  MPRoktConfig *config = [self buildRoktConfigFromDict:roktConfig];
91
134
  #endif
92
135
 
136
+ _rokt_log(@"[mParticle-Rokt] selectPlacements called with identifier: %@, attributes count: %lu", identifer, (unsigned long)finalAttributes.count);
137
+
93
138
  [MParticle _setWrapperSdk_internal:MPWrapperSdkReactNative version:@""];
94
139
  // Create callback implementation
95
140
  MPRoktEventCallback *callbacks = [[MPRoktEventCallback alloc] init];
96
-
97
141
  __weak __typeof__(self) weakSelf = self;
98
142
 
99
143
  callbacks.onLoad = ^{
100
- [self.eventManager onRoktCallbackReceived:@"onLoad"];
144
+ _rokt_log(@"[mParticle-Rokt] onLoad");
145
+ [weakSelf.eventManager onRoktCallbackReceived:@"onLoad"];
101
146
  };
102
147
 
103
148
  callbacks.onUnLoad = ^{
104
- [self.eventManager onRoktCallbackReceived:@"onUnLoad"];
105
- RCTLogInfo(@"unloaded");
149
+ _rokt_log(@"[mParticle-Rokt] onUnLoad");
150
+ [weakSelf.eventManager onRoktCallbackReceived:@"onUnLoad"];
106
151
  };
107
152
 
108
153
  callbacks.onShouldShowLoadingIndicator = ^{
109
- [self.eventManager onRoktCallbackReceived:@"onShouldShowLoadingIndicator"];
154
+ _rokt_log(@"[mParticle-Rokt] onShouldShowLoadingIndicator");
155
+ [weakSelf.eventManager onRoktCallbackReceived:@"onShouldShowLoadingIndicator"];
110
156
  };
111
157
 
112
158
  callbacks.onShouldHideLoadingIndicator = ^{
113
- [self.eventManager onRoktCallbackReceived:@"onShouldHideLoadingIndicator"];
159
+ _rokt_log(@"[mParticle-Rokt] onShouldHideLoadingIndicator");
160
+ [weakSelf.eventManager onRoktCallbackReceived:@"onShouldHideLoadingIndicator"];
114
161
  };
115
162
 
116
163
  callbacks.onEmbeddedSizeChange = ^(NSString *placementId, CGFloat height) {
117
- [self.eventManager onWidgetHeightChanges:height placement:placementId];
164
+ _rokt_log(@"[mParticle-Rokt] onEmbeddedSizeChange");
165
+ [weakSelf.eventManager onWidgetHeightChanges:height placement:placementId];
118
166
  };
119
167
 
168
+ BOOL bridgeNil = (self.bridge == nil);
169
+ BOOL uiManagerNil = (self.bridge.uiManager == nil);
170
+ _rokt_log(@"[mParticle-Rokt] bridge %@, uiManager %@", bridgeNil ? @"nil" : @"non-nil", uiManagerNil ? @"nil" : @"non-nil");
171
+
172
+ if (bridgeNil || uiManagerNil) {
173
+ _rokt_log(@"[mParticle-Rokt] addUIBlock skipped: self.bridge%@ is nil. selectPlacements will not be called. This can occur in New Architecture bridgeless production builds.", bridgeNil ? @"" : @".uiManager");
174
+ } else {
175
+ _rokt_log(@"[mParticle-Rokt] queuing addUIBlock for identifier: %@", identifer);
176
+ }
120
177
  [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *,UIView *> *viewRegistry) {
121
- NSMutableDictionary *nativePlaceholders = [self getNativePlaceholders:placeholders viewRegistry:viewRegistry];
178
+ __strong __typeof__(weakSelf) strongSelf = weakSelf;
179
+ _rokt_log(@"[mParticle-Rokt] addUIBlock executing for identifier: %@, viewRegistry count: %lu", identifer, (unsigned long)viewRegistry.count);
180
+
181
+ NSMutableDictionary *nativePlaceholders = strongSelf ? [strongSelf getNativePlaceholders:placeholders viewRegistry:viewRegistry] : [NSMutableDictionary dictionary];
122
182
 
123
- [self subscribeViewEvents:identifer];
183
+ if (strongSelf) {
184
+ [strongSelf subscribeViewEvents:identifer];
185
+ }
124
186
 
187
+ id mpInstance = [MParticle sharedInstance];
188
+ id roktKit = mpInstance ? [mpInstance rokt] : nil;
189
+ _rokt_log(@"[mParticle-Rokt] MParticle sharedInstance %@, rokt kit %@", mpInstance ? @"non-nil" : @"nil", roktKit ? @"non-nil" : @"nil");
190
+ _rokt_log(@"[mParticle-Rokt] calling mParticle Core selectPlacements for: %@", identifer);
125
191
  [[[MParticle sharedInstance] rokt] selectPlacements:identifer
126
192
  attributes:finalAttributes
127
193
  embeddedViews:nativePlaceholders
128
194
  config:config
129
195
  callbacks:callbacks];
130
196
  }];
197
+ _rokt_log(@"[mParticle-Rokt] addUIBlock enqueued for identifier: %@", identifer);
131
198
  }
132
199
 
133
200
  RCT_EXPORT_METHOD(purchaseFinalized : (NSString *)placementId catalogItemId : (
@@ -166,6 +233,7 @@ RCT_EXPORT_METHOD(purchaseFinalized : (NSString *)placementId catalogItemId : (
166
233
  }
167
234
 
168
235
  - (MPRoktConfig *)buildRoktConfigFromDict:(NSDictionary<NSString *, id> *)configMap {
236
+ _rokt_log(@"[mParticle-Rokt] buildRoktConfigFromDict: configMap %@", configMap == nil ? @"nil" : [NSString stringWithFormat:@"non-nil (%lu keys)", (unsigned long)configMap.count]);
169
237
  MPRoktConfig *config = [[MPRoktConfig alloc] init];
170
238
  BOOL isConfigEmpty = YES;
171
239
 
@@ -198,11 +266,13 @@ RCT_EXPORT_METHOD(purchaseFinalized : (NSString *)placementId catalogItemId : (
198
266
  config.cacheDuration = cacheDuration;
199
267
  }
200
268
 
269
+ _rokt_log(@"[mParticle-Rokt] buildRoktConfigFromDict: returning %@", isConfigEmpty ? @"nil" : @"config");
201
270
  return isConfigEmpty ? nil : config;
202
271
  }
203
272
 
204
273
  - (void)subscribeViewEvents:(NSString* _Nonnull) viewName
205
274
  {
275
+ _rokt_log(@"[mParticle-Rokt] subscribeViewEvents for viewName: %@", viewName);
206
276
  if (self.eventManager == nil) {
207
277
  self.eventManager = [RoktEventManager allocWithZone: nil];
208
278
  }
@@ -213,6 +283,7 @@ RCT_EXPORT_METHOD(purchaseFinalized : (NSString *)placementId catalogItemId : (
213
283
 
214
284
  - (NSMutableDictionary *)getNativePlaceholders:(NSDictionary *)placeholders viewRegistry:(NSDictionary<NSNumber *, UIView *> *)viewRegistry
215
285
  {
286
+ _rokt_log(@"[mParticle-Rokt] getNativePlaceholders: placeholders %lu, viewRegistry %lu", (unsigned long)placeholders.count, (unsigned long)viewRegistry.count);
216
287
  NSMutableDictionary *nativePlaceholders = [[NSMutableDictionary alloc]initWithCapacity:placeholders.count];
217
288
 
218
289
  for(id key in placeholders){
@@ -234,12 +305,14 @@ RCT_EXPORT_METHOD(purchaseFinalized : (NSString *)placementId catalogItemId : (
234
305
  #endif // RCT_NEW_ARCH_ENABLED
235
306
  }
236
307
 
308
+ _rokt_log(@"[mParticle-Rokt] getNativePlaceholders: resolved %lu native placeholder(s)", (unsigned long)nativePlaceholders.count);
237
309
  return nativePlaceholders;
238
310
  }
239
311
 
240
312
  #ifdef RCT_NEW_ARCH_ENABLED
241
313
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params {
242
314
  self.bridge = params.instance.bridge;
315
+ _rokt_log(@"[mParticle-Rokt] getTurboModule: bridge set to %@", self.bridge == nil ? @"nil" : @"non-nil");
243
316
  return std::make_shared<facebook::react::NativeMPRoktSpecJSI>(params);
244
317
  }
245
318
  #endif // RCT_NEW_ARCH_ENABLED
@@ -163,7 +163,8 @@ RCT_EXPORT_METHOD(getUserAttributes:(NSString *)mpid callback:(RCTResponseSender
163
163
  {
164
164
  MParticleUser *selectedUser = [[MParticleUser alloc] init];
165
165
  selectedUser.userId = [NSNumber numberWithLong:mpid.longLongValue];
166
- callback(@[[NSNull null], [selectedUser userAttributes]]);
166
+ NSDictionary *attributes = [selectedUser userAttributes] ?: @{};
167
+ callback(@[[NSNull null], attributes]);
167
168
  }
168
169
 
169
170
  RCT_EXPORT_METHOD(setUserTag:(NSString *)mpid tag:(NSString *)tag)