Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:

example-ios:
name: Build Example iOS App
runs-on: macos-latest
runs-on: macos-15
defaults:
run:
working-directory: ./example
Expand All @@ -96,14 +96,16 @@ jobs:
uses: actions/setup-node@v4
with:
node-version: 22
- name: Select Xcode Version
run: sudo xcode-select -s /Applications/Xcode_16.4.app
- name: Install Cordova
run: npm install -g cordova
- name: Install Dependencies
run: npm ci
- name: Add iOS Platform
run: cordova platform add ios
- name: Build iOS
run: cordova build ios
run: cordova build ios --verbose

pr-notify:
if: >
Expand Down
4 changes: 4 additions & 0 deletions example/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@

<!-- Platform-specific file copy hook -->
<hook type="after_platform_add" src="hooks/after_platform_add/010_copy_platform_specific_files.js" />
<!-- Run pod install for iOS -->
<hook type="after_platform_add" src="hooks/after_platform_add/020_run_pod_install.js" />
<!-- Update Android Gradle dependencies -->
<hook type="after_platform_add" src="hooks/after_platform_add/030_update_android_gradle.js" />
<plugin name="cordova-plugin-mparticle" spec="../plugin" />
</widget>
45 changes: 45 additions & 0 deletions example/hooks/after_platform_add/020_run_pod_install.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env node

var shell = require('child_process');
var path = require('path');
var fs = require('fs');

module.exports = function(context) {
// Skip if not iOS
if (context.opts.platforms.indexOf('ios') === -1) {
return;
}

console.log('Setting up iOS pods...');

// Get the paths
var iosPath = path.join(context.opts.projectRoot, 'platforms', 'ios');
var customPodfilePath = path.join(context.opts.projectRoot, 'platform_overrides', 'ios', 'Podfile');
var platformPodfilePath = path.join(iosPath, 'Podfile');

return new Promise((resolve, reject) => {
// Copy custom Podfile if it exists
if (fs.existsSync(customPodfilePath)) {
try {
fs.copyFileSync(customPodfilePath, platformPodfilePath);
console.log('Copied custom Podfile');
} catch (error) {
console.error('Error copying Podfile: ' + error);
reject(error);
return;
}
}

// Run pod install
shell.exec('pod install', { cwd: iosPath }, function(error, stdout, stderr) {
if (error) {
console.error('Error running pod install: ' + error);
console.error('stderr: ' + stderr);
reject(error);
return;
}
console.log('pod install output: ' + stdout);
resolve();
});
});
};
32 changes: 32 additions & 0 deletions example/hooks/after_platform_add/030_update_android_gradle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env node

var fs = require('fs');
var path = require('path');

module.exports = function(context) {
// Skip if not Android
if (context.opts.platforms.indexOf('android') === -1) {
return;
}

console.log('Copying Android build-extras.gradle...');

// Source and destination paths
var srcFile = path.join(context.opts.projectRoot, 'platform_overrides', 'android', 'build-extras.gradle');
var destFile = path.join(context.opts.projectRoot, 'platforms', 'android', 'app', 'build-extras.gradle');

try {
// Ensure the source file exists
if (!fs.existsSync(srcFile)) {
console.error('build-extras.gradle not found in platform_overrides');
return;
}

// Copy the file
fs.copyFileSync(srcFile, destFile);
console.log('Successfully copied build-extras.gradle to platform directory');
} catch (error) {
console.error('Error copying build-extras.gradle:', error);
throw error;
}
};
3 changes: 3 additions & 0 deletions example/platform_overrides/android/build-extras.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dependencies {
implementation 'com.mparticle:android-rokt-kit:5.71.0'
}
6 changes: 6 additions & 0 deletions example/platform_overrides/ios/Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
platform :ios, '12.0'
use_frameworks!

target 'MParticleExample' do
pod 'mParticle-Rokt', '8.2.0'
end
18 changes: 18 additions & 0 deletions example/www/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,21 @@ h1 {
animation:fade 3000ms infinite;
-webkit-animation:fade 3000ms infinite;
}

