Skip to content

Commit 0bfa737

Browse files
committed
Implement Rokt integration in React Native SDK
- Added Rokt module for placement selection in both Android and iOS. - Updated TypeScript definitions and JavaScript interface for Rokt functionality. - Modified sample app to demonstrate Rokt placement selection. - Updated build configurations and dependencies for compatibility with new features.
1 parent 96558c0 commit 0bfa737

File tree

21 files changed

+802
-25
lines changed

21 files changed

+802
-25
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,6 @@ build
7979
.gradle
8080
local.properties
8181
package-lock.json
82+
83+
# TypeScript build output
84+
lib/

.npmignore

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,17 @@ yarn-error.log*
5252
*.dylib
5353
*.dll
5454

55-
# Add this line to your .npmignore file
56-
package-lock.json
55+
# Development files
56+
package-lock.json
57+
yarn.lock
58+
tsconfig.json
59+
release.sh
60+
61+
# TypeScript source files (compiled to lib/)
62+
js/
63+
64+
# Development and test files
65+
**/*.test.ts
66+
**/*.test.tsx
67+
**/*.spec.ts
68+
**/*.spec.tsx

android/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
buildscript {
2+
ext.kotlin_version = "1.8.21"
23
repositories {
34
mavenCentral()
45
google()
56
}
67
dependencies {
78
classpath 'com.android.tools.build:gradle:8.1.4'
9+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
810
}
911
}
1012

@@ -36,6 +38,7 @@ def supportsNamespace() {
3638

3739
// apply plugin: 'org.jlleitschuh.gradle.ktlint'
3840
apply plugin: 'com.android.library'
41+
apply plugin: 'kotlin-android'
3942

4043
android {
4144
if (supportsNamespace()) {

android/src/main/java/com/mparticle/react/MParticlePackage.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.facebook.react.bridge.NativeModule;
66
import com.facebook.react.bridge.ReactApplicationContext;
77
import com.facebook.react.uimanager.ViewManager;
8+
import com.mparticle.react.rokt.MPRoktModule;
89

910
import java.util.ArrayList;
1011
import java.util.Collections;
@@ -17,6 +18,7 @@ public List<NativeModule> createNativeModules(
1718
List<NativeModule> modules = new ArrayList<>();
1819

1920
modules.add(new MParticleModule(reactContext));
21+
modules.add(new MPRoktModule(reactContext));
2022

2123
return modules;
2224
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.mparticle.react.rokt
2+
3+
import com.facebook.common.logging.FLog
4+
import com.facebook.react.bridge.ReactApplicationContext
5+
import com.facebook.react.bridge.ReactContextBaseJavaModule
6+
import com.facebook.react.bridge.ReactMethod
7+
import com.facebook.react.bridge.ReadableMap
8+
import com.facebook.react.util.RCTLog
9+
import com.mparticle.MParticle
10+
import com.mparticle.internal.KitManager
11+
import com.mparticle.rokt.CacheConfig
12+
import com.mparticle.rokt.RoktConfig
13+
14+
class MPRoktModule(private val reactContext: ReactApplicationContext) :
15+
ReactContextBaseJavaModule(reactContext) {
16+
17+
override fun getName(): String = "MPRokt"
18+
19+
@ReactMethod
20+
fun selectPlacements(
21+
identifier: String,
22+
attributes: ReadableMap?,
23+
placeholders: ReadableMap?,
24+
roktConfig: ReadableMap?,
25+
fontFilesMap: ReadableMap?,
26+
) {
27+
val finalAttributes = readableMapToMapOfStrings(attributes)
28+
val config = buildRoktConfig(roktConfig)
29+
MParticle.getInstance()?.Rokt()?.selectPlacements(
30+
identifier = identifier,
31+
attributes = finalAttributes,
32+
callbacks = null,
33+
embeddedViews = null, /*TODO*/
34+
fontTypefaces = null /*TODO*/,
35+
config = config,
36+
)
37+
}
38+
39+
private fun readableMapToMapOfStrings(attributes: ReadableMap?): Map<String, String> =
40+
attributes?.toHashMap()?.filter { it.value is String }?.mapValues { it.value as String }
41+
?: emptyMap()
42+
43+
private fun String.toColorMode(): RoktConfig.ColorMode = when (this) {
44+
"dark" -> RoktConfig.ColorMode.DARK
45+
"light" -> RoktConfig.ColorMode.LIGHT
46+
else -> RoktConfig.ColorMode.SYSTEM
47+
}
48+
49+
private fun buildRoktConfig(roktConfig: ReadableMap?): RoktConfig {
50+
val builder = RoktConfig.Builder()
51+
val configMap: Map<String, String> = readableMapToMapOfStrings(roktConfig)
52+
configMap["colorMode"]?.let {
53+
builder.colorMode(it.toColorMode())
54+
}
55+
roktConfig?.getMap("cacheConfig")?.let {
56+
builder.cacheConfig(buildCacheConfig(it))
57+
}
58+
return builder.build()
59+
}
60+
61+
private fun buildCacheConfig(cacheConfigMap: ReadableMap?): CacheConfig {
62+
val cacheDurationInSeconds =
63+
if (cacheConfigMap?.hasKey("cacheDurationInSeconds") == true) {
64+
cacheConfigMap.getDouble("cacheDurationInSeconds").toLong()
65+
} else {
66+
0L
67+
}
68+
val cacheAttributes =
69+
if (cacheConfigMap?.hasKey("cacheAttributes") == true) {
70+
cacheConfigMap.getMap("cacheAttributes")?.toHashMap()?.mapValues { it.value as String }
71+
} else {
72+
null
73+
}
74+
return CacheConfig(
75+
cacheDurationInSeconds = cacheDurationInSeconds,
76+
cacheAttributes = cacheAttributes,
77+
)
78+
}
79+
}

ios/RNMParticle/RNMPRokt.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#import <Foundation/Foundation.h>
2+
#import <React/RCTBridge.h>
3+
4+
@interface RNMPRokt : NSObject <RCTBridgeModule>
5+
6+
@end

ios/RNMParticle/RNMPRokt.m

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#import "RNMPRokt.h"
2+
#if defined(__has_include) && __has_include(<mParticle_Apple_SDK/mParticle.h>)
3+
#import <mParticle_Apple_SDK/mParticle.h>
4+
#elif defined(__has_include) && __has_include(<mParticle_Apple_SDK_NoLocation/mParticle.h>)
5+
#import <mParticle_Apple_SDK_NoLocation/mParticle.h>
6+
#else
7+
#import "mParticle.h"
8+
#endif
9+
#if defined(__has_include) && __has_include(<mParticle_Apple_SDK/mParticle_Apple_SDK-Swift.h>)
10+
#import <mParticle_Apple_SDK/mParticle_Apple_SDK-Swift.h>
11+
#elif defined(__has_include) && __has_include(<mParticle_Apple_SDK_NoLocation/mParticle_Apple_SDK-Swift.h>)
12+
#import <mParticle_Apple_SDK_NoLocation/mParticle_Apple_SDK-Swift.h>
13+
#else
14+
#import "mParticle_Apple_SDK-Swift.h"
15+
#endif
16+
#import <React/RCTConvert.h>
17+
18+
@implementation RNMPRokt
19+
20+
RCT_EXTERN void RCTRegisterModule(Class);
21+
22+
+ (NSString *)moduleName {
23+
return @"MPRokt";
24+
}
25+
26+
+ (void)load {
27+
RCTRegisterModule(self);
28+
}
29+
30+
RCT_EXPORT_METHOD(selectPlacements:(NSString *) identifer attributes:(NSDictionary *)attributes placeholders:(NSDictionary * _Nullable)placeholders roktConfig:(NSDictionary * _Nullable)roktConfig fontFilesMap:(NSDictionary * _Nullable)fontFilesMap)
31+
{
32+
NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];
33+
MPRoktConfig *config = [self buildRoktConfigFromDict:roktConfig];
34+
// TODO: Add placeholders and fontFilesMap
35+
[[[MParticle sharedInstance] rokt] selectPlacements:identifer attributes:finalAttributes];
36+
}
37+
38+
- (NSMutableDictionary*)convertToMutableDictionaryOfStrings:(NSDictionary*)attributes
39+
{
40+
NSMutableDictionary *finalAttributes = [attributes mutableCopy];
41+
NSArray *keysForNullValues = [finalAttributes allKeysForObject:[NSNull null]];
42+
[finalAttributes removeObjectsForKeys:keysForNullValues];
43+
44+
NSSet *keys = [finalAttributes keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) {
45+
return ![obj isKindOfClass:[NSString class]];
46+
}];
47+
48+
[finalAttributes removeObjectsForKeys:[keys allObjects]];
49+
return finalAttributes;
50+
51+
}
52+
53+
- (MPColorMode)stringToColorMode:(NSString*)colorString
54+
{
55+
if ([colorString isEqualToString:@"light"]) {
56+
return MPColorModeLight;
57+
}
58+
else if ([colorString isEqualToString:@"dark"]) {
59+
return MPColorModeDark;
60+
}
61+
else {
62+
return MPColorModeSystem;
63+
}
64+
}
65+
66+
- (MPRoktConfig *)buildRoktConfigFromDict:(NSDictionary<NSString *, id> *)configMap {
67+
MPRoktConfig *config = [[MPRoktConfig alloc] init];
68+
BOOL isConfigEmpty = YES;
69+
70+
NSString *colorModeString = configMap[@"colorMode"];
71+
if (colorModeString && [colorModeString isKindOfClass:[NSString class]]) {
72+
if (@available(iOS 12.0, *)) {
73+
isConfigEmpty = NO;
74+
if ([colorModeString isEqualToString:@"dark"]) {
75+
if (@available(iOS 13.0, *)) {
76+
config.colorMode = MPColorModeDark;
77+
}
78+
} else if ([colorModeString isEqualToString:@"light"]) {
79+
config.colorMode = MPColorModeLight;
80+
} else {
81+
// default: "system"
82+
config.colorMode = MPColorModeSystem;
83+
}
84+
}
85+
}
86+
87+
NSDictionary *cacheConfigMap = configMap[@"cacheConfig"];
88+
if (cacheConfigMap && [cacheConfigMap isKindOfClass:[NSDictionary class]]) {
89+
isConfigEmpty = NO;
90+
NSNumber *cacheDuration = cacheConfigMap[@"cacheDurationInSeconds"];
91+
if (!cacheDuration) {
92+
cacheDuration = @0;
93+
}
94+
NSDictionary<NSString *, NSString *> *cacheAttributes = cacheConfigMap[@"cacheAttributes"];
95+
config.cacheAttributes = cacheAttributes;
96+
config.cacheDuration = cacheDuration;
97+
}
98+
99+
return isConfigEmpty ? nil : config;
100+
}
101+
102+
@end

0 commit comments

Comments
 (0)