Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ jobs:
-only-testing:MParticleSampleTests/RCTConvertCommerceMappingTests \
-only-testing:MParticleSampleTests/RoktNativeLayoutComponentViewSizingTests \
-only-testing:MParticleSampleTests/RNMParticleDuplicateSDKTests \
-only-testing:MParticleSampleTests/RNMPRoktEventMapperTests \
-only-testing:MParticleSampleTests/RNMPRoktConfigFactoryTests \
-only-testing:MParticleSampleTests/RNMPRoktSwiftTests \
| bundle exec xcpretty -k

- name: Archive iOS sample app and check for a single copy of each SDK
Expand Down
2 changes: 2 additions & 0 deletions ios/RNMParticle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
C4A1D2E32F6A000100ABCDEF /* RoktPlaceholderRegistry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoktPlaceholderRegistry.h; sourceTree = "<group>"; };
C4A1D2E42F6A000100ABCDEF /* RoktPlaceholderRegistry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoktPlaceholderRegistry.m; sourceTree = "<group>"; };
C4A1D2E62F6A000100ABCDEF /* RNMPSDKImports.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNMPSDKImports.h; sourceTree = "<group>"; };
C4A1D2E72F6A000100ABCDEF /* RNMPRoktSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNMPRoktSwift.h; sourceTree = "<group>"; };

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not changing this here. ios/RNMParticle.xcodeproj is not a working build path today. On main, before this stack, a standalone build fails, first on its 12.4 deployment target and then on its recursive React header search paths. Its mParticle header paths also point at the old pre-9.x pod layout, and it has none for RoktContracts. The supported integrations build these files through the podspec or Package.swift. Removing the project would be a separate change.

B39BCD942E30562400FC90B8 /* RoktNativeLayoutComponentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoktNativeLayoutComponentView.h; sourceTree = "<group>"; };
B39BCD952E30562400FC90B8 /* RoktNativeLayoutComponentView.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = RoktNativeLayoutComponentView.mm; sourceTree = "<group>"; };
DBDF24D71E007EB1000F3D73 /* libRNMParticle.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNMParticle.a; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -81,6 +82,7 @@
C4A1D2E32F6A000100ABCDEF /* RoktPlaceholderRegistry.h */,
C4A1D2E42F6A000100ABCDEF /* RoktPlaceholderRegistry.m */,
C4A1D2E62F6A000100ABCDEF /* RNMPSDKImports.h */,
C4A1D2E72F6A000100ABCDEF /* RNMPRoktSwift.h */,
B39BCD942E30562400FC90B8 /* RoktNativeLayoutComponentView.h */,
B39BCD952E30562400FC90B8 /* RoktNativeLayoutComponentView.mm */,
B39BCD892E2A06D700FC90B8 /* RNMPRokt.h */,
Expand Down
62 changes: 12 additions & 50 deletions ios/RNMParticle/RNMPRokt.mm
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import "RNMPRokt.h"
#import "RNMPSDKImports.h"
#import "RNMPRoktSwift.h"
#import <React/RCTConvert.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
Expand Down Expand Up @@ -119,14 +120,14 @@ - (void)selectPlacements:(NSString *)identifer
NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];

NSDictionary *roktConfigDict = safeExtractRoktConfigDict(roktConfig);
RoktConfig *config = [self buildRoktConfigFromDict:roktConfigDict];
RoktConfig *config = [RNMPRoktConfigFactory configFromDictionary:roktConfigDict];
#else
// Old Architecture Implementation — selectPlacements
RCT_EXPORT_METHOD(selectPlacements:(NSString *) identifer attributes:(NSDictionary *)attributes placeholders:(NSDictionary * _Nullable)placeholders roktConfig:(NSDictionary * _Nullable)roktConfig fontFilesMap:(NSDictionary * _Nullable)fontFilesMap)
{
_rokt_log(@"[mParticle-Rokt] Old Architecture Implementation");
NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];
RoktConfig *config = [self buildRoktConfigFromDict:roktConfig];
RoktConfig *config = [RNMPRoktConfigFactory configFromDictionary:roktConfig];
#endif

_rokt_log(@"[mParticle-Rokt] selectPlacements called with identifier: %@, attributes count: %lu", identifer, (unsigned long)finalAttributes.count);
Expand Down Expand Up @@ -171,7 +172,7 @@ - (void)selectPlacements:(NSString *)identifer
// Replaced by a newer call with the same identifier, or cancelled by close(): the SDK
// is never called, so report the failure the way the SDK reports a call it rejects.
_rokt_log(@"[mParticle-Rokt] pending selectPlacements dropped for: %@", identifer);
[weakSelf.eventManager onRoktEvents:[[RoktPlacementFailure alloc] initWithIdentifier:nil] viewName:identifer];
[weakSelf.eventManager onRoktEvents:[RNMPRoktEventMapper placementFailure] viewName:identifer];
}];
});
}
Expand All @@ -185,14 +186,14 @@ - (void)selectShoppableAds:(NSString *)identifier
_rokt_log(@"[mParticle-Rokt] selectShoppableAds New Architecture");
NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];
NSDictionary *roktConfigDict = safeExtractRoktConfigDict(roktConfig);
RoktConfig *config = [self buildRoktConfigFromDict:roktConfigDict];
RoktConfig *config = [RNMPRoktConfigFactory configFromDictionary:roktConfigDict];
#else
// Old Architecture Implementation — selectShoppableAds
RCT_EXPORT_METHOD(selectShoppableAds:(NSString *)identifier attributes:(NSDictionary *)attributes roktConfig:(NSDictionary * _Nullable)roktConfig)
{
_rokt_log(@"[mParticle-Rokt] selectShoppableAds Old Architecture");
NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes];
RoktConfig *config = [self buildRoktConfigFromDict:roktConfig];
RoktConfig *config = [RNMPRoktConfigFactory configFromDictionary:roktConfig];
#endif

_rokt_log(@"[mParticle-Rokt] selectShoppableAds called with identifier: %@, attributes count: %lu", identifier, (unsigned long)finalAttributes.count);
Expand Down Expand Up @@ -310,45 +311,6 @@ - (void)getSessionIdWithResolve:(RCTPromiseResolveBlock)resolve
return finalAttributes;
}

- (RoktConfig *)buildRoktConfigFromDict:(NSDictionary<NSString *, id> *)configMap {
_rokt_log(@"[mParticle-Rokt] buildRoktConfigFromDict: configMap %@", configMap == nil ? @"nil" : [NSString stringWithFormat:@"non-nil (%lu keys)", (unsigned long)configMap.count]);
if (configMap == nil || configMap.count == 0) {
_rokt_log(@"[mParticle-Rokt] buildRoktConfigFromDict: returning nil");
return nil;
}

RoktConfigBuilder *builder = [[RoktConfigBuilder alloc] init];
BOOL isConfigEmpty = YES;

NSString *colorModeString = configMap[@"colorMode"];
if (colorModeString && [colorModeString isKindOfClass:[NSString class]]) {
isConfigEmpty = NO;
if ([colorModeString isEqualToString:@"dark"]) {
[builder colorMode:RoktColorModeDark];
} else if ([colorModeString isEqualToString:@"light"]) {
[builder colorMode:RoktColorModeLight];
} else {
[builder colorMode:RoktColorModeSystem];
}
}

NSDictionary *cacheConfigMap = configMap[@"cacheConfig"];
if (cacheConfigMap && [cacheConfigMap isKindOfClass:[NSDictionary class]]) {
isConfigEmpty = NO;
NSNumber *cacheDuration = cacheConfigMap[@"cacheDurationInSeconds"];
if (!cacheDuration) {
cacheDuration = @0;
}
NSDictionary<NSString *, NSString *> *cacheAttributes = cacheConfigMap[@"cacheAttributes"];
RoktCacheConfig *cacheConfig = [[RoktCacheConfig alloc] initWithCacheDuration:[cacheDuration longLongValue]
cacheAttributes:cacheAttributes ?: @{}];
[builder cacheConfig:cacheConfig];
}

_rokt_log(@"[mParticle-Rokt] buildRoktConfigFromDict: returning %@", isConfigEmpty ? @"nil" : @"config");
return isConfigEmpty ? nil : [builder build];
}

// Main thread only — RCTViewRegistry and RoktPlaceholderRegistry read the mounted view hierarchy.
// A positive numeric value is a legacy findNodeHandle react tag. Zero is the name-lookup
// sentinel used by the JS wrapper; unresolved tags also fall back to placeholderName.
Expand All @@ -359,15 +321,15 @@ - (NSMutableDictionary *)resolvePlaceholders:(NSDictionary *)placeholders

for(id key in placeholders){
id reactTag = [placeholders objectForKey:key];
RoktEmbeddedView *embeddedView = nil;
UIView *embeddedView = nil;
if ([reactTag isKindOfClass:[NSNumber class]] && [reactTag integerValue] > 0) {
embeddedView = [self embeddedViewForReactTag:reactTag];
}
if (embeddedView == nil && [key isKindOfClass:[NSString class]]) {
UIView *view = [RoktPlaceholderRegistry viewForName:key];
// nil fails isKindOfClass:, covering both "not mounted" and "wrong class".
if ([view isKindOfClass:[RoktEmbeddedView class]]) {
embeddedView = (RoktEmbeddedView *)view;
// nil is not an embedded view, covering both "not mounted" and "wrong class".
if ([RNMPRoktViews isEmbeddedView:view]) {
embeddedView = view;
}
}
if (embeddedView == nil) {
Expand Down Expand Up @@ -396,15 +358,15 @@ - (NSMutableDictionary *)resolvePlaceholders:(NSDictionary *)placeholders
return pending;
}

- (nullable RoktEmbeddedView *)embeddedViewForReactTag:(NSNumber *)reactTag
- (nullable UIView *)embeddedViewForReactTag:(NSNumber *)reactTag
{
UIView *view = [_viewRegistry_DEPRECATED viewForReactTag:reactTag];
#ifdef RCT_NEW_ARCH_ENABLED
return [view isKindOfClass:[RoktNativeLayoutComponentView class]]
? ((RoktNativeLayoutComponentView *)view).roktEmbeddedView
: nil;
#else
return [view isKindOfClass:[RoktEmbeddedView class]] ? (RoktEmbeddedView *)view : nil;
return [RNMPRoktViews isEmbeddedView:view] ? view : nil;
#endif // RCT_NEW_ARCH_ENABLED
}

Expand Down
30 changes: 30 additions & 0 deletions ios/RNMParticle/RNMPRoktSwift.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

// Implemented in Swift (Swift/*.swift). Declared by hand instead of importing the generated
// -Swift.h header: under Swift Package Manager the Swift code is a separate target, and
// Objective-C++ files cannot reach another target's generated header without C++ modules.
// Only Foundation and UIKit types appear here, so Objective-C++ never needs the RoktContracts
// headers. Keep each declaration in sync with its @objc name; RNMPRoktSwiftTests checks them.

@interface RNMPRoktEventMapper : NSObject
// Keys: "payload" (the RoktEvents body), optional "callback" (a RoktCallback value), and
// optional "height" and "placement" (LayoutHeightChanges).
+ (NSDictionary<NSString *, id> *)mapEvent:(id)event viewName:(nullable NSString *)viewName;
// A RoktPlacementFailure with no identifier.
+ (id)placementFailure;
@end

@interface RNMPRoktConfigFactory : NSObject
// A RoktConfig, or nil when the dictionary has no usable keys.
+ (nullable id)configFromDictionary:(nullable NSDictionary<NSString *, id> *)dictionary;
@end

@interface RNMPRoktViews : NSObject
// A RoktEmbeddedView.
+ (UIView *)makeEmbeddedViewWithFrame:(CGRect)frame;
+ (BOOL)isEmbeddedView:(nullable UIView *)view;
@end

NS_ASSUME_NONNULL_END
5 changes: 5 additions & 0 deletions ios/RNMParticle/RNMPSDKImports.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
@import mParticle_Apple_SDK_ObjC;
#endif

// RoktContracts for Objective-C (.m) files only. Objective-C++ files use its types through the
// Swift layer (RNMPRoktSwift.h), because a Swift Package Manager Objective-C++ target cannot
// import them; the SDK headers above only forward-declare RoktEmbeddedView, RoktConfig and RoktEvent.
#ifndef __cplusplus
#if __has_include(<RoktContracts/RoktContracts-Swift.h>)
#import <RoktContracts/RoktContracts-Swift.h>
#elif __has_include(<RoktContracts/RoktContracts.h>)
Expand All @@ -26,3 +30,4 @@
#else
@import RoktContracts;
#endif
#endif // __cplusplus
Loading
Loading