.button {
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
border-radius: 4px;
}

.button:hover {
background-color: #45a049;
}
1 change: 1 addition & 0 deletions example/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ <h1>Apache Cordova</h1>
<p class="event listening">Connecting to Device</p>
<p class="event received">Device is Ready</p>
</div>
<button id="selectPlacementsBtn" class="button">Select Placements</button>
</div>
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="js/index.js"></script>
Expand Down
35 changes: 33 additions & 2 deletions example/www/js/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
document.getElementById("selectPlacementsBtn").addEventListener('click', selectPlacements, false);

var app = {
// Application Constructor
initialize: function() {
Expand Down Expand Up @@ -32,15 +34,17 @@ var app = {

user.setUserAttribute(mparticle.UserAttributeType.FirstName, 'Cordova Test first name');
user.setUserAttributeArray(mparticle.UserAttributeType.FirstName, ['Cordova Test value 1', 'Cordova Test value 2']);
user.setUserTag('Cordova testUser');

// TODO: Uncomment this when a new version of mparticle-apple-integration-rokt is released
// user.setUserTag('Cordova testUser');
user.removeUserAttribute(mparticle.UserAttributeType.FirstName);
user.getUserIdentities(function(userIdenitities) {
console.log('User userIdentities: ' + userIdenitities);
});
});

var request = new mparticle.IdentityRequest();
request.setEmail('cordova123@gmail.com');
request.setEmail('j.smith@example.com');

identity.login(request, function (userID) {
console.log('Login Success: ' + userID);
Expand Down Expand Up @@ -78,4 +82,31 @@ var app = {
}
};

function selectPlacements() {
console.log('MParticleCordova Plugin Example: Selecting Placements');

var attributes = {
'email': 'j.smith@example.com',
'firstname': 'Jenny',
'lastname': 'Smith',
'billingzipcode': '90210',
'confirmationref': '54321'
};

var config = {
colorMode: mparticle.RoktColorMode.SYSTEM,
cacheConfig: {
cacheDurationInSeconds: 5400,
cacheAttributes: {}
},
edgeToEdgeDisplay: true
};

mparticle.selectPlacements(
'MSDKOverlayLayout',
attributes,
config
);
}

app.initialize();
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import com.mparticle.consent.GDPRConsent;
import com.mparticle.identity.*;
import com.mparticle.internal.Logger;
import com.mparticle.rokt.RoktConfig;
import com.mparticle.rokt.CacheConfig;

import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
Expand Down Expand Up @@ -91,6 +93,9 @@ public boolean execute(String action, final JSONArray args, final CallbackContex
} else if (action.equals("removeCCPAConsentState")) {
removeCCPAConsentState(args);
return true;
} else if (action.equals("selectPlacements")) {
selectPlacements(args);
return true;
} else {
return false;
}
Expand Down Expand Up @@ -403,6 +408,40 @@ public void removeCCPAConsentState(final JSONArray state) throws JSONException {
}
}

public void selectPlacements(final JSONArray args) throws JSONException {
final String identifier = args.getString(0);
final JSONObject attributesMap = args.getJSONObject(1);
final JSONObject configMap = args.getJSONObject(2);


final Map<String, String> attributes = ConvertStringMap(attributesMap);

final RoktConfig.ColorMode colorMode = RoktConfig.ColorMode.valueOf(configMap.getJSONObject("colorMode").getString("value"));
Comment thread
jamesnrokt marked this conversation as resolved.

final JSONObject cacheConfigMap = configMap.getJSONObject("cacheConfig");
final CacheConfig cacheConfig = new CacheConfig(
cacheConfigMap.getLong("cacheDurationInSeconds"),
ConvertStringMap(cacheConfigMap.getJSONObject("cacheAttributes"))
);

final boolean edgeToEdgeDisplay = configMap.getBoolean("edgeToEdgeDisplay");

final RoktConfig roktConfig = new RoktConfig.Builder()
.colorMode(colorMode)
.cacheConfig(cacheConfig)
.edgeToEdgeDisplay(edgeToEdgeDisplay)
.build();

MParticle.getInstance().Rokt().selectPlacements(
identifier,
attributes,
null, // callbacks not used in Cordova
null, // embeddedViews not used in Cordova
null, // fontTypefaces not used in Cordova
roktConfig
);
}

private static IdentityApiRequest ConvertIdentityAPIRequest(JSONObject map) throws JSONException {
IdentityApiRequest.Builder identityRequest = IdentityApiRequest.withEmptyUser();

Expand Down
34 changes: 34 additions & 0 deletions plugin/src/ios/CDVMParticle.m
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,40 @@ - (void)getUserIdentities:(CDVInvokedUrlCommand*)command {
}];
}

- (void)selectPlacements:(CDVInvokedUrlCommand*)command {
[self.commandDelegate runInBackground:^{
NSString *identifier = [command.arguments objectAtIndex:0];
NSDictionary *attributes = [command.arguments objectAtIndex:1];
NSDictionary *configDict = [command.arguments objectAtIndex:2];

MPRoktConfig *config = [[MPRoktConfig alloc] init];

NSString *colorModeStr = configDict[@"colorMode"][@"value"];
if ([colorModeStr isEqualToString:@"LIGHT"]) {
config.colorMode = MPColorModeLight;
} else if ([colorModeStr isEqualToString:@"DARK"]) {
config.colorMode = MPColorModeDark;
} else {
config.colorMode = MPColorModeSystem;
}

NSDictionary *cacheConfig = configDict[@"cacheConfig"];
if (cacheConfig) {
config.cacheDuration = @([cacheConfig[@"cacheDurationInSeconds"] longLongValue]);
config.cacheAttributes = cacheConfig[@"cacheAttributes"];
Comment thread
jamesnrokt marked this conversation as resolved.
}

[[MParticle sharedInstance].rokt selectPlacements:identifier
attributes:attributes
embeddedViews:nil
config:config
callbacks:nil];

CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}];
}

typedef NS_ENUM(NSUInteger, MPCDVCommerceEventAction) {
MPCDVCommerceEventActionAddToCart = 1,
MPCDVCommerceEventActionRemoveFromCart,
Expand Down
42 changes: 42 additions & 0 deletions plugin/www/mparticle.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,48 @@ var mparticle = {
this.hardwareId = hardwareId
return this
}
},

RoktColorMode: {
LIGHT: 'LIGHT',
DARK: 'DARK',
SYSTEM: 'SYSTEM'
},

validateRoktColorMode: function (colorMode) {
var validColorModes = Object.values(this.RoktColorMode)
if (!validColorModes.includes(colorMode)) {
console.error('Invalid color mode value: ' + colorMode + '. Must be one of: ' + validColorModes.join(', '))
return this.RoktColorMode.SYSTEM
}
return colorMode
},

selectPlacements: function (identifier, attributes, config) {
var defaultConfig = {
colorMode: this.RoktColorMode.SYSTEM,
cacheConfig: {
cacheDurationInSeconds: 5400,
cacheAttributes: {}
},
edgeToEdgeDisplay: true
}

var requestedColorMode = (config && config.colorMode) || defaultConfig.colorMode
requestedColorMode = this.validateRoktColorMode(requestedColorMode)

var finalConfig = {
colorMode: {
value: requestedColorMode
},
cacheConfig: {
cacheDurationInSeconds: (config && config.cacheConfig && config.cacheConfig.cacheDurationInSeconds) || defaultConfig.cacheConfig.cacheDurationInSeconds,
cacheAttributes: (config && config.cacheConfig && config.cacheConfig.cacheAttributes) || defaultConfig.cacheConfig.cacheAttributes
},
edgeToEdgeDisplay: (config && config.edgeToEdgeDisplay !== undefined) ? config.edgeToEdgeDisplay : defaultConfig.edgeToEdgeDisplay
}

exec('selectPlacements', [identifier, attributes || {}, finalConfig])
}
}

Expand Down