cloudx-react-native 2.0.0-beta.1 → 2.0.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.
- package/README.md +420 -1046
- package/android/src/main/AndroidManifest.xml +0 -4
- package/android/src/main/java/com/cloudxreactnative/CloudXAdEvents.kt +39 -0
- package/android/src/main/java/com/cloudxreactnative/CloudXAdInfo.kt +32 -0
- package/android/src/main/java/com/cloudxreactnative/CloudXModuleImpl.kt +694 -0
- package/android/src/{newarch/com/cloudxreactnative/CloudXReactNativePackage.kt → main/java/com/cloudxreactnative/CloudXPackage.kt} +14 -13
- package/android/src/newarch/com/cloudxreactnative/{CloudXReactNativeModule.kt → CloudXModule.kt} +31 -34
- package/android/src/oldarch/com/cloudxreactnative/{CloudXReactNativeModule.kt → CloudXModule.kt} +27 -32
- package/cloudx-react-native.podspec +1 -1
- package/ios/CloudX.h +47 -0
- package/ios/CloudX.mm +1406 -0
- package/lib/commonjs/AppTrackingTransparency.js +13 -13
- package/lib/commonjs/AppTrackingTransparency.js.map +1 -1
- package/lib/commonjs/CloudX.js +16 -12
- package/lib/commonjs/CloudX.js.map +1 -1
- package/lib/commonjs/CloudXAdPosition.js +23 -0
- package/lib/commonjs/CloudXAdPosition.js.map +1 -0
- package/lib/commonjs/{BannerAd.js → CloudXBannerAd.js} +42 -37
- package/lib/commonjs/CloudXBannerAd.js.map +1 -0
- package/lib/commonjs/CloudXErrorCode.js +116 -0
- package/lib/commonjs/CloudXErrorCode.js.map +1 -0
- package/lib/commonjs/{InterstitialAd.js → CloudXInterstitialAd.js} +10 -10
- package/lib/commonjs/CloudXInterstitialAd.js.map +1 -0
- package/lib/commonjs/{MRecAd.js → CloudXMRECAd.js} +42 -37
- package/lib/commonjs/CloudXMRECAd.js.map +1 -0
- package/lib/commonjs/{RewardedAd.js → CloudXRewardedAd.js} +10 -10
- package/lib/commonjs/CloudXRewardedAd.js.map +1 -0
- package/lib/commonjs/EventEmitter.js +3 -3
- package/lib/commonjs/EventEmitter.js.map +1 -1
- package/lib/commonjs/hooks.js +25 -26
- package/lib/commonjs/hooks.js.map +1 -1
- package/lib/commonjs/index.js +27 -41
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/specs/{NativeCloudXModule.js → NativeCloudX.js} +2 -2
- package/lib/commonjs/specs/NativeCloudX.js.map +1 -0
- package/lib/commonjs/types/AdProps.js +6 -0
- package/lib/commonjs/types/AdProps.js.map +1 -0
- package/lib/commonjs/types/InterstitialAd.js +6 -0
- package/lib/commonjs/types/InterstitialAd.js.map +1 -0
- package/lib/commonjs/types/MRECAd.js +6 -0
- package/lib/commonjs/types/MRECAd.js.map +1 -0
- package/lib/commonjs/types/ViewAd.js +6 -0
- package/lib/commonjs/types/ViewAd.js.map +1 -0
- package/lib/module/AppTrackingTransparency.js +12 -12
- package/lib/module/AppTrackingTransparency.js.map +1 -1
- package/lib/module/CloudX.js +16 -12
- package/lib/module/CloudX.js.map +1 -1
- package/lib/module/CloudXAdPosition.js +17 -0
- package/lib/module/CloudXAdPosition.js.map +1 -0
- package/lib/module/{BannerAd.js → CloudXBannerAd.js} +41 -36
- package/lib/module/CloudXBannerAd.js.map +1 -0
- package/lib/module/CloudXErrorCode.js +110 -0
- package/lib/module/CloudXErrorCode.js.map +1 -0
- package/lib/module/{InterstitialAd.js → CloudXInterstitialAd.js} +9 -9
- package/lib/module/CloudXInterstitialAd.js.map +1 -0
- package/lib/module/{MRecAd.js → CloudXMRECAd.js} +41 -36
- package/lib/module/CloudXMRECAd.js.map +1 -0
- package/lib/module/{RewardedAd.js → CloudXRewardedAd.js} +9 -9
- package/lib/module/CloudXRewardedAd.js.map +1 -0
- package/lib/module/EventEmitter.js +2 -2
- package/lib/module/EventEmitter.js.map +1 -1
- package/lib/module/hooks.js +14 -15
- package/lib/module/hooks.js.map +1 -1
- package/lib/module/index.js +9 -10
- package/lib/module/index.js.map +1 -1
- package/lib/module/specs/{NativeCloudXModule.js → NativeCloudX.js} +2 -2
- package/lib/module/specs/NativeCloudX.js.map +1 -0
- package/lib/module/types/AdProps.js +2 -0
- package/lib/module/types/AdProps.js.map +1 -0
- package/lib/module/types/InterstitialAd.js +2 -0
- package/lib/module/types/InterstitialAd.js.map +1 -0
- package/lib/module/types/MRECAd.js +2 -0
- package/lib/module/types/MRECAd.js.map +1 -0
- package/lib/module/types/ViewAd.js +2 -0
- package/lib/module/types/ViewAd.js.map +1 -0
- package/lib/typescript/src/AppTrackingTransparency.d.ts +4 -4
- package/lib/typescript/src/AppTrackingTransparency.d.ts.map +1 -1
- package/lib/typescript/src/CloudX.d.ts.map +1 -1
- package/lib/typescript/src/CloudXAdPosition.d.ts +16 -0
- package/lib/typescript/src/CloudXAdPosition.d.ts.map +1 -0
- package/lib/typescript/src/CloudXBannerAd.d.ts +4 -0
- package/lib/typescript/src/CloudXBannerAd.d.ts.map +1 -0
- package/lib/typescript/src/{ErrorCode.d.ts → CloudXErrorCode.d.ts} +2 -2
- package/lib/typescript/src/CloudXErrorCode.d.ts.map +1 -0
- package/lib/typescript/src/CloudXInterstitialAd.d.ts +4 -0
- package/lib/typescript/src/CloudXInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/src/CloudXMRECAd.d.ts +4 -0
- package/lib/typescript/src/CloudXMRECAd.d.ts.map +1 -0
- package/lib/typescript/src/CloudXRewardedAd.d.ts +4 -0
- package/lib/typescript/src/CloudXRewardedAd.d.ts.map +1 -0
- package/lib/typescript/src/EventEmitter.d.ts +4 -2
- package/lib/typescript/src/EventEmitter.d.ts.map +1 -1
- package/lib/typescript/src/hooks.d.ts +7 -8
- package/lib/typescript/src/hooks.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +12 -13
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/specs/{NativeCloudXModule.d.ts → NativeCloudX.d.ts} +47 -64
- package/lib/typescript/src/specs/NativeCloudX.d.ts.map +1 -0
- package/lib/typescript/src/types/AdEvent.d.ts +3 -3
- package/lib/typescript/src/types/AdEvent.d.ts.map +1 -1
- package/lib/typescript/src/types/AdInfo.d.ts +7 -7
- package/lib/typescript/src/types/AdInfo.d.ts.map +1 -1
- package/lib/typescript/src/types/AdProps.d.ts +21 -0
- package/lib/typescript/src/types/AdProps.d.ts.map +1 -0
- package/lib/typescript/src/types/BannerAd.d.ts +8 -34
- package/lib/typescript/src/types/BannerAd.d.ts.map +1 -1
- package/lib/typescript/src/types/CloudX.d.ts +7 -4
- package/lib/typescript/src/types/CloudX.d.ts.map +1 -1
- package/lib/typescript/src/types/Configuration.d.ts +7 -3
- package/lib/typescript/src/types/Configuration.d.ts.map +1 -1
- package/lib/typescript/src/types/FullscreenAd.d.ts +10 -9
- package/lib/typescript/src/types/FullscreenAd.d.ts.map +1 -1
- package/lib/typescript/src/types/InterstitialAd.d.ts +8 -0
- package/lib/typescript/src/types/InterstitialAd.d.ts.map +1 -0
- package/lib/typescript/src/types/MRECAd.d.ts +13 -0
- package/lib/typescript/src/types/MRECAd.d.ts.map +1 -0
- package/lib/typescript/src/types/RewardedAd.d.ts +5 -4
- package/lib/typescript/src/types/RewardedAd.d.ts.map +1 -1
- package/lib/typescript/src/types/ViewAd.d.ts +29 -0
- package/lib/typescript/src/types/ViewAd.d.ts.map +1 -0
- package/lib/typescript/src/types/index.d.ts +11 -7
- package/lib/typescript/src/types/index.d.ts.map +1 -1
- package/package.json +8 -10
- package/src/AppTrackingTransparency.ts +10 -10
- package/src/CloudX.ts +21 -16
- package/src/CloudXAdPosition.ts +16 -0
- package/src/{BannerAd.ts → CloudXBannerAd.ts} +69 -47
- package/src/{ErrorCode.ts → CloudXErrorCode.ts} +1 -1
- package/src/{InterstitialAd.ts → CloudXInterstitialAd.ts} +17 -17
- package/src/{MRecAd.ts → CloudXMRECAd.ts} +69 -47
- package/src/{RewardedAd.ts → CloudXRewardedAd.ts} +18 -18
- package/src/EventEmitter.ts +4 -4
- package/src/hooks.ts +20 -22
- package/src/index.ts +27 -24
- package/src/specs/{NativeCloudXModule.ts → NativeCloudX.ts} +61 -82
- package/src/types/AdEvent.ts +3 -3
- package/src/types/AdInfo.ts +7 -7
- package/src/types/AdProps.ts +27 -0
- package/src/types/BannerAd.ts +8 -54
- package/src/types/CloudX.ts +10 -5
- package/src/types/Configuration.ts +8 -3
- package/src/types/FullscreenAd.ts +10 -9
- package/src/types/InterstitialAd.ts +8 -0
- package/src/types/MRECAd.ts +13 -0
- package/src/types/RewardedAd.ts +5 -4
- package/src/types/ViewAd.ts +38 -0
- package/src/types/index.ts +11 -7
- package/android/src/main/java/com/cloudxreactnative/CloudXAdViewEvent.kt +0 -15
- package/android/src/main/java/com/cloudxreactnative/CloudXBannerViewManagerImpl.kt +0 -472
- package/android/src/main/java/com/cloudxreactnative/CloudXReactNativeModuleImpl.kt +0 -861
- package/android/src/newarch/com/cloudxreactnative/CloudXBannerViewManager.kt +0 -90
- package/android/src/oldarch/com/cloudxreactnative/CloudXBannerViewManager.kt +0 -76
- package/android/src/oldarch/com/cloudxreactnative/CloudXReactNativePackage.kt +0 -16
- package/ios/RNCloudXBannerView.h +0 -51
- package/ios/RNCloudXBannerView.mm +0 -633
- package/ios/RNCloudXBannerViewManager.h +0 -11
- package/ios/RNCloudXBannerViewManager.mm +0 -60
- package/ios/RNCloudXModule.h +0 -30
- package/ios/RNCloudXModule.mm +0 -1088
- package/lib/commonjs/AdView.js +0 -151
- package/lib/commonjs/AdView.js.map +0 -1
- package/lib/commonjs/BannerAd.js.map +0 -1
- package/lib/commonjs/ErrorCode.js +0 -116
- package/lib/commonjs/ErrorCode.js.map +0 -1
- package/lib/commonjs/InterstitialAd.js.map +0 -1
- package/lib/commonjs/MRecAd.js.map +0 -1
- package/lib/commonjs/RewardedAd.js.map +0 -1
- package/lib/commonjs/specs/CloudXAdViewNativeComponent.js +0 -26
- package/lib/commonjs/specs/CloudXAdViewNativeComponent.js.map +0 -1
- package/lib/commonjs/specs/NativeCloudXModule.js.map +0 -1
- package/lib/module/AdView.js +0 -144
- package/lib/module/AdView.js.map +0 -1
- package/lib/module/BannerAd.js.map +0 -1
- package/lib/module/ErrorCode.js +0 -110
- package/lib/module/ErrorCode.js.map +0 -1
- package/lib/module/InterstitialAd.js.map +0 -1
- package/lib/module/MRecAd.js.map +0 -1
- package/lib/module/RewardedAd.js.map +0 -1
- package/lib/module/specs/CloudXAdViewNativeComponent.js +0 -20
- package/lib/module/specs/CloudXAdViewNativeComponent.js.map +0 -1
- package/lib/module/specs/NativeCloudXModule.js.map +0 -1
- package/lib/typescript/src/AdView.d.ts +0 -69
- package/lib/typescript/src/AdView.d.ts.map +0 -1
- package/lib/typescript/src/BannerAd.d.ts +0 -4
- package/lib/typescript/src/BannerAd.d.ts.map +0 -1
- package/lib/typescript/src/ErrorCode.d.ts.map +0 -1
- package/lib/typescript/src/InterstitialAd.d.ts +0 -4
- package/lib/typescript/src/InterstitialAd.d.ts.map +0 -1
- package/lib/typescript/src/MRecAd.d.ts +0 -4
- package/lib/typescript/src/MRecAd.d.ts.map +0 -1
- package/lib/typescript/src/RewardedAd.d.ts +0 -4
- package/lib/typescript/src/RewardedAd.d.ts.map +0 -1
- package/lib/typescript/src/specs/CloudXAdViewNativeComponent.d.ts +0 -61
- package/lib/typescript/src/specs/CloudXAdViewNativeComponent.d.ts.map +0 -1
- package/lib/typescript/src/specs/NativeCloudXModule.d.ts.map +0 -1
- package/src/AdView.tsx +0 -213
- package/src/specs/CloudXAdViewNativeComponent.ts +0 -82
package/ios/CloudX.mm
ADDED
|
@@ -0,0 +1,1406 @@
|
|
|
1
|
+
//
|
|
2
|
+
// CloudX.mm
|
|
3
|
+
// cloudx-react-native
|
|
4
|
+
//
|
|
5
|
+
|
|
6
|
+
#import "CloudX.h"
|
|
7
|
+
#import <React/RCTUtils.h>
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@interface UIColor (CLXUtils)
|
|
11
|
+
+ (nullable UIColor *)clx_colorWithHexString:(NSString *)hexString;
|
|
12
|
+
@end
|
|
13
|
+
|
|
14
|
+
@interface CloudX()
|
|
15
|
+
|
|
16
|
+
// A simple BOOL tracks initialization state. Concurrent initialize calls are serialized
|
|
17
|
+
// by methodQueue (main queue), making the check-then-set atomic. The "initializing"
|
|
18
|
+
// middle state is unnecessary here because
|
|
19
|
+
// CloudXCore's own completion block handles any duplicate init attempts internally.
|
|
20
|
+
@property (nonatomic, assign, getter=isPluginInitialized) BOOL pluginInitialized;
|
|
21
|
+
|
|
22
|
+
// Fullscreen ad storage — lazily created on first load/show, keyed by ad unit ID.
|
|
23
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, CLXInterstitial *> *interstitials;
|
|
24
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, CLXRewarded *> *rewardedAds;
|
|
25
|
+
|
|
26
|
+
// Overlay banner/MREC state — each ad unit ID owns exactly one CLXBannerAdView,
|
|
27
|
+
// positioned window-level via NSLayoutConstraints against the root view controller.
|
|
28
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, CLXBannerAdView *> *adViews;
|
|
29
|
+
// CLXBannerType stored as NSNumber so didFailToLoadAd: can route the event to the
|
|
30
|
+
// correct JS listener without a CLXAd object (that callback only receives adUnitId).
|
|
31
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *adViewAdFormats;
|
|
32
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSString *> *adViewPositions;
|
|
33
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSValue *> *adViewOffsets;
|
|
34
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSArray<NSLayoutConstraint *> *> *adViewConstraints;
|
|
35
|
+
@property (nonatomic, strong) NSMutableArray<NSString *> *adUnitIdentifiersToShowAfterCreate;
|
|
36
|
+
// One safe-area background UIView per ad unit ID. Each banner/MREC that is positioned
|
|
37
|
+
// at TOP_CENTER or BOTTOM_CENTER with a publisher background color gets its own view so
|
|
38
|
+
// multiple simultaneous overlay ads don't compete for a single shared view.
|
|
39
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, UIView *> *safeAreaBackgrounds;
|
|
40
|
+
@property (nonatomic, strong) NSMutableDictionary<NSString *, UIColor *> *publisherBannerBackgroundColors;
|
|
41
|
+
|
|
42
|
+
@property (nonatomic, assign) BOOL hasListeners;
|
|
43
|
+
|
|
44
|
+
@end
|
|
45
|
+
|
|
46
|
+
@implementation CloudX
|
|
47
|
+
|
|
48
|
+
static NSString *const SDK_TAG = @"CloudXCore";
|
|
49
|
+
static NSString *const TAG = @"CloudX";
|
|
50
|
+
|
|
51
|
+
static NSString *const ON_BANNER_AD_LOADED_EVENT = @"OnBannerAdLoadedEvent";
|
|
52
|
+
static NSString *const ON_BANNER_AD_LOAD_FAILED_EVENT = @"OnBannerAdLoadFailedEvent";
|
|
53
|
+
static NSString *const ON_BANNER_AD_CLICKED_EVENT = @"OnBannerAdClickedEvent";
|
|
54
|
+
static NSString *const ON_BANNER_AD_COLLAPSED_EVENT = @"OnBannerAdCollapsedEvent";
|
|
55
|
+
static NSString *const ON_BANNER_AD_EXPANDED_EVENT = @"OnBannerAdExpandedEvent";
|
|
56
|
+
static NSString *const ON_BANNER_AD_REVENUE_PAID = @"OnBannerAdRevenuePaid";
|
|
57
|
+
|
|
58
|
+
static NSString *const ON_MREC_AD_LOADED_EVENT = @"OnMRecAdLoadedEvent";
|
|
59
|
+
static NSString *const ON_MREC_AD_LOAD_FAILED_EVENT = @"OnMRecAdLoadFailedEvent";
|
|
60
|
+
static NSString *const ON_MREC_AD_CLICKED_EVENT = @"OnMRecAdClickedEvent";
|
|
61
|
+
static NSString *const ON_MREC_AD_COLLAPSED_EVENT = @"OnMRecAdCollapsedEvent";
|
|
62
|
+
static NSString *const ON_MREC_AD_EXPANDED_EVENT = @"OnMRecAdExpandedEvent";
|
|
63
|
+
static NSString *const ON_MREC_AD_REVENUE_PAID = @"OnMRecAdRevenuePaid";
|
|
64
|
+
|
|
65
|
+
static NSString *const ON_INTERSTITIAL_LOADED_EVENT = @"OnInterstitialLoadedEvent";
|
|
66
|
+
static NSString *const ON_INTERSTITIAL_LOAD_FAILED_EVENT = @"OnInterstitialLoadFailedEvent";
|
|
67
|
+
static NSString *const ON_INTERSTITIAL_CLICKED_EVENT = @"OnInterstitialClickedEvent";
|
|
68
|
+
static NSString *const ON_INTERSTITIAL_DISPLAYED_EVENT = @"OnInterstitialDisplayedEvent";
|
|
69
|
+
static NSString *const ON_INTERSTITIAL_DISPLAY_FAILED_EVENT = @"OnInterstitialDisplayFailedEvent";
|
|
70
|
+
static NSString *const ON_INTERSTITIAL_HIDDEN_EVENT = @"OnInterstitialHiddenEvent";
|
|
71
|
+
static NSString *const ON_INTERSTITIAL_AD_REVENUE_PAID = @"OnInterstitialAdRevenuePaid";
|
|
72
|
+
|
|
73
|
+
static NSString *const ON_REWARDED_AD_LOADED_EVENT = @"OnRewardedAdLoadedEvent";
|
|
74
|
+
static NSString *const ON_REWARDED_AD_LOAD_FAILED_EVENT = @"OnRewardedAdLoadFailedEvent";
|
|
75
|
+
static NSString *const ON_REWARDED_AD_CLICKED_EVENT = @"OnRewardedAdClickedEvent";
|
|
76
|
+
static NSString *const ON_REWARDED_AD_DISPLAYED_EVENT = @"OnRewardedAdDisplayedEvent";
|
|
77
|
+
static NSString *const ON_REWARDED_AD_DISPLAY_FAILED_EVENT = @"OnRewardedAdDisplayFailedEvent";
|
|
78
|
+
static NSString *const ON_REWARDED_AD_HIDDEN_EVENT = @"OnRewardedAdHiddenEvent";
|
|
79
|
+
static NSString *const ON_REWARDED_AD_RECEIVED_REWARD_EVENT = @"OnRewardedAdReceivedRewardEvent";
|
|
80
|
+
static NSString *const ON_REWARDED_AD_REVENUE_PAID = @"OnRewardedAdRevenuePaid";
|
|
81
|
+
|
|
82
|
+
static NSString *const TOP_CENTER = @"top_center";
|
|
83
|
+
static NSString *const TOP_LEFT = @"top_left";
|
|
84
|
+
static NSString *const TOP_RIGHT = @"top_right";
|
|
85
|
+
static NSString *const CENTERED = @"centered";
|
|
86
|
+
static NSString *const CENTER_LEFT = @"center_left";
|
|
87
|
+
static NSString *const CENTER_RIGHT = @"center_right";
|
|
88
|
+
static NSString *const BOTTOM_LEFT = @"bottom_left";
|
|
89
|
+
static NSString *const BOTTOM_CENTER = @"bottom_center";
|
|
90
|
+
static NSString *const BOTTOM_RIGHT = @"bottom_right";
|
|
91
|
+
|
|
92
|
+
static CloudX *CloudXShared;
|
|
93
|
+
|
|
94
|
+
RCT_EXPORT_MODULE(CloudX)
|
|
95
|
+
|
|
96
|
+
+ (BOOL)requiresMainQueueSetup
|
|
97
|
+
{
|
|
98
|
+
return YES;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
- (dispatch_queue_t)methodQueue
|
|
102
|
+
{
|
|
103
|
+
return dispatch_get_main_queue();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
+ (CloudX *)shared
|
|
107
|
+
{
|
|
108
|
+
return CloudXShared;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
- (instancetype)init
|
|
112
|
+
{
|
|
113
|
+
self = [super init];
|
|
114
|
+
if ( self )
|
|
115
|
+
{
|
|
116
|
+
CloudXShared = self;
|
|
117
|
+
|
|
118
|
+
self.interstitials = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
119
|
+
self.rewardedAds = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
120
|
+
|
|
121
|
+
self.adViews = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
122
|
+
self.adViewAdFormats = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
123
|
+
self.adViewPositions = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
124
|
+
self.adViewOffsets = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
125
|
+
self.adViewConstraints = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
126
|
+
self.adUnitIdentifiersToShowAfterCreate = [NSMutableArray arrayWithCapacity: 2];
|
|
127
|
+
self.safeAreaBackgrounds = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
128
|
+
self.publisherBannerBackgroundColors = [NSMutableDictionary dictionaryWithCapacity: 2];
|
|
129
|
+
}
|
|
130
|
+
return self;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
#pragma mark - Initialization
|
|
134
|
+
|
|
135
|
+
RCT_EXPORT_METHOD(isInitialized:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
136
|
+
{
|
|
137
|
+
resolve(@([self isPluginInitialized] && [CloudXCore shared].isInitialized));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
RCT_EXPORT_METHOD(initialize:(NSString *)pluginVersion appKey:(NSString *)appKey resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
141
|
+
{
|
|
142
|
+
if ( [self isPluginInitialized] )
|
|
143
|
+
{
|
|
144
|
+
resolve(@{@"success": @(YES)});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
self.pluginInitialized = YES;
|
|
149
|
+
|
|
150
|
+
[self log: @"Initializing CloudX React Native v%@...", pluginVersion];
|
|
151
|
+
|
|
152
|
+
if ( !appKey || appKey.length == 0 )
|
|
153
|
+
{
|
|
154
|
+
reject(RCTErrorUnspecified, @"Unable to initialize CloudX SDK - no SDK key provided!", nil);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
CLXInitializationConfiguration *initConfig = [CLXInitializationConfiguration configurationWithAppKey: appKey builderBlock:^(CLXInitializationConfigurationBuilder *builder) {
|
|
159
|
+
builder.pluginVersion = [@"React-Native-" stringByAppendingString: pluginVersion];
|
|
160
|
+
}];
|
|
161
|
+
|
|
162
|
+
[[CloudXCore shared] initializeWithConfiguration: initConfig completion:^(CLXSdkConfiguration *sdkConfiguration, CLXError *error) {
|
|
163
|
+
if ( error )
|
|
164
|
+
{
|
|
165
|
+
NSString *message = error.userInfo[NSLocalizedDescriptionKey] ?: @"Unknown initialization error";
|
|
166
|
+
[self log: @"SDK initialization failed: %@", message];
|
|
167
|
+
resolve(@{@"success": @(NO), @"message": message});
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
[self log: @"SDK initialized"];
|
|
171
|
+
resolve(@{@"success": @(YES)});
|
|
172
|
+
}];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
#pragma mark - General Public API
|
|
176
|
+
|
|
177
|
+
RCT_EXPORT_METHOD(isTablet:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
178
|
+
{
|
|
179
|
+
resolve(@([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
RCT_EXPORT_METHOD(getVersion:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
183
|
+
{
|
|
184
|
+
resolve([CloudXCore shared].sdkVersion ?: @"");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
RCT_EXPORT_METHOD(setMinLogLevel:(NSString *)level)
|
|
188
|
+
{
|
|
189
|
+
[CloudXCore setMinLogLevel: [self logLevelFromString: level]];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
RCT_EXPORT_METHOD(setVisualDebuggingEnabled:(BOOL)enabled)
|
|
193
|
+
{
|
|
194
|
+
[CloudXCore setVisualDebuggingEnabled: enabled];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
RCT_EXPORT_METHOD(setHashedUserID:(NSString *)hashedUserID)
|
|
198
|
+
{
|
|
199
|
+
[[CloudXCore shared] setHashedUserID: hashedUserID];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
RCT_EXPORT_METHOD(setUserKeyValue:(NSString *)key value:(NSString *)value)
|
|
203
|
+
{
|
|
204
|
+
[[CloudXCore shared] setUserKeyValue: key value: value];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
RCT_EXPORT_METHOD(setAppKeyValue:(NSString *)key value:(NSString *)value)
|
|
208
|
+
{
|
|
209
|
+
[[CloudXCore shared] setAppKeyValue: key value: value];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
RCT_EXPORT_METHOD(clearAllKeyValues)
|
|
213
|
+
{
|
|
214
|
+
[[CloudXCore shared] clearAllKeyValues];
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
#pragma mark - Banners
|
|
218
|
+
|
|
219
|
+
RCT_EXPORT_METHOD(createBanner:(NSString *)adUnitIdentifier position:(NSString *)bannerPosition)
|
|
220
|
+
{
|
|
221
|
+
[self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT atPosition: bannerPosition withOffset: CGPointZero];
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
RCT_EXPORT_METHOD(createBannerWithOffsets:(NSString *)adUnitIdentifier position:(NSString *)bannerPosition xOffset:(double)xOffset yOffset:(double)yOffset)
|
|
225
|
+
{
|
|
226
|
+
[self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT atPosition: bannerPosition withOffset: CGPointMake(xOffset, yOffset)];
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
RCT_EXPORT_METHOD(setBannerBackgroundColor:(NSString *)adUnitIdentifier hexColorString:(NSString *)hexColorString)
|
|
230
|
+
{
|
|
231
|
+
[self setAdViewBackgroundColorForAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT hexColorCode: hexColorString];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
RCT_EXPORT_METHOD(setBannerPlacement:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement)
|
|
235
|
+
{
|
|
236
|
+
[self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
RCT_EXPORT_METHOD(setBannerCustomData:(NSString *)adUnitIdentifier customData:(nullable NSString *)customData)
|
|
240
|
+
{
|
|
241
|
+
[self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
RCT_EXPORT_METHOD(updateBannerPosition:(NSString *)adUnitIdentifier position:(NSString *)bannerPosition)
|
|
245
|
+
{
|
|
246
|
+
CGPoint existingOffset = [self.adViewOffsets[adUnitIdentifier] CGPointValue];
|
|
247
|
+
[self updateAdViewPosition: bannerPosition withOffset: existingOffset forAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
RCT_EXPORT_METHOD(updateBannerOffsets:(NSString *)adUnitIdentifier xOffset:(double)xOffset yOffset:(double)yOffset)
|
|
251
|
+
{
|
|
252
|
+
[self updateAdViewPosition: self.adViewPositions[adUnitIdentifier] withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
RCT_EXPORT_METHOD(startBannerAutoRefresh:(NSString *)adUnitIdentifier)
|
|
256
|
+
{
|
|
257
|
+
[self startAutoRefresh: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
RCT_EXPORT_METHOD(stopBannerAutoRefresh:(NSString *)adUnitIdentifier)
|
|
261
|
+
{
|
|
262
|
+
[self stopAutoRefresh: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
RCT_EXPORT_METHOD(showBanner:(NSString *)adUnitIdentifier)
|
|
266
|
+
{
|
|
267
|
+
[self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
RCT_EXPORT_METHOD(hideBanner:(NSString *)adUnitIdentifier)
|
|
271
|
+
{
|
|
272
|
+
[self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
RCT_EXPORT_METHOD(destroyBanner:(NSString *)adUnitIdentifier)
|
|
276
|
+
{
|
|
277
|
+
[self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: DEVICE_SPECIFIC_ADVIEW_AD_FORMAT];
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
#pragma mark - MRECs
|
|
281
|
+
|
|
282
|
+
RCT_EXPORT_METHOD(createMREC:(NSString *)adUnitIdentifier position:(NSString *)mrecPosition)
|
|
283
|
+
{
|
|
284
|
+
[self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC atPosition: mrecPosition withOffset: CGPointZero];
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
RCT_EXPORT_METHOD(createMRECWithOffsets:(NSString *)adUnitIdentifier position:(NSString *)mrecPosition xOffset:(double)xOffset yOffset:(double)yOffset)
|
|
288
|
+
{
|
|
289
|
+
[self createAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC atPosition: mrecPosition withOffset: CGPointMake(xOffset, yOffset)];
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
RCT_EXPORT_METHOD(setMRECPlacement:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement)
|
|
293
|
+
{
|
|
294
|
+
[self setAdViewPlacement: placement forAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
RCT_EXPORT_METHOD(setMRECCustomData:(NSString *)adUnitIdentifier customData:(nullable NSString *)customData)
|
|
298
|
+
{
|
|
299
|
+
[self setAdViewCustomData: customData forAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
RCT_EXPORT_METHOD(updateMRECPosition:(NSString *)adUnitIdentifier position:(NSString *)mrecPosition)
|
|
303
|
+
{
|
|
304
|
+
CGPoint existingOffset = [self.adViewOffsets[adUnitIdentifier] CGPointValue];
|
|
305
|
+
[self updateAdViewPosition: mrecPosition withOffset: existingOffset forAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
RCT_EXPORT_METHOD(updateMRECOffsets:(NSString *)adUnitIdentifier xOffset:(double)xOffset yOffset:(double)yOffset)
|
|
309
|
+
{
|
|
310
|
+
[self updateAdViewPosition: self.adViewPositions[adUnitIdentifier] withOffset: CGPointMake(xOffset, yOffset) forAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
RCT_EXPORT_METHOD(setMRECBackgroundColor:(NSString *)adUnitIdentifier hexColorString:(NSString *)hexColorString)
|
|
314
|
+
{
|
|
315
|
+
[self setAdViewBackgroundColorForAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC hexColorCode: hexColorString];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
RCT_EXPORT_METHOD(startMRECAutoRefresh:(NSString *)adUnitIdentifier)
|
|
319
|
+
{
|
|
320
|
+
[self startAutoRefresh: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
RCT_EXPORT_METHOD(stopMRECAutoRefresh:(NSString *)adUnitIdentifier)
|
|
324
|
+
{
|
|
325
|
+
[self stopAutoRefresh: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
RCT_EXPORT_METHOD(showMREC:(NSString *)adUnitIdentifier)
|
|
329
|
+
{
|
|
330
|
+
[self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
RCT_EXPORT_METHOD(hideMREC:(NSString *)adUnitIdentifier)
|
|
334
|
+
{
|
|
335
|
+
[self hideAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
RCT_EXPORT_METHOD(destroyMREC:(NSString *)adUnitIdentifier)
|
|
339
|
+
{
|
|
340
|
+
[self destroyAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: CLXBannerTypeMREC];
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
#pragma mark - Interstitials
|
|
344
|
+
|
|
345
|
+
RCT_EXPORT_METHOD(loadInterstitial:(NSString *)adUnitIdentifier)
|
|
346
|
+
{
|
|
347
|
+
[self log: @"🔴 loadInterstitial called from JS — adUnitId: %@", adUnitIdentifier];
|
|
348
|
+
CLXInterstitial *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier];
|
|
349
|
+
[interstitial load];
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
RCT_EXPORT_METHOD(isInterstitialReady:(NSString *)adUnitIdentifier resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
353
|
+
{
|
|
354
|
+
CLXInterstitial *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier];
|
|
355
|
+
resolve(@([interstitial isReady]));
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
RCT_EXPORT_METHOD(showInterstitial:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData)
|
|
359
|
+
{
|
|
360
|
+
UIViewController *vc = [self topViewController];
|
|
361
|
+
if ( !vc )
|
|
362
|
+
{
|
|
363
|
+
[self log: @"showInterstitial: no visible view controller — emitting display failure"];
|
|
364
|
+
NSDictionary *body = @{@"adUnitId": adUnitIdentifier ?: @"",
|
|
365
|
+
@"code": @(-1),
|
|
366
|
+
@"message": @"No visible view controller to present interstitial from"};
|
|
367
|
+
[self sendReactNativeEventWithName: ON_INTERSTITIAL_DISPLAY_FAILED_EVENT body: body];
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
CLXInterstitial *interstitial = [self retrieveInterstitialForAdUnitIdentifier: adUnitIdentifier];
|
|
372
|
+
[interstitial showFromViewController: vc placement: placement customData: customData];
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
RCT_EXPORT_METHOD(destroyInterstitial:(NSString *)adUnitIdentifier)
|
|
376
|
+
{
|
|
377
|
+
[self log: @"Destroying interstitial with ad unit identifier \"%@\"", adUnitIdentifier];
|
|
378
|
+
|
|
379
|
+
CLXInterstitial *interstitial = self.interstitials[adUnitIdentifier];
|
|
380
|
+
if ( interstitial )
|
|
381
|
+
{
|
|
382
|
+
interstitial.delegate = nil;
|
|
383
|
+
interstitial.revenueDelegate = nil;
|
|
384
|
+
[interstitial destroy];
|
|
385
|
+
[self.interstitials removeObjectForKey: adUnitIdentifier];
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
#pragma mark - Rewarded
|
|
390
|
+
|
|
391
|
+
RCT_EXPORT_METHOD(loadRewarded:(NSString *)adUnitIdentifier)
|
|
392
|
+
{
|
|
393
|
+
[self log: @"🔴 loadRewarded called from JS — adUnitId: %@", adUnitIdentifier];
|
|
394
|
+
CLXRewarded *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier];
|
|
395
|
+
[rewardedAd load];
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
RCT_EXPORT_METHOD(isRewardedReady:(NSString *)adUnitIdentifier resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
|
|
399
|
+
{
|
|
400
|
+
CLXRewarded *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier];
|
|
401
|
+
resolve(@([rewardedAd isReady]));
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
RCT_EXPORT_METHOD(showRewarded:(NSString *)adUnitIdentifier placement:(nullable NSString *)placement customData:(nullable NSString *)customData)
|
|
405
|
+
{
|
|
406
|
+
UIViewController *vc = [self topViewController];
|
|
407
|
+
if ( !vc )
|
|
408
|
+
{
|
|
409
|
+
[self log: @"showRewarded: no visible view controller — emitting display failure"];
|
|
410
|
+
NSDictionary *body = @{@"adUnitId": adUnitIdentifier ?: @"",
|
|
411
|
+
@"code": @(-1),
|
|
412
|
+
@"message": @"No visible view controller to present rewarded ad from"};
|
|
413
|
+
[self sendReactNativeEventWithName: ON_REWARDED_AD_DISPLAY_FAILED_EVENT body: body];
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
CLXRewarded *rewardedAd = [self retrieveRewardedAdForAdUnitIdentifier: adUnitIdentifier];
|
|
418
|
+
[rewardedAd showFromViewController: vc placement: placement customData: customData];
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
RCT_EXPORT_METHOD(destroyRewarded:(NSString *)adUnitIdentifier)
|
|
422
|
+
{
|
|
423
|
+
[self log: @"Destroying rewarded ad with ad unit identifier \"%@\"", adUnitIdentifier];
|
|
424
|
+
|
|
425
|
+
CLXRewarded *rewardedAd = self.rewardedAds[adUnitIdentifier];
|
|
426
|
+
if ( rewardedAd )
|
|
427
|
+
{
|
|
428
|
+
rewardedAd.delegate = nil;
|
|
429
|
+
rewardedAd.revenueDelegate = nil;
|
|
430
|
+
[rewardedAd destroy];
|
|
431
|
+
[self.rewardedAds removeObjectForKey: adUnitIdentifier];
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
#pragma mark - Ad Callbacks
|
|
436
|
+
|
|
437
|
+
- (void)didLoadAd:(CLXAd *)ad
|
|
438
|
+
{
|
|
439
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
440
|
+
NSString *name;
|
|
441
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
442
|
+
if ( adFormat == CLXAdFormatBanner || adFormat == CLXAdFormatMREC )
|
|
443
|
+
{
|
|
444
|
+
CLXBannerType bannerType = ( adFormat == CLXAdFormatMREC ) ? CLXBannerTypeMREC : CLXBannerTypeW320H50;
|
|
445
|
+
CLXBannerAdView *adView = [self retrieveAdViewForAdUnitIdentifier: ad.adUnitId adFormat: bannerType];
|
|
446
|
+
adView.userInteractionEnabled = YES;
|
|
447
|
+
|
|
448
|
+
name = ( adFormat == CLXAdFormatMREC ) ? ON_MREC_AD_LOADED_EVENT : ON_BANNER_AD_LOADED_EVENT;
|
|
449
|
+
[self positionAdViewForAd: ad];
|
|
450
|
+
|
|
451
|
+
if ( adView && adView.isHidden )
|
|
452
|
+
{
|
|
453
|
+
[adView stopAutoRefresh];
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
else if ( adFormat == CLXAdFormatInterstitial )
|
|
457
|
+
{
|
|
458
|
+
name = ON_INTERSTITIAL_LOADED_EVENT;
|
|
459
|
+
}
|
|
460
|
+
else if ( adFormat == CLXAdFormatRewarded )
|
|
461
|
+
{
|
|
462
|
+
name = ON_REWARDED_AD_LOADED_EVENT;
|
|
463
|
+
}
|
|
464
|
+
else
|
|
465
|
+
{
|
|
466
|
+
[self logInvalidAdFormat: adFormat];
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
[self sendReactNativeEventWithName: name body: [self adInfoForAd: ad]];
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
- (void)didFailToLoadAd:(NSString *)adUnitId error:(CLXError *)error
|
|
475
|
+
{
|
|
476
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
477
|
+
if ( !adUnitId )
|
|
478
|
+
{
|
|
479
|
+
[self log: @"didFailToLoadAd received nil adUnitId — broadcasting to all fullscreen listeners. Error: %@", error];
|
|
480
|
+
// Nil adUnitId means the core SDK couldn't resolve the ad unit.
|
|
481
|
+
// Broadcast failure to all registered fullscreen ads so JS pendingShow state resets.
|
|
482
|
+
for ( NSString *key in self.interstitials )
|
|
483
|
+
{
|
|
484
|
+
[self sendReactNativeEventWithName: ON_INTERSTITIAL_LOAD_FAILED_EVENT
|
|
485
|
+
body: [self adLoadFailedInfoForAd: key withError: error]];
|
|
486
|
+
}
|
|
487
|
+
for ( NSString *key in self.rewardedAds )
|
|
488
|
+
{
|
|
489
|
+
[self sendReactNativeEventWithName: ON_REWARDED_AD_LOAD_FAILED_EVENT
|
|
490
|
+
body: [self adLoadFailedInfoForAd: key withError: error]];
|
|
491
|
+
}
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
NSString *name;
|
|
496
|
+
if ( self.adViews[adUnitId] )
|
|
497
|
+
{
|
|
498
|
+
CLXBannerType adFormat = (CLXBannerType)[self.adViewAdFormats[adUnitId] integerValue];
|
|
499
|
+
name = ( adFormat == CLXBannerTypeMREC ) ? ON_MREC_AD_LOAD_FAILED_EVENT : ON_BANNER_AD_LOAD_FAILED_EVENT;
|
|
500
|
+
}
|
|
501
|
+
else if ( self.interstitials[adUnitId] )
|
|
502
|
+
{
|
|
503
|
+
name = ON_INTERSTITIAL_LOAD_FAILED_EVENT;
|
|
504
|
+
}
|
|
505
|
+
else if ( self.rewardedAds[adUnitId] )
|
|
506
|
+
{
|
|
507
|
+
name = ON_REWARDED_AD_LOAD_FAILED_EVENT;
|
|
508
|
+
}
|
|
509
|
+
else
|
|
510
|
+
{
|
|
511
|
+
[self log: @"didFailToLoadAd — adUnitId '%@' not found in any dictionary (keys: adViews=%@, interstitials=%@, rewardedAds=%@)",
|
|
512
|
+
adUnitId, self.adViews.allKeys, self.interstitials.allKeys, self.rewardedAds.allKeys];
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
[self sendReactNativeEventWithName: name body: [self adLoadFailedInfoForAd: adUnitId withError: error]];
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
- (void)didClickAd:(CLXAd *)ad
|
|
521
|
+
{
|
|
522
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
523
|
+
NSString *name;
|
|
524
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
525
|
+
if ( adFormat == CLXAdFormatBanner )
|
|
526
|
+
{
|
|
527
|
+
name = ON_BANNER_AD_CLICKED_EVENT;
|
|
528
|
+
}
|
|
529
|
+
else if ( adFormat == CLXAdFormatMREC )
|
|
530
|
+
{
|
|
531
|
+
name = ON_MREC_AD_CLICKED_EVENT;
|
|
532
|
+
}
|
|
533
|
+
else if ( adFormat == CLXAdFormatInterstitial )
|
|
534
|
+
{
|
|
535
|
+
name = ON_INTERSTITIAL_CLICKED_EVENT;
|
|
536
|
+
}
|
|
537
|
+
else if ( adFormat == CLXAdFormatRewarded )
|
|
538
|
+
{
|
|
539
|
+
name = ON_REWARDED_AD_CLICKED_EVENT;
|
|
540
|
+
}
|
|
541
|
+
else
|
|
542
|
+
{
|
|
543
|
+
[self logInvalidAdFormat: adFormat];
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
[self sendReactNativeEventWithName: name body: [self adInfoForAd: ad]];
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
- (void)didDisplayAd:(CLXAd *)ad
|
|
552
|
+
{
|
|
553
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
554
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
555
|
+
if ( adFormat != CLXAdFormatInterstitial && adFormat != CLXAdFormatRewarded ) return;
|
|
556
|
+
|
|
557
|
+
NSString *name;
|
|
558
|
+
if ( adFormat == CLXAdFormatInterstitial )
|
|
559
|
+
{
|
|
560
|
+
name = ON_INTERSTITIAL_DISPLAYED_EVENT;
|
|
561
|
+
}
|
|
562
|
+
else
|
|
563
|
+
{
|
|
564
|
+
name = ON_REWARDED_AD_DISPLAYED_EVENT;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
[self sendReactNativeEventWithName: name body: [self adInfoForAd: ad]];
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
- (void)didFailToDisplayAd:(CLXAd *)ad error:(CLXError *)error
|
|
572
|
+
{
|
|
573
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
574
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
575
|
+
if ( adFormat != CLXAdFormatInterstitial && adFormat != CLXAdFormatRewarded ) return;
|
|
576
|
+
|
|
577
|
+
NSString *name;
|
|
578
|
+
if ( adFormat == CLXAdFormatInterstitial )
|
|
579
|
+
{
|
|
580
|
+
name = ON_INTERSTITIAL_DISPLAY_FAILED_EVENT;
|
|
581
|
+
}
|
|
582
|
+
else
|
|
583
|
+
{
|
|
584
|
+
name = ON_REWARDED_AD_DISPLAY_FAILED_EVENT;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
[self sendReactNativeEventWithName: name body: [self adDisplayFailedInfoForAd: ad withError: error]];
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
- (void)didHideAd:(CLXAd *)ad
|
|
592
|
+
{
|
|
593
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
594
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
595
|
+
if ( adFormat != CLXAdFormatInterstitial && adFormat != CLXAdFormatRewarded ) return;
|
|
596
|
+
|
|
597
|
+
NSString *name;
|
|
598
|
+
if ( adFormat == CLXAdFormatInterstitial )
|
|
599
|
+
{
|
|
600
|
+
name = ON_INTERSTITIAL_HIDDEN_EVENT;
|
|
601
|
+
}
|
|
602
|
+
else
|
|
603
|
+
{
|
|
604
|
+
name = ON_REWARDED_AD_HIDDEN_EVENT;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
[self sendReactNativeEventWithName: name body: [self adInfoForAd: ad]];
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
- (void)didExpandAd:(CLXAd *)ad
|
|
612
|
+
{
|
|
613
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
614
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
615
|
+
if ( adFormat != CLXAdFormatBanner && adFormat != CLXAdFormatMREC )
|
|
616
|
+
{
|
|
617
|
+
[self logInvalidAdFormat: adFormat];
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
[self sendReactNativeEventWithName: ( adFormat == CLXAdFormatMREC ) ? ON_MREC_AD_EXPANDED_EVENT : ON_BANNER_AD_EXPANDED_EVENT
|
|
622
|
+
body: [self adInfoForAd: ad]];
|
|
623
|
+
});
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
- (void)didCollapseAd:(CLXAd *)ad
|
|
627
|
+
{
|
|
628
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
629
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
630
|
+
if ( adFormat != CLXAdFormatBanner && adFormat != CLXAdFormatMREC )
|
|
631
|
+
{
|
|
632
|
+
[self logInvalidAdFormat: adFormat];
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
[self sendReactNativeEventWithName: ( adFormat == CLXAdFormatMREC ) ? ON_MREC_AD_COLLAPSED_EVENT : ON_BANNER_AD_COLLAPSED_EVENT
|
|
637
|
+
body: [self adInfoForAd: ad]];
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
- (void)didPayRevenueForAd:(CLXAd *)ad
|
|
642
|
+
{
|
|
643
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
644
|
+
NSString *name;
|
|
645
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
646
|
+
if ( adFormat == CLXAdFormatBanner )
|
|
647
|
+
{
|
|
648
|
+
name = ON_BANNER_AD_REVENUE_PAID;
|
|
649
|
+
}
|
|
650
|
+
else if ( adFormat == CLXAdFormatMREC )
|
|
651
|
+
{
|
|
652
|
+
name = ON_MREC_AD_REVENUE_PAID;
|
|
653
|
+
}
|
|
654
|
+
else if ( adFormat == CLXAdFormatInterstitial )
|
|
655
|
+
{
|
|
656
|
+
name = ON_INTERSTITIAL_AD_REVENUE_PAID;
|
|
657
|
+
}
|
|
658
|
+
else if ( adFormat == CLXAdFormatRewarded )
|
|
659
|
+
{
|
|
660
|
+
name = ON_REWARDED_AD_REVENUE_PAID;
|
|
661
|
+
}
|
|
662
|
+
else
|
|
663
|
+
{
|
|
664
|
+
[self logInvalidAdFormat: adFormat];
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
[self sendReactNativeEventWithName: name body: [self adInfoForAd: ad]];
|
|
669
|
+
});
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
- (void)didRewardUserForAd:(CLXAd *)ad withReward:(CLXReward *)reward
|
|
673
|
+
{
|
|
674
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
675
|
+
CLXAdFormat adFormat = ad.adFormat;
|
|
676
|
+
if ( adFormat != CLXAdFormatRewarded )
|
|
677
|
+
{
|
|
678
|
+
[self logInvalidAdFormat: adFormat];
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
NSString *rewardLabel = reward ? reward.label : @"";
|
|
683
|
+
NSInteger rewardAmount = reward ? reward.amount : 0;
|
|
684
|
+
|
|
685
|
+
NSMutableDictionary *body = [@{@"rewardLabel": rewardLabel,
|
|
686
|
+
@"rewardAmount": @(rewardAmount)} mutableCopy];
|
|
687
|
+
[body addEntriesFromDictionary: [self adInfoForAd: ad]];
|
|
688
|
+
|
|
689
|
+
[self sendReactNativeEventWithName: ON_REWARDED_AD_RECEIVED_REWARD_EVENT body: body];
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
#pragma mark - Internal Methods
|
|
694
|
+
|
|
695
|
+
- (void)executeOnMainQueue:(dispatch_block_t)block
|
|
696
|
+
{
|
|
697
|
+
if ( [NSThread isMainThread] )
|
|
698
|
+
{
|
|
699
|
+
block();
|
|
700
|
+
}
|
|
701
|
+
else
|
|
702
|
+
{
|
|
703
|
+
dispatch_async(dispatch_get_main_queue(), block);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
- (void)createAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat atPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset
|
|
708
|
+
{
|
|
709
|
+
[self executeOnMainQueue:^{
|
|
710
|
+
[self log: @"Creating %ld with ad unit identifier \"%@\", position: \"%@\", and offset: %@", (long)adFormat, adUnitIdentifier, adViewPosition, NSStringFromCGPoint(offset)];
|
|
711
|
+
|
|
712
|
+
CLXBannerAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat atPosition: adViewPosition withOffset: offset];
|
|
713
|
+
adView.hidden = YES;
|
|
714
|
+
self.safeAreaBackgrounds[adUnitIdentifier].hidden = YES;
|
|
715
|
+
|
|
716
|
+
self.adViewAdFormats[adUnitIdentifier] = @(adFormat);
|
|
717
|
+
[self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
718
|
+
|
|
719
|
+
[adView load];
|
|
720
|
+
|
|
721
|
+
// If showBanner/showMRec arrived before createBanner/createMRec finished,
|
|
722
|
+
// the identifier was queued; flush it now that the view exists.
|
|
723
|
+
if ( [self.adUnitIdentifiersToShowAfterCreate containsObject: adUnitIdentifier] )
|
|
724
|
+
{
|
|
725
|
+
[self showAdViewWithAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
726
|
+
[self.adUnitIdentifiersToShowAfterCreate removeObject: adUnitIdentifier];
|
|
727
|
+
}
|
|
728
|
+
}];
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
- (void)setAdViewBackgroundColorForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat hexColorCode:(NSString *)hexColorCode
|
|
732
|
+
{
|
|
733
|
+
[self executeOnMainQueue:^{
|
|
734
|
+
[self log: @"Setting %ld with ad unit identifier \"%@\" to color: \"%@\"", (long)adFormat, adUnitIdentifier, hexColorCode];
|
|
735
|
+
|
|
736
|
+
UIColor *convertedColor;
|
|
737
|
+
// FF000000 is opaque black, which UIColor renders identically to clearColor
|
|
738
|
+
// when composited. Nudge to FF000001 so the view is visibly black, not transparent.
|
|
739
|
+
if ( [hexColorCode containsString: @"FF000000"] )
|
|
740
|
+
{
|
|
741
|
+
convertedColor = [UIColor clx_colorWithHexString: @"FF000001"];
|
|
742
|
+
}
|
|
743
|
+
else
|
|
744
|
+
{
|
|
745
|
+
convertedColor = [UIColor clx_colorWithHexString: hexColorCode];
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
CLXBannerAdView *view = [self retrieveOrCreateBannerViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
749
|
+
self.publisherBannerBackgroundColors[adUnitIdentifier] = convertedColor;
|
|
750
|
+
self.safeAreaBackgrounds[adUnitIdentifier].backgroundColor = view.backgroundColor = convertedColor;
|
|
751
|
+
}];
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
- (void)setAdViewPlacement:(nullable NSString *)placement forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
755
|
+
{
|
|
756
|
+
[self executeOnMainQueue:^{
|
|
757
|
+
[self log: @"Setting placement \"%@\" for %ld with ad unit identifier \"%@\"", placement, (long)adFormat, adUnitIdentifier];
|
|
758
|
+
|
|
759
|
+
CLXBannerAdView *adView = [self retrieveOrCreateBannerViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
760
|
+
adView.placement = placement;
|
|
761
|
+
}];
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
- (void)setAdViewCustomData:(nullable NSString *)customData forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
765
|
+
{
|
|
766
|
+
[self executeOnMainQueue:^{
|
|
767
|
+
[self log: @"Setting custom data \"%@\" for %ld with ad unit identifier \"%@\"", customData, (long)adFormat, adUnitIdentifier];
|
|
768
|
+
|
|
769
|
+
CLXBannerAdView *adView = [self retrieveOrCreateBannerViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
770
|
+
adView.customData = customData;
|
|
771
|
+
}];
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
- (void)updateAdViewPosition:(NSString *)adViewPosition withOffset:(CGPoint)offset forAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
775
|
+
{
|
|
776
|
+
[self executeOnMainQueue:^{
|
|
777
|
+
self.adViewPositions[adUnitIdentifier] = adViewPosition;
|
|
778
|
+
self.adViewOffsets[adUnitIdentifier] = [NSValue valueWithCGPoint: offset];
|
|
779
|
+
[self positionAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
780
|
+
}];
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
- (void)startAutoRefresh:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
784
|
+
{
|
|
785
|
+
[self executeOnMainQueue:^{
|
|
786
|
+
[self log: @"Starting auto refresh %ld with ad unit identifier \"%@\"", (long)adFormat, adUnitIdentifier];
|
|
787
|
+
|
|
788
|
+
CLXBannerAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
789
|
+
[view startAutoRefresh];
|
|
790
|
+
}];
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
- (void)stopAutoRefresh:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
794
|
+
{
|
|
795
|
+
[self executeOnMainQueue:^{
|
|
796
|
+
[self log: @"Stopping auto refresh %ld with ad unit identifier \"%@\"", (long)adFormat, adUnitIdentifier];
|
|
797
|
+
|
|
798
|
+
CLXBannerAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
799
|
+
[view stopAutoRefresh];
|
|
800
|
+
}];
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
- (void)showAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
804
|
+
{
|
|
805
|
+
[self executeOnMainQueue:^{
|
|
806
|
+
[self log: @"Showing %ld with ad unit identifier \"%@\"", (long)adFormat, adUnitIdentifier];
|
|
807
|
+
|
|
808
|
+
CLXBannerAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
809
|
+
if ( !view )
|
|
810
|
+
{
|
|
811
|
+
[self log: @"%ld does not exist for ad unit identifier %@. Deferring show.", (long)adFormat, adUnitIdentifier];
|
|
812
|
+
[self.adUnitIdentifiersToShowAfterCreate addObject: adUnitIdentifier];
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
self.safeAreaBackgrounds[adUnitIdentifier].hidden = NO;
|
|
816
|
+
view.hidden = NO;
|
|
817
|
+
|
|
818
|
+
[view startAutoRefresh];
|
|
819
|
+
}];
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
- (void)hideAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
823
|
+
{
|
|
824
|
+
[self executeOnMainQueue:^{
|
|
825
|
+
[self log: @"Hiding %ld with ad unit identifier \"%@\"", (long)adFormat, adUnitIdentifier];
|
|
826
|
+
[self.adUnitIdentifiersToShowAfterCreate removeObject: adUnitIdentifier];
|
|
827
|
+
|
|
828
|
+
CLXBannerAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
829
|
+
view.hidden = YES;
|
|
830
|
+
self.safeAreaBackgrounds[adUnitIdentifier].hidden = YES;
|
|
831
|
+
|
|
832
|
+
[view stopAutoRefresh];
|
|
833
|
+
}];
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
- (void)destroyAdViewWithAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
837
|
+
{
|
|
838
|
+
[self executeOnMainQueue:^{
|
|
839
|
+
[self log: @"Destroying %ld with ad unit identifier \"%@\"", (long)adFormat, adUnitIdentifier];
|
|
840
|
+
|
|
841
|
+
[self.adUnitIdentifiersToShowAfterCreate removeObject: adUnitIdentifier];
|
|
842
|
+
|
|
843
|
+
CLXBannerAdView *view = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
844
|
+
view.delegate = nil;
|
|
845
|
+
view.revenueDelegate = nil;
|
|
846
|
+
|
|
847
|
+
NSArray<NSLayoutConstraint *> *activeConstraints = self.adViewConstraints[adUnitIdentifier];
|
|
848
|
+
[NSLayoutConstraint deactivateConstraints: activeConstraints];
|
|
849
|
+
|
|
850
|
+
[view destroy];
|
|
851
|
+
[view removeFromSuperview];
|
|
852
|
+
|
|
853
|
+
UIView *safeAreaBg = self.safeAreaBackgrounds[adUnitIdentifier];
|
|
854
|
+
[NSLayoutConstraint deactivateConstraints: safeAreaBg.constraints];
|
|
855
|
+
[safeAreaBg removeFromSuperview];
|
|
856
|
+
|
|
857
|
+
[self.adViews removeObjectForKey: adUnitIdentifier];
|
|
858
|
+
[self.adViewPositions removeObjectForKey: adUnitIdentifier];
|
|
859
|
+
[self.adViewOffsets removeObjectForKey: adUnitIdentifier];
|
|
860
|
+
[self.adViewAdFormats removeObjectForKey: adUnitIdentifier];
|
|
861
|
+
[self.adViewConstraints removeObjectForKey: adUnitIdentifier];
|
|
862
|
+
[self.safeAreaBackgrounds removeObjectForKey: adUnitIdentifier];
|
|
863
|
+
[self.publisherBannerBackgroundColors removeObjectForKey: adUnitIdentifier];
|
|
864
|
+
}];
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
- (CLXInterstitial *)retrieveInterstitialForAdUnitIdentifier:(NSString *)adUnitIdentifier
|
|
868
|
+
{
|
|
869
|
+
CLXInterstitial *result = self.interstitials[adUnitIdentifier];
|
|
870
|
+
if ( !result )
|
|
871
|
+
{
|
|
872
|
+
result = [[CloudXCore shared] createInterstitialWithAdUnitId: adUnitIdentifier];
|
|
873
|
+
result.delegate = self;
|
|
874
|
+
result.revenueDelegate = self;
|
|
875
|
+
|
|
876
|
+
self.interstitials[adUnitIdentifier] = result;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
return result;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
- (CLXRewarded *)retrieveRewardedAdForAdUnitIdentifier:(NSString *)adUnitIdentifier
|
|
883
|
+
{
|
|
884
|
+
CLXRewarded *result = self.rewardedAds[adUnitIdentifier];
|
|
885
|
+
if ( !result )
|
|
886
|
+
{
|
|
887
|
+
result = [[CloudXCore shared] createRewardedWithAdUnitId: adUnitIdentifier];
|
|
888
|
+
result.delegate = self;
|
|
889
|
+
result.revenueDelegate = self;
|
|
890
|
+
|
|
891
|
+
self.rewardedAds[adUnitIdentifier] = result;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
return result;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
- (nullable CLXBannerAdView *)retrieveAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
898
|
+
{
|
|
899
|
+
return [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat atPosition: nil withOffset: CGPointZero];
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
- (CLXBannerAdView *)retrieveOrCreateBannerViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
903
|
+
{
|
|
904
|
+
NSString *resolvedPosition = self.adViewPositions[adUnitIdentifier];
|
|
905
|
+
if ( !resolvedPosition || resolvedPosition.length == 0 )
|
|
906
|
+
{
|
|
907
|
+
// Use a stable default when setters run before create/show.
|
|
908
|
+
resolvedPosition = CENTERED;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
NSValue *resolvedOffsetValue = self.adViewOffsets[adUnitIdentifier];
|
|
912
|
+
CGPoint resolvedOffset = resolvedOffsetValue ? [resolvedOffsetValue CGPointValue] : CGPointZero;
|
|
913
|
+
|
|
914
|
+
return [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier
|
|
915
|
+
adFormat: adFormat
|
|
916
|
+
atPosition: resolvedPosition
|
|
917
|
+
withOffset: resolvedOffset];
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
- (nullable CLXBannerAdView *)retrieveAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat atPosition:(nullable NSString *)adViewPosition withOffset:(CGPoint)offset
|
|
921
|
+
{
|
|
922
|
+
if ( ![NSThread isMainThread] )
|
|
923
|
+
{
|
|
924
|
+
__block CLXBannerAdView *result = nil;
|
|
925
|
+
dispatch_sync(dispatch_get_main_queue(), ^{
|
|
926
|
+
result = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat atPosition: adViewPosition withOffset: offset];
|
|
927
|
+
});
|
|
928
|
+
return result;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
CLXBannerAdView *result = self.adViews[adUnitIdentifier];
|
|
932
|
+
// Only create a new view when a position is supplied; nil position means
|
|
933
|
+
// "read-only" lookup (e.g. from delegate callbacks or setter helpers).
|
|
934
|
+
if ( !result && adViewPosition )
|
|
935
|
+
{
|
|
936
|
+
if ( adFormat == CLXBannerTypeMREC )
|
|
937
|
+
{
|
|
938
|
+
result = [[CloudXCore shared] createMRECWithAdUnitId: adUnitIdentifier];
|
|
939
|
+
}
|
|
940
|
+
else
|
|
941
|
+
{
|
|
942
|
+
result = [[CloudXCore shared] createBannerWithAdUnitId: adUnitIdentifier];
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
result.delegate = self;
|
|
946
|
+
result.revenueDelegate = self;
|
|
947
|
+
result.userInteractionEnabled = NO;
|
|
948
|
+
result.translatesAutoresizingMaskIntoConstraints = NO;
|
|
949
|
+
|
|
950
|
+
self.adViews[adUnitIdentifier] = result;
|
|
951
|
+
self.adViewPositions[adUnitIdentifier] = adViewPosition;
|
|
952
|
+
self.adViewOffsets[adUnitIdentifier] = [NSValue valueWithCGPoint: offset];
|
|
953
|
+
|
|
954
|
+
UIView *rootView = [self topViewController].view;
|
|
955
|
+
if ( rootView )
|
|
956
|
+
{
|
|
957
|
+
[rootView addSubview: result];
|
|
958
|
+
}
|
|
959
|
+
else
|
|
960
|
+
{
|
|
961
|
+
[self log: @"retrieveAdView: no visible root view for ad unit \"%@\"", adUnitIdentifier];
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
return result;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
- (void)positionAdViewForAd:(CLXAd *)ad
|
|
969
|
+
{
|
|
970
|
+
[self executeOnMainQueue:^{
|
|
971
|
+
CLXBannerType bannerType = ( ad.adFormat == CLXAdFormatMREC ) ? CLXBannerTypeMREC : CLXBannerTypeW320H50;
|
|
972
|
+
[self positionAdViewForAdUnitIdentifier: ad.adUnitId adFormat: bannerType];
|
|
973
|
+
}];
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
- (void)positionAdViewForAdUnitIdentifier:(NSString *)adUnitIdentifier adFormat:(CLXBannerType)adFormat
|
|
977
|
+
{
|
|
978
|
+
[self executeOnMainQueue:^{
|
|
979
|
+
CLXBannerAdView *adView = [self retrieveAdViewForAdUnitIdentifier: adUnitIdentifier adFormat: adFormat];
|
|
980
|
+
NSString *adViewPosition = self.adViewPositions[adUnitIdentifier];
|
|
981
|
+
|
|
982
|
+
NSValue *adViewOffsetValue = self.adViewOffsets[adUnitIdentifier];
|
|
983
|
+
CGPoint adViewOffset = [adViewOffsetValue CGPointValue];
|
|
984
|
+
CGFloat xOffset = adViewOffset.x;
|
|
985
|
+
CGFloat yOffset = adViewOffset.y;
|
|
986
|
+
|
|
987
|
+
if ( [adViewPosition containsString: @"right"] )
|
|
988
|
+
{
|
|
989
|
+
xOffset = -xOffset;
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
if ( [adViewPosition containsString: @"bottom"] )
|
|
993
|
+
{
|
|
994
|
+
yOffset = -yOffset;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
UIView *superview = adView.superview;
|
|
998
|
+
if ( !superview ) return;
|
|
999
|
+
|
|
1000
|
+
NSArray<NSLayoutConstraint *> *activeConstraints = self.adViewConstraints[adUnitIdentifier];
|
|
1001
|
+
[NSLayoutConstraint deactivateConstraints: activeConstraints];
|
|
1002
|
+
|
|
1003
|
+
// Lazily create the per-ad-unit safe-area background on first position call.
|
|
1004
|
+
UIView *safeAreaBg = self.safeAreaBackgrounds[adUnitIdentifier];
|
|
1005
|
+
if ( !safeAreaBg )
|
|
1006
|
+
{
|
|
1007
|
+
safeAreaBg = [[UIView alloc] init];
|
|
1008
|
+
safeAreaBg.hidden = YES;
|
|
1009
|
+
safeAreaBg.backgroundColor = self.publisherBannerBackgroundColors[adUnitIdentifier] ?: UIColor.clearColor;
|
|
1010
|
+
safeAreaBg.translatesAutoresizingMaskIntoConstraints = NO;
|
|
1011
|
+
safeAreaBg.userInteractionEnabled = NO;
|
|
1012
|
+
self.safeAreaBackgrounds[adUnitIdentifier] = safeAreaBg;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
if ( ![superview.subviews containsObject: safeAreaBg] )
|
|
1016
|
+
{
|
|
1017
|
+
[safeAreaBg removeFromSuperview];
|
|
1018
|
+
[superview insertSubview: safeAreaBg belowSubview: adView];
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
[NSLayoutConstraint deactivateConstraints: safeAreaBg.constraints];
|
|
1022
|
+
safeAreaBg.hidden = adView.hidden;
|
|
1023
|
+
|
|
1024
|
+
CGFloat adViewHeight = [self adViewHeightForFormat: adFormat];
|
|
1025
|
+
CGFloat adViewWidth;
|
|
1026
|
+
|
|
1027
|
+
if ( [adViewPosition isEqual: TOP_CENTER] || [adViewPosition isEqual: BOTTOM_CENTER] )
|
|
1028
|
+
{
|
|
1029
|
+
adViewWidth = CGRectGetWidth(superview.bounds);
|
|
1030
|
+
}
|
|
1031
|
+
else
|
|
1032
|
+
{
|
|
1033
|
+
adViewWidth = [self adViewWidthForFormat: adFormat];
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
CGSize adViewSize = CGSizeMake(adViewWidth, adViewHeight);
|
|
1037
|
+
|
|
1038
|
+
NSMutableArray<NSLayoutConstraint *> *constraints = [NSMutableArray arrayWithObject: [adView.heightAnchor constraintEqualToConstant: adViewSize.height]];
|
|
1039
|
+
|
|
1040
|
+
UILayoutGuide *layoutGuide = superview.safeAreaLayoutGuide;
|
|
1041
|
+
|
|
1042
|
+
// TOP_CENTER / BOTTOM_CENTER with a publisher background color and no offset:
|
|
1043
|
+
// extend the safe-area background view beyond the layout guide so the color
|
|
1044
|
+
// bleeds into the notch/home-indicator region and looks like a solid bar.
|
|
1045
|
+
if ( [adViewPosition isEqual: TOP_CENTER] || [adViewPosition isEqual: BOTTOM_CENTER] )
|
|
1046
|
+
{
|
|
1047
|
+
if ( self.publisherBannerBackgroundColors[adUnitIdentifier] && adFormat != CLXBannerTypeMREC && CGPointEqualToPoint(adViewOffset, CGPointZero) )
|
|
1048
|
+
{
|
|
1049
|
+
[constraints addObjectsFromArray: @[[adView.widthAnchor constraintEqualToConstant: adViewWidth],
|
|
1050
|
+
[adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor],
|
|
1051
|
+
[safeAreaBg.widthAnchor constraintEqualToConstant: adViewWidth],
|
|
1052
|
+
[safeAreaBg.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor]]];
|
|
1053
|
+
|
|
1054
|
+
if ( [adViewPosition isEqual: TOP_CENTER] )
|
|
1055
|
+
{
|
|
1056
|
+
[constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor],
|
|
1057
|
+
[safeAreaBg.topAnchor constraintEqualToAnchor: superview.topAnchor],
|
|
1058
|
+
[safeAreaBg.bottomAnchor constraintEqualToAnchor: adView.topAnchor]]];
|
|
1059
|
+
}
|
|
1060
|
+
else
|
|
1061
|
+
{
|
|
1062
|
+
[constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor],
|
|
1063
|
+
[safeAreaBg.topAnchor constraintEqualToAnchor: adView.bottomAnchor],
|
|
1064
|
+
[safeAreaBg.bottomAnchor constraintEqualToAnchor: superview.bottomAnchor]]];
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
else
|
|
1068
|
+
{
|
|
1069
|
+
safeAreaBg.hidden = YES;
|
|
1070
|
+
|
|
1071
|
+
[constraints addObjectsFromArray: @[[adView.widthAnchor constraintEqualToConstant: adViewWidth],
|
|
1072
|
+
[adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor]]];
|
|
1073
|
+
|
|
1074
|
+
if ( [adViewPosition isEqual: TOP_CENTER] )
|
|
1075
|
+
{
|
|
1076
|
+
[constraints addObject: [adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor constant: yOffset]];
|
|
1077
|
+
}
|
|
1078
|
+
else
|
|
1079
|
+
{
|
|
1080
|
+
[constraints addObject: [adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor constant: yOffset]];
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
else
|
|
1085
|
+
{
|
|
1086
|
+
safeAreaBg.hidden = YES;
|
|
1087
|
+
|
|
1088
|
+
[constraints addObject: [adView.widthAnchor constraintEqualToConstant: adViewWidth]];
|
|
1089
|
+
|
|
1090
|
+
if ( [adViewPosition isEqual: TOP_LEFT] )
|
|
1091
|
+
{
|
|
1092
|
+
[constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor constant: yOffset],
|
|
1093
|
+
[adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor constant: xOffset]]];
|
|
1094
|
+
}
|
|
1095
|
+
else if ( [adViewPosition isEqual: TOP_RIGHT] )
|
|
1096
|
+
{
|
|
1097
|
+
[constraints addObjectsFromArray: @[[adView.topAnchor constraintEqualToAnchor: layoutGuide.topAnchor constant: yOffset],
|
|
1098
|
+
[adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor constant: xOffset]]];
|
|
1099
|
+
}
|
|
1100
|
+
else if ( [adViewPosition isEqual: CENTER_LEFT] )
|
|
1101
|
+
{
|
|
1102
|
+
[constraints addObjectsFromArray: @[[adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor constant: yOffset],
|
|
1103
|
+
[adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor constant: xOffset]]];
|
|
1104
|
+
}
|
|
1105
|
+
else if ( [adViewPosition isEqual: CENTERED] )
|
|
1106
|
+
{
|
|
1107
|
+
[constraints addObjectsFromArray: @[[adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor constant: xOffset],
|
|
1108
|
+
[adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor constant: yOffset]]];
|
|
1109
|
+
}
|
|
1110
|
+
else if ( [adViewPosition isEqual: CENTER_RIGHT] )
|
|
1111
|
+
{
|
|
1112
|
+
[constraints addObjectsFromArray: @[[adView.centerYAnchor constraintEqualToAnchor: layoutGuide.centerYAnchor constant: yOffset],
|
|
1113
|
+
[adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor constant: xOffset]]];
|
|
1114
|
+
}
|
|
1115
|
+
else if ( [adViewPosition isEqual: BOTTOM_LEFT] )
|
|
1116
|
+
{
|
|
1117
|
+
[constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor constant: yOffset],
|
|
1118
|
+
[adView.leftAnchor constraintEqualToAnchor: superview.leftAnchor constant: xOffset]]];
|
|
1119
|
+
}
|
|
1120
|
+
else if ( [adViewPosition isEqual: BOTTOM_RIGHT] )
|
|
1121
|
+
{
|
|
1122
|
+
[constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor constant: yOffset],
|
|
1123
|
+
[adView.rightAnchor constraintEqualToAnchor: superview.rightAnchor constant: xOffset]]];
|
|
1124
|
+
}
|
|
1125
|
+
else
|
|
1126
|
+
{
|
|
1127
|
+
[self log: @"Unrecognized ad view position: \"%@\", defaulting to bottom_center", adViewPosition];
|
|
1128
|
+
[constraints addObjectsFromArray: @[[adView.bottomAnchor constraintEqualToAnchor: layoutGuide.bottomAnchor],
|
|
1129
|
+
[adView.centerXAnchor constraintEqualToAnchor: layoutGuide.centerXAnchor]]];
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
self.adViewConstraints[adUnitIdentifier] = constraints;
|
|
1134
|
+
|
|
1135
|
+
[NSLayoutConstraint activateConstraints: constraints];
|
|
1136
|
+
}];
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
- (CGFloat)adViewWidthForFormat:(CLXBannerType)adFormat
|
|
1140
|
+
{
|
|
1141
|
+
if ( adFormat == CLXBannerTypeMREC ) return 300.0;
|
|
1142
|
+
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? 728.0 : 320.0;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
- (CGFloat)adViewHeightForFormat:(CLXBannerType)adFormat
|
|
1146
|
+
{
|
|
1147
|
+
if ( adFormat == CLXBannerTypeMREC ) return 250.0;
|
|
1148
|
+
return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ? 90.0 : 50.0;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
- (UIViewController *)topViewController
|
|
1152
|
+
{
|
|
1153
|
+
return [self deepestPresentedViewControllerFrom: [self keyWindowRootViewController]];
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
/// Scene-based key-window lookup (iOS 13+). Returns the root view controller of the
|
|
1157
|
+
/// foreground-active scene's key window, resolving the window at call time so callers
|
|
1158
|
+
/// never hold a stale reference.
|
|
1159
|
+
- (nullable UIViewController *)keyWindowRootViewController
|
|
1160
|
+
{
|
|
1161
|
+
for ( UIScene *scene in UIApplication.sharedApplication.connectedScenes )
|
|
1162
|
+
{
|
|
1163
|
+
if ( scene.activationState != UISceneActivationStateForegroundActive ) continue;
|
|
1164
|
+
if ( ![scene isKindOfClass: [UIWindowScene class]] ) continue;
|
|
1165
|
+
|
|
1166
|
+
UIWindowScene *windowScene = (UIWindowScene *)scene;
|
|
1167
|
+
for ( UIWindow *window in windowScene.windows )
|
|
1168
|
+
{
|
|
1169
|
+
if ( window.isKeyWindow ) return window.rootViewController;
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
return nil;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/// Walks the view-controller containment hierarchy to find the deepest visible leaf.
|
|
1176
|
+
/// Needed because UIKit rejects `presentViewController:` calls on a VC that already
|
|
1177
|
+
/// has a presented child. Terminates when no deeper child exists (next becomes nil).
|
|
1178
|
+
- (nullable UIViewController *)deepestPresentedViewControllerFrom:(nullable UIViewController *)root
|
|
1179
|
+
{
|
|
1180
|
+
UIViewController *vc = nil;
|
|
1181
|
+
UIViewController *next = root;
|
|
1182
|
+
|
|
1183
|
+
while ( next )
|
|
1184
|
+
{
|
|
1185
|
+
vc = next;
|
|
1186
|
+
next = vc.presentedViewController;
|
|
1187
|
+
|
|
1188
|
+
if ( !next && [vc isKindOfClass: [UINavigationController class]] )
|
|
1189
|
+
{
|
|
1190
|
+
UINavigationController *nav = (UINavigationController *)vc;
|
|
1191
|
+
next = nav.topViewController;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
if ( !next && [vc isKindOfClass: [UITabBarController class]] )
|
|
1195
|
+
{
|
|
1196
|
+
UITabBarController *tab = (UITabBarController *)vc;
|
|
1197
|
+
next = tab.selectedViewController;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
return vc;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
- (CLXLogLevel)logLevelFromString:(NSString *)level
|
|
1205
|
+
{
|
|
1206
|
+
NSString *lower = [level lowercaseString];
|
|
1207
|
+
if ( [lower isEqualToString: @"verbose"] ) return CLXLogLevelVerbose;
|
|
1208
|
+
if ( [lower isEqualToString: @"debug"] ) return CLXLogLevelDebug;
|
|
1209
|
+
if ( [lower isEqualToString: @"info"] ) return CLXLogLevelInfo;
|
|
1210
|
+
if ( [lower isEqualToString: @"warn"] ) return CLXLogLevelWarn;
|
|
1211
|
+
if ( [lower isEqualToString: @"error"] ) return CLXLogLevelError;
|
|
1212
|
+
if ( [lower isEqualToString: @"none"] ) return CLXLogLevelNone;
|
|
1213
|
+
return CLXLogLevelInfo;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
- (void)logInvalidAdFormat:(CLXAdFormat)adFormat
|
|
1217
|
+
{
|
|
1218
|
+
NSLog(@"[%@] [%@] invalid ad format: %ld, from %@", SDK_TAG, TAG, (long)adFormat, [NSThread callStackSymbols]);
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
- (void)log:(NSString *)format, ...
|
|
1222
|
+
{
|
|
1223
|
+
va_list valist;
|
|
1224
|
+
va_start(valist, format);
|
|
1225
|
+
NSString *message = [[NSString alloc] initWithFormat: format arguments: valist];
|
|
1226
|
+
va_end(valist);
|
|
1227
|
+
|
|
1228
|
+
NSLog(@"[%@] [%@] %@", SDK_TAG, TAG, message);
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
#pragma mark - Ad Info
|
|
1232
|
+
|
|
1233
|
+
- (NSDictionary<NSString *, id> *)adInfoForAd:(CLXAd *)ad
|
|
1234
|
+
{
|
|
1235
|
+
return @{@"adUnitId": ad.adUnitId ?: @"",
|
|
1236
|
+
@"adFormat": [self adFormatStringForAd: ad],
|
|
1237
|
+
@"networkName": ad.networkName ?: @"",
|
|
1238
|
+
@"networkPlacement": ad.networkPlacement ?: @"",
|
|
1239
|
+
@"placement": ad.placement ?: @"",
|
|
1240
|
+
@"revenue": ad.revenue ?: @(0)};
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1243
|
+
- (NSDictionary<NSString *, id> *)adLoadFailedInfoForAd:(NSString *)adUnitIdentifier withError:(nullable CLXError *)error
|
|
1244
|
+
{
|
|
1245
|
+
return error ?
|
|
1246
|
+
@{@"adUnitId": adUnitIdentifier,
|
|
1247
|
+
@"code": @(error.code),
|
|
1248
|
+
@"message": error.localizedDescription ?: @""}
|
|
1249
|
+
:
|
|
1250
|
+
@{@"adUnitId": adUnitIdentifier,
|
|
1251
|
+
@"code": @(CLXErrorCodeInternalError),
|
|
1252
|
+
@"message": @""};
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
- (NSDictionary<NSString *, id> *)adDisplayFailedInfoForAd:(CLXAd *)ad withError:(CLXError *)error
|
|
1256
|
+
{
|
|
1257
|
+
NSMutableDictionary *body = [@{@"code": @(error.code),
|
|
1258
|
+
@"message": error.localizedDescription ?: @""} mutableCopy];
|
|
1259
|
+
[body addEntriesFromDictionary: [self adInfoForAd: ad]];
|
|
1260
|
+
return body;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
- (NSString *)adFormatStringForAd:(CLXAd *)ad
|
|
1264
|
+
{
|
|
1265
|
+
switch ( ad.adFormat )
|
|
1266
|
+
{
|
|
1267
|
+
case CLXAdFormatBanner: return @"BANNER";
|
|
1268
|
+
case CLXAdFormatMREC: return @"MREC";
|
|
1269
|
+
case CLXAdFormatInterstitial: return @"INTERSTITIAL";
|
|
1270
|
+
case CLXAdFormatRewarded: return @"REWARDED";
|
|
1271
|
+
default: return @"";
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
#pragma mark - React Native Event Bridge
|
|
1276
|
+
|
|
1277
|
+
- (void)sendReactNativeEventWithName:(NSString *)name body:(NSDictionary<NSString *, id> *)body
|
|
1278
|
+
{
|
|
1279
|
+
[self sendEventWithName: name body: body];
|
|
1280
|
+
}
|
|
1281
|
+
|
|
1282
|
+
- (NSArray<NSString *> *)supportedEvents
|
|
1283
|
+
{
|
|
1284
|
+
return @[ON_MREC_AD_LOADED_EVENT,
|
|
1285
|
+
ON_MREC_AD_LOAD_FAILED_EVENT,
|
|
1286
|
+
ON_MREC_AD_CLICKED_EVENT,
|
|
1287
|
+
ON_MREC_AD_COLLAPSED_EVENT,
|
|
1288
|
+
ON_MREC_AD_EXPANDED_EVENT,
|
|
1289
|
+
ON_MREC_AD_REVENUE_PAID,
|
|
1290
|
+
|
|
1291
|
+
ON_BANNER_AD_LOADED_EVENT,
|
|
1292
|
+
ON_BANNER_AD_LOAD_FAILED_EVENT,
|
|
1293
|
+
ON_BANNER_AD_CLICKED_EVENT,
|
|
1294
|
+
ON_BANNER_AD_COLLAPSED_EVENT,
|
|
1295
|
+
ON_BANNER_AD_EXPANDED_EVENT,
|
|
1296
|
+
ON_BANNER_AD_REVENUE_PAID,
|
|
1297
|
+
|
|
1298
|
+
ON_INTERSTITIAL_LOADED_EVENT,
|
|
1299
|
+
ON_INTERSTITIAL_LOAD_FAILED_EVENT,
|
|
1300
|
+
ON_INTERSTITIAL_CLICKED_EVENT,
|
|
1301
|
+
ON_INTERSTITIAL_DISPLAYED_EVENT,
|
|
1302
|
+
ON_INTERSTITIAL_DISPLAY_FAILED_EVENT,
|
|
1303
|
+
ON_INTERSTITIAL_HIDDEN_EVENT,
|
|
1304
|
+
ON_INTERSTITIAL_AD_REVENUE_PAID,
|
|
1305
|
+
|
|
1306
|
+
ON_REWARDED_AD_LOADED_EVENT,
|
|
1307
|
+
ON_REWARDED_AD_LOAD_FAILED_EVENT,
|
|
1308
|
+
ON_REWARDED_AD_CLICKED_EVENT,
|
|
1309
|
+
ON_REWARDED_AD_DISPLAYED_EVENT,
|
|
1310
|
+
ON_REWARDED_AD_DISPLAY_FAILED_EVENT,
|
|
1311
|
+
ON_REWARDED_AD_HIDDEN_EVENT,
|
|
1312
|
+
ON_REWARDED_AD_RECEIVED_REWARD_EVENT,
|
|
1313
|
+
ON_REWARDED_AD_REVENUE_PAID];
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
- (NSDictionary *)constantsToExport
|
|
1317
|
+
{
|
|
1318
|
+
return @{@"ON_MREC_AD_LOADED_EVENT": ON_MREC_AD_LOADED_EVENT,
|
|
1319
|
+
@"ON_MREC_AD_LOAD_FAILED_EVENT": ON_MREC_AD_LOAD_FAILED_EVENT,
|
|
1320
|
+
@"ON_MREC_AD_CLICKED_EVENT": ON_MREC_AD_CLICKED_EVENT,
|
|
1321
|
+
@"ON_MREC_AD_COLLAPSED_EVENT": ON_MREC_AD_COLLAPSED_EVENT,
|
|
1322
|
+
@"ON_MREC_AD_EXPANDED_EVENT": ON_MREC_AD_EXPANDED_EVENT,
|
|
1323
|
+
@"ON_MREC_AD_REVENUE_PAID": ON_MREC_AD_REVENUE_PAID,
|
|
1324
|
+
|
|
1325
|
+
@"ON_BANNER_AD_LOADED_EVENT": ON_BANNER_AD_LOADED_EVENT,
|
|
1326
|
+
@"ON_BANNER_AD_LOAD_FAILED_EVENT": ON_BANNER_AD_LOAD_FAILED_EVENT,
|
|
1327
|
+
@"ON_BANNER_AD_CLICKED_EVENT": ON_BANNER_AD_CLICKED_EVENT,
|
|
1328
|
+
@"ON_BANNER_AD_COLLAPSED_EVENT": ON_BANNER_AD_COLLAPSED_EVENT,
|
|
1329
|
+
@"ON_BANNER_AD_EXPANDED_EVENT": ON_BANNER_AD_EXPANDED_EVENT,
|
|
1330
|
+
@"ON_BANNER_AD_REVENUE_PAID": ON_BANNER_AD_REVENUE_PAID,
|
|
1331
|
+
|
|
1332
|
+
@"ON_INTERSTITIAL_LOADED_EVENT": ON_INTERSTITIAL_LOADED_EVENT,
|
|
1333
|
+
@"ON_INTERSTITIAL_LOAD_FAILED_EVENT": ON_INTERSTITIAL_LOAD_FAILED_EVENT,
|
|
1334
|
+
@"ON_INTERSTITIAL_CLICKED_EVENT": ON_INTERSTITIAL_CLICKED_EVENT,
|
|
1335
|
+
@"ON_INTERSTITIAL_DISPLAYED_EVENT": ON_INTERSTITIAL_DISPLAYED_EVENT,
|
|
1336
|
+
@"ON_INTERSTITIAL_DISPLAY_FAILED_EVENT": ON_INTERSTITIAL_DISPLAY_FAILED_EVENT,
|
|
1337
|
+
@"ON_INTERSTITIAL_HIDDEN_EVENT": ON_INTERSTITIAL_HIDDEN_EVENT,
|
|
1338
|
+
@"ON_INTERSTITIAL_AD_REVENUE_PAID": ON_INTERSTITIAL_AD_REVENUE_PAID,
|
|
1339
|
+
|
|
1340
|
+
@"ON_REWARDED_AD_LOADED_EVENT": ON_REWARDED_AD_LOADED_EVENT,
|
|
1341
|
+
@"ON_REWARDED_AD_LOAD_FAILED_EVENT": ON_REWARDED_AD_LOAD_FAILED_EVENT,
|
|
1342
|
+
@"ON_REWARDED_AD_CLICKED_EVENT": ON_REWARDED_AD_CLICKED_EVENT,
|
|
1343
|
+
@"ON_REWARDED_AD_DISPLAYED_EVENT": ON_REWARDED_AD_DISPLAYED_EVENT,
|
|
1344
|
+
@"ON_REWARDED_AD_DISPLAY_FAILED_EVENT": ON_REWARDED_AD_DISPLAY_FAILED_EVENT,
|
|
1345
|
+
@"ON_REWARDED_AD_HIDDEN_EVENT": ON_REWARDED_AD_HIDDEN_EVENT,
|
|
1346
|
+
@"ON_REWARDED_AD_RECEIVED_REWARD_EVENT": ON_REWARDED_AD_RECEIVED_REWARD_EVENT,
|
|
1347
|
+
@"ON_REWARDED_AD_REVENUE_PAID": ON_REWARDED_AD_REVENUE_PAID,
|
|
1348
|
+
|
|
1349
|
+
@"TOP_CENTER_POSITION": TOP_CENTER,
|
|
1350
|
+
@"TOP_LEFT_POSITION": TOP_LEFT,
|
|
1351
|
+
@"TOP_RIGHT_POSITION": TOP_RIGHT,
|
|
1352
|
+
@"CENTERED_POSITION": CENTERED,
|
|
1353
|
+
@"CENTER_LEFT_POSITION": CENTER_LEFT,
|
|
1354
|
+
@"CENTER_RIGHT_POSITION": CENTER_RIGHT,
|
|
1355
|
+
@"BOTTOM_LEFT_POSITION": BOTTOM_LEFT,
|
|
1356
|
+
@"BOTTOM_CENTER_POSITION": BOTTOM_CENTER,
|
|
1357
|
+
@"BOTTOM_RIGHT_POSITION": BOTTOM_RIGHT};
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
- (NSDictionary *)getConstants
|
|
1361
|
+
{
|
|
1362
|
+
return [self constantsToExport];
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
- (void)startObserving
|
|
1366
|
+
{
|
|
1367
|
+
self.hasListeners = YES;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
- (void)stopObserving
|
|
1371
|
+
{
|
|
1372
|
+
self.hasListeners = NO;
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
1376
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
1377
|
+
{
|
|
1378
|
+
return std::make_shared<facebook::react::NativeCloudXSpecJSI>(params);
|
|
1379
|
+
}
|
|
1380
|
+
#endif
|
|
1381
|
+
|
|
1382
|
+
@end
|
|
1383
|
+
|
|
1384
|
+
@implementation UIColor (CLXUtils)
|
|
1385
|
+
|
|
1386
|
+
// Parses 6-digit (#RRGGBB) and 8-digit (#AARRGGBB) hex color strings into UIColor.
|
|
1387
|
+
// The AARRGGBB byte order matches Android's Color.parseColor convention, keeping
|
|
1388
|
+
// the cross-platform API surface consistent for JS callers.
|
|
1389
|
+
+ (nullable UIColor *)clx_colorWithHexString:(NSString *)hexString
|
|
1390
|
+
{
|
|
1391
|
+
NSString *hex = [hexString stringByReplacingOccurrencesOfString: @"#" withString: @""];
|
|
1392
|
+
if ( hex.length == 6 ) hex = [@"FF" stringByAppendingString: hex];
|
|
1393
|
+
if ( hex.length != 8 ) return nil;
|
|
1394
|
+
|
|
1395
|
+
unsigned int argb = 0;
|
|
1396
|
+
[[NSScanner scannerWithString: hex] scanHexInt: &argb];
|
|
1397
|
+
|
|
1398
|
+
CGFloat alpha = ((argb >> 24) & 0xFF) / 255.0;
|
|
1399
|
+
CGFloat red = ((argb >> 16) & 0xFF) / 255.0;
|
|
1400
|
+
CGFloat green = ((argb >> 8) & 0xFF) / 255.0;
|
|
1401
|
+
CGFloat blue = (argb & 0xFF) / 255.0;
|
|
1402
|
+
|
|
1403
|
+
return [UIColor colorWithRed: red green: green blue: blue alpha: alpha];
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
@end
|