react-native-empower-mobile-ads 1.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 +149 -0
- package/ios/EmpowerAdsModule.m +21 -0
- package/ios/EmpowerAdsModule.swift +111 -0
- package/ios/EmpowerAppOpenModule.m +16 -0
- package/ios/EmpowerAppOpenModule.swift +55 -0
- package/ios/EmpowerBannerViewManager.m +14 -0
- package/ios/EmpowerBannerViewManager.swift +121 -0
- package/ios/EmpowerInterstitialModule.m +18 -0
- package/ios/EmpowerInterstitialModule.swift +62 -0
- package/ios/EmpowerRewardedModule.m +18 -0
- package/ios/EmpowerRewardedModule.swift +70 -0
- package/lib/commonjs/AppOpenAd.js +40 -0
- package/lib/commonjs/AppOpenAd.js.map +1 -0
- package/lib/commonjs/BannerAd.js +69 -0
- package/lib/commonjs/BannerAd.js.map +1 -0
- package/lib/commonjs/EmpowerAds.js +62 -0
- package/lib/commonjs/EmpowerAds.js.map +1 -0
- package/lib/commonjs/InterstitialAd.js +40 -0
- package/lib/commonjs/InterstitialAd.js.map +1 -0
- package/lib/commonjs/RewardedAd.js +41 -0
- package/lib/commonjs/RewardedAd.js.map +1 -0
- package/lib/commonjs/StickyAd.js +71 -0
- package/lib/commonjs/StickyAd.js.map +1 -0
- package/lib/commonjs/index.js +61 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +34 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/AppOpenAd.js +34 -0
- package/lib/module/AppOpenAd.js.map +1 -0
- package/lib/module/BannerAd.js +61 -0
- package/lib/module/BannerAd.js.map +1 -0
- package/lib/module/EmpowerAds.js +56 -0
- package/lib/module/EmpowerAds.js.map +1 -0
- package/lib/module/InterstitialAd.js +34 -0
- package/lib/module/InterstitialAd.js.map +1 -0
- package/lib/module/RewardedAd.js +35 -0
- package/lib/module/RewardedAd.js.map +1 -0
- package/lib/module/StickyAd.js +63 -0
- package/lib/module/StickyAd.js.map +1 -0
- package/lib/module/index.js +15 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +37 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/AppOpenAd.d.ts +21 -0
- package/lib/typescript/AppOpenAd.d.ts.map +1 -0
- package/lib/typescript/BannerAd.d.ts +4 -0
- package/lib/typescript/BannerAd.d.ts.map +1 -0
- package/lib/typescript/EmpowerAds.d.ts +37 -0
- package/lib/typescript/EmpowerAds.d.ts.map +1 -0
- package/lib/typescript/InterstitialAd.d.ts +24 -0
- package/lib/typescript/InterstitialAd.d.ts.map +1 -0
- package/lib/typescript/RewardedAd.d.ts +25 -0
- package/lib/typescript/RewardedAd.d.ts.map +1 -0
- package/lib/typescript/StickyAd.d.ts +4 -0
- package/lib/typescript/StickyAd.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +8 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +80 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +63 -0
- package/react-native-empower-mobile-ads.podspec +27 -0
- package/src/AppOpenAd.ts +43 -0
- package/src/BannerAd.tsx +81 -0
- package/src/EmpowerAds.ts +63 -0
- package/src/InterstitialAd.ts +50 -0
- package/src/RewardedAd.ts +51 -0
- package/src/StickyAd.tsx +84 -0
- package/src/index.ts +23 -0
- package/src/types.ts +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# react-native-empower-mobile-ads
|
|
2
|
+
|
|
3
|
+
React Native bridge for EmpowerMobileAds SDK. Supports banner, sticky, interstitial, rewarded and app open ad formats.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install react-native-empower-mobile-ads
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### iOS Setup
|
|
12
|
+
|
|
13
|
+
**1.** Add the Empower private spec repo to your `Podfile`:
|
|
14
|
+
|
|
15
|
+
```ruby
|
|
16
|
+
source 'https://github.com/empowernet/specs.git'
|
|
17
|
+
source 'https://cdn.cocoapods.org/'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**2.** Install pods:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
cd ios && pod install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
### Initialize SDK
|
|
29
|
+
|
|
30
|
+
Call this once on app startup, before loading any ads:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { EmpowerAds } from 'react-native-empower-mobile-ads';
|
|
34
|
+
|
|
35
|
+
await EmpowerAds.initialize('YOUR_APP_IDENTIFIER', {
|
|
36
|
+
testMode: false,
|
|
37
|
+
logLevel: 'all',
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Banner Ad
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { BannerAd } from 'react-native-empower-mobile-ads';
|
|
45
|
+
|
|
46
|
+
<BannerAd
|
|
47
|
+
zoneId="your_zone_id"
|
|
48
|
+
style={{ width: 320, height: 50 }}
|
|
49
|
+
onAdLoaded={() => console.log('Ad loaded')}
|
|
50
|
+
onAdFailed={(error) => console.log('Ad failed:', error)}
|
|
51
|
+
onAdClicked={() => console.log('Ad clicked')}
|
|
52
|
+
onSizeChanged={({ width, height }) => console.log('New size:', width, height)}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Sticky Ad
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { StickyAd } from 'react-native-empower-mobile-ads';
|
|
60
|
+
|
|
61
|
+
<StickyAd
|
|
62
|
+
zoneId="your_zone_id"
|
|
63
|
+
style={{ width: 320, height: 50 }}
|
|
64
|
+
onAdLoaded={() => console.log('Sticky loaded')}
|
|
65
|
+
/>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Interstitial Ad
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { InterstitialAd } from 'react-native-empower-mobile-ads';
|
|
72
|
+
|
|
73
|
+
// Load
|
|
74
|
+
await InterstitialAd.load('your_zone_id');
|
|
75
|
+
|
|
76
|
+
// Show when ready
|
|
77
|
+
if (await InterstitialAd.isReady()) {
|
|
78
|
+
await InterstitialAd.show();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Listen for status changes
|
|
82
|
+
const remove = InterstitialAd.addEventListener('statusChanged', (event) => {
|
|
83
|
+
console.log('Interstitial status:', event.status);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Cleanup
|
|
87
|
+
remove();
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Rewarded Ad
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
import { RewardedAd } from 'react-native-empower-mobile-ads';
|
|
94
|
+
|
|
95
|
+
// Listen for reward
|
|
96
|
+
const remove = RewardedAd.addEventListener('statusChanged', (event) => {
|
|
97
|
+
if (event.status === 'rewarded') {
|
|
98
|
+
// Grant the reward
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Load & show
|
|
103
|
+
await RewardedAd.load('your_zone_id');
|
|
104
|
+
if (await RewardedAd.isReady()) {
|
|
105
|
+
await RewardedAd.show();
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### App Open Ad
|
|
110
|
+
|
|
111
|
+
```tsx
|
|
112
|
+
import { AppOpenAd } from 'react-native-empower-mobile-ads';
|
|
113
|
+
|
|
114
|
+
await AppOpenAd.load('your_zone_id');
|
|
115
|
+
if (await AppOpenAd.isReady()) {
|
|
116
|
+
await AppOpenAd.show();
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Configuration
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
// Content page for ad targeting
|
|
124
|
+
EmpowerAds.setContentPage('https://example.com/article/123');
|
|
125
|
+
|
|
126
|
+
// Global targeting parameters
|
|
127
|
+
EmpowerAds.setGlobalTargeting({
|
|
128
|
+
category: ['sports', 'news'],
|
|
129
|
+
section: ['homepage'],
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// User segments
|
|
133
|
+
EmpowerAds.setSegments(['premium_user']);
|
|
134
|
+
|
|
135
|
+
// GDPR - non-personalized ads
|
|
136
|
+
EmpowerAds.setNonPersonalized(true);
|
|
137
|
+
|
|
138
|
+
// Disable all ads
|
|
139
|
+
EmpowerAds.setAdsDisabled(true);
|
|
140
|
+
|
|
141
|
+
// Show remove ads button
|
|
142
|
+
EmpowerAds.setShowRemoveAdsButton(true);
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Requirements
|
|
146
|
+
|
|
147
|
+
- React Native >= 0.71
|
|
148
|
+
- iOS >= 13.0
|
|
149
|
+
- EmpowerMobileAds SDK (via CocoaPods private spec repo)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(EmpowerAdsModule, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(initialize:(NSString *)appId
|
|
7
|
+
options:(NSDictionary *)options
|
|
8
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
9
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
10
|
+
|
|
11
|
+
RCT_EXTERN_METHOD(setContentPage:(NSString *)url)
|
|
12
|
+
RCT_EXTERN_METHOD(setGlobalTargeting:(NSDictionary *)targeting)
|
|
13
|
+
RCT_EXTERN_METHOD(setSegments:(NSArray *)segments)
|
|
14
|
+
RCT_EXTERN_METHOD(setNonPersonalized:(BOOL)value)
|
|
15
|
+
RCT_EXTERN_METHOD(setAdsDisabled:(BOOL)value)
|
|
16
|
+
RCT_EXTERN_METHOD(setShowRemoveAdsButton:(BOOL)value)
|
|
17
|
+
|
|
18
|
+
RCT_EXTERN_METHOD(getNoktaId:(RCTPromiseResolveBlock)resolver
|
|
19
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
20
|
+
|
|
21
|
+
@end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import EmpowerMobileAds
|
|
4
|
+
|
|
5
|
+
@objc(EmpowerAdsModule)
|
|
6
|
+
class EmpowerAdsModule: RCTEventEmitter {
|
|
7
|
+
|
|
8
|
+
override static func moduleName() -> String! { "EmpowerAdsModule" }
|
|
9
|
+
override static func requiresMainQueueSetup() -> Bool { true }
|
|
10
|
+
|
|
11
|
+
override func supportedEvents() -> [String]! {
|
|
12
|
+
["onAdsReady", "onAdsFailed"]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@objc func initialize(_ appId: String, options: NSDictionary, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
16
|
+
DispatchQueue.main.async {
|
|
17
|
+
let testMode = options["testMode"] as? Bool ?? false
|
|
18
|
+
let appVersion = options["appVersion"] as? String ?? "1"
|
|
19
|
+
let vParam = options["vParam"] as? String
|
|
20
|
+
|
|
21
|
+
if let logLevel = options["logLevel"] as? String {
|
|
22
|
+
switch logLevel {
|
|
23
|
+
case "none": EMASettings.shared.logLevel = .none
|
|
24
|
+
case "error": EMASettings.shared.logLevel = .error
|
|
25
|
+
default: EMASettings.shared.logLevel = .all
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if let nonPersonalized = options["nonPersonalized"] as? Bool {
|
|
30
|
+
EMASettings.shared.isAdsNonPersonalized = nonPersonalized
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Set root view controller
|
|
34
|
+
EMASettings.shared.rootViewController = RCTPresentedViewController()
|
|
35
|
+
|
|
36
|
+
EMAManager.shared.initAd(appId, appVersion, testMode, vParam)
|
|
37
|
+
|
|
38
|
+
// Listen for config ready
|
|
39
|
+
EMAManager.shared.appViewDelegates.append(AppViewBridge(onComplete: { [weak self] in
|
|
40
|
+
self?.sendEvent(withName: "onAdsReady", body: nil)
|
|
41
|
+
resolver(nil)
|
|
42
|
+
}, onFail: { [weak self] in
|
|
43
|
+
self?.sendEvent(withName: "onAdsFailed", body: nil)
|
|
44
|
+
rejecter("ADS_INIT_FAILED", "EmpowerMobileAds initialization failed", nil)
|
|
45
|
+
}))
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@objc func setContentPage(_ url: String) {
|
|
50
|
+
DispatchQueue.main.async {
|
|
51
|
+
EMAManager.shared.contentPage = url
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@objc func setGlobalTargeting(_ targeting: NSDictionary) {
|
|
56
|
+
DispatchQueue.main.async {
|
|
57
|
+
var result: [String: [String]] = [:]
|
|
58
|
+
for (key, value) in targeting {
|
|
59
|
+
if let k = key as? String, let v = value as? [String] {
|
|
60
|
+
result[k] = v
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
EMAManager.shared.globalTargeting = result
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@objc func setSegments(_ segments: NSArray) {
|
|
68
|
+
DispatchQueue.main.async {
|
|
69
|
+
EMAManager.shared.segments = segments as? [String] ?? []
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@objc func setNonPersonalized(_ value: Bool) {
|
|
74
|
+
DispatchQueue.main.async {
|
|
75
|
+
EMASettings.shared.isAdsNonPersonalized = value
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@objc func setAdsDisabled(_ value: Bool) {
|
|
80
|
+
DispatchQueue.main.async {
|
|
81
|
+
EMASettings.shared.isAdsDisabled = value
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@objc func setShowRemoveAdsButton(_ value: Bool) {
|
|
86
|
+
DispatchQueue.main.async {
|
|
87
|
+
EMASettings.shared.showRemoveAdsButton = value
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@objc func getNoktaId(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
92
|
+
DispatchQueue.main.async {
|
|
93
|
+
let noktaId = EMAManager.shared.getNoktaId()
|
|
94
|
+
resolver(noktaId)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// MARK: - AppViewDelegate Bridge
|
|
100
|
+
private class AppViewBridge: NSObject, AppViewDelegate {
|
|
101
|
+
let onComplete: () -> Void
|
|
102
|
+
let onFail: () -> Void
|
|
103
|
+
|
|
104
|
+
init(onComplete: @escaping () -> Void, onFail: @escaping () -> Void) {
|
|
105
|
+
self.onComplete = onComplete
|
|
106
|
+
self.onFail = onFail
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
func appViewCompleted() { onComplete() }
|
|
110
|
+
func appViewFailed() { onFail() }
|
|
111
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(EmpowerAppOpenModule, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(load:(NSString *)zoneId
|
|
7
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
8
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
9
|
+
|
|
10
|
+
RCT_EXTERN_METHOD(isReady:(RCTPromiseResolveBlock)resolver
|
|
11
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
12
|
+
|
|
13
|
+
RCT_EXTERN_METHOD(show:(RCTPromiseResolveBlock)resolver
|
|
14
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
15
|
+
|
|
16
|
+
@end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import EmpowerMobileAds
|
|
4
|
+
|
|
5
|
+
@objc(EmpowerAppOpenModule)
|
|
6
|
+
class EmpowerAppOpenModule: RCTEventEmitter, AdStatusDelegate {
|
|
7
|
+
|
|
8
|
+
override static func moduleName() -> String! { "EmpowerAppOpenModule" }
|
|
9
|
+
override static func requiresMainQueueSetup() -> Bool { true }
|
|
10
|
+
|
|
11
|
+
override func supportedEvents() -> [String]! {
|
|
12
|
+
["onAppOpenStatusChanged"]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@objc func load(_ zoneId: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
16
|
+
DispatchQueue.main.async {
|
|
17
|
+
EMAManager.shared.loadAppOpen(zoneId: zoneId)
|
|
18
|
+
resolver(nil)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@objc func isReady(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
23
|
+
DispatchQueue.main.async {
|
|
24
|
+
resolver(EMAManager.shared.isAppOpenReady())
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@objc func show(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
29
|
+
DispatchQueue.main.async {
|
|
30
|
+
guard let rootVC = EMASettings.shared.rootViewController ?? RCTPresentedViewController() else {
|
|
31
|
+
rejecter("NO_VC", "No root view controller available", nil)
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
EMAManager.shared.showAppOpen(from: rootVC)
|
|
35
|
+
resolver(nil)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// MARK: - AdStatusDelegate
|
|
40
|
+
|
|
41
|
+
func empowerAppOpenStatusChanged(_ manager: EmpowerAppOpenManager) {
|
|
42
|
+
let statusString: String
|
|
43
|
+
switch manager.status {
|
|
44
|
+
case .ready: statusString = "ready"
|
|
45
|
+
case .failed: statusString = "failed"
|
|
46
|
+
case .used: statusString = "used"
|
|
47
|
+
case .willPresent: statusString = "willPresent"
|
|
48
|
+
default: statusString = "unknown"
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
sendEvent(withName: "onAppOpenStatusChanged", body: [
|
|
52
|
+
"status": statusString,
|
|
53
|
+
])
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import <React/RCTViewManager.h>
|
|
2
|
+
|
|
3
|
+
@interface RCT_EXTERN_MODULE(EmpowerBannerViewManager, RCTViewManager)
|
|
4
|
+
|
|
5
|
+
RCT_EXPORT_VIEW_PROPERTY(zoneId, NSString)
|
|
6
|
+
RCT_EXPORT_VIEW_PROPERTY(adType, NSString)
|
|
7
|
+
RCT_EXPORT_VIEW_PROPERTY(keywords, NSString)
|
|
8
|
+
RCT_EXPORT_VIEW_PROPERTY(customParameters, NSDictionary)
|
|
9
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdLoaded, RCTDirectEventBlock)
|
|
10
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdFailed, RCTDirectEventBlock)
|
|
11
|
+
RCT_EXPORT_VIEW_PROPERTY(onAdClicked, RCTDirectEventBlock)
|
|
12
|
+
RCT_EXPORT_VIEW_PROPERTY(onSizeChanged, RCTDirectEventBlock)
|
|
13
|
+
|
|
14
|
+
@end
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
import React
|
|
4
|
+
import EmpowerMobileAds
|
|
5
|
+
|
|
6
|
+
@objc(EmpowerBannerViewManager)
|
|
7
|
+
class EmpowerBannerViewManager: RCTViewManager {
|
|
8
|
+
|
|
9
|
+
override static func moduleName() -> String! { "EmpowerBannerView" }
|
|
10
|
+
override static func requiresMainQueueSetup() -> Bool { true }
|
|
11
|
+
|
|
12
|
+
override func view() -> UIView! {
|
|
13
|
+
return EmpowerBannerView(bridge: self.bridge)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// MARK: - EmpowerBannerView
|
|
18
|
+
class EmpowerBannerView: UIView, AdStatusDelegate {
|
|
19
|
+
|
|
20
|
+
private var bridge: RCTBridge?
|
|
21
|
+
private var zoneManager: EmpowerZoneManager?
|
|
22
|
+
private var containerView: UIView!
|
|
23
|
+
private var isAdLoaded = false
|
|
24
|
+
|
|
25
|
+
// React props
|
|
26
|
+
@objc var zoneId: String = "" { didSet { loadAdIfReady() } }
|
|
27
|
+
@objc var adType: String = "banner"
|
|
28
|
+
@objc var keywords: String?
|
|
29
|
+
@objc var customParameters: NSDictionary?
|
|
30
|
+
|
|
31
|
+
// React event callbacks
|
|
32
|
+
@objc var onAdLoaded: RCTDirectEventBlock?
|
|
33
|
+
@objc var onAdFailed: RCTDirectEventBlock?
|
|
34
|
+
@objc var onAdClicked: RCTDirectEventBlock?
|
|
35
|
+
@objc var onSizeChanged: RCTDirectEventBlock?
|
|
36
|
+
|
|
37
|
+
init(bridge: RCTBridge?) {
|
|
38
|
+
self.bridge = bridge
|
|
39
|
+
super.init(frame: .zero)
|
|
40
|
+
|
|
41
|
+
containerView = UIView()
|
|
42
|
+
containerView.translatesAutoresizingMaskIntoConstraints = false
|
|
43
|
+
addSubview(containerView)
|
|
44
|
+
|
|
45
|
+
NSLayoutConstraint.activate([
|
|
46
|
+
containerView.topAnchor.constraint(equalTo: topAnchor),
|
|
47
|
+
containerView.leadingAnchor.constraint(equalTo: leadingAnchor),
|
|
48
|
+
containerView.trailingAnchor.constraint(equalTo: trailingAnchor),
|
|
49
|
+
containerView.bottomAnchor.constraint(equalTo: bottomAnchor),
|
|
50
|
+
])
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
required init?(coder: NSCoder) { fatalError("init(coder:) not supported") }
|
|
54
|
+
|
|
55
|
+
// MARK: - Load
|
|
56
|
+
|
|
57
|
+
private func loadAdIfReady() {
|
|
58
|
+
guard !zoneId.isEmpty, !isAdLoaded else { return }
|
|
59
|
+
guard let rootVC = EMASettings.shared.rootViewController ?? RCTPresentedViewController() else { return }
|
|
60
|
+
|
|
61
|
+
isAdLoaded = true
|
|
62
|
+
|
|
63
|
+
var customParams: [String: [String]]? = nil
|
|
64
|
+
if let cp = customParameters as? [String: [String]] {
|
|
65
|
+
customParams = cp
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
DispatchQueue.main.async { [weak self] in
|
|
69
|
+
guard let self = self else { return }
|
|
70
|
+
|
|
71
|
+
self.zoneManager = EMAManager.shared.loadBannerAd(
|
|
72
|
+
viewController: rootVC,
|
|
73
|
+
zoneId: self.zoneId,
|
|
74
|
+
bannerContainer: self.containerView,
|
|
75
|
+
delegate: self,
|
|
76
|
+
adConfiguration: nil,
|
|
77
|
+
customParameters: customParams,
|
|
78
|
+
category: nil,
|
|
79
|
+
keywords: self.keywords
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// MARK: - AdStatusDelegate
|
|
85
|
+
|
|
86
|
+
func bannerStatusChanged(_ manager: EmpowerBannerManager) {
|
|
87
|
+
DispatchQueue.main.async { [weak self] in
|
|
88
|
+
guard let self = self else { return }
|
|
89
|
+
|
|
90
|
+
switch manager.status {
|
|
91
|
+
case .ready:
|
|
92
|
+
self.onAdLoaded?([:])
|
|
93
|
+
|
|
94
|
+
// Report actual size back to RN so the JS side can adjust layout
|
|
95
|
+
let adWidth = manager.bannerModel.width
|
|
96
|
+
let adHeight = manager.bannerModel.height
|
|
97
|
+
if adWidth > 0, adHeight > 0 {
|
|
98
|
+
self.onSizeChanged?([
|
|
99
|
+
"width": adWidth,
|
|
100
|
+
"height": adHeight,
|
|
101
|
+
])
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
case .failed:
|
|
105
|
+
self.onAdFailed?(["error": "Ad failed to load"])
|
|
106
|
+
|
|
107
|
+
case .willPresent, .willLeave:
|
|
108
|
+
self.onAdClicked?([:])
|
|
109
|
+
|
|
110
|
+
default:
|
|
111
|
+
break
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// MARK: - Cleanup
|
|
117
|
+
|
|
118
|
+
deinit {
|
|
119
|
+
zoneManager?.destroy()
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(EmpowerInterstitialModule, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(load:(NSString *)zoneId
|
|
7
|
+
keywords:(NSString *)keywords
|
|
8
|
+
customParameters:(NSDictionary *)customParameters
|
|
9
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
10
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
11
|
+
|
|
12
|
+
RCT_EXTERN_METHOD(isReady:(RCTPromiseResolveBlock)resolver
|
|
13
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
14
|
+
|
|
15
|
+
RCT_EXTERN_METHOD(show:(RCTPromiseResolveBlock)resolver
|
|
16
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
17
|
+
|
|
18
|
+
@end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import EmpowerMobileAds
|
|
4
|
+
|
|
5
|
+
@objc(EmpowerInterstitialModule)
|
|
6
|
+
class EmpowerInterstitialModule: RCTEventEmitter, AdStatusDelegate {
|
|
7
|
+
|
|
8
|
+
private var zoneManager: EmpowerZoneManager?
|
|
9
|
+
|
|
10
|
+
override static func moduleName() -> String! { "EmpowerInterstitialModule" }
|
|
11
|
+
override static func requiresMainQueueSetup() -> Bool { true }
|
|
12
|
+
|
|
13
|
+
override func supportedEvents() -> [String]! {
|
|
14
|
+
["onInterstitialStatusChanged"]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@objc func load(_ zoneId: String?, keywords: String?, customParameters: NSDictionary?,
|
|
18
|
+
resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
19
|
+
DispatchQueue.main.async { [weak self] in
|
|
20
|
+
guard let self = self else { return }
|
|
21
|
+
|
|
22
|
+
var customParams: [String: [String]]? = nil
|
|
23
|
+
if let cp = customParameters as? [String: [String]] {
|
|
24
|
+
customParams = cp
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
EMAManager.shared.loadInterstitial(
|
|
28
|
+
zoneId: zoneId,
|
|
29
|
+
delegate: self,
|
|
30
|
+
customParameters: customParams,
|
|
31
|
+
keywords: keywords
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
resolver(nil)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@objc func isReady(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
39
|
+
DispatchQueue.main.async {
|
|
40
|
+
resolver(EMAManager.shared.isInterstitialReady())
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@objc func show(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
45
|
+
DispatchQueue.main.async {
|
|
46
|
+
guard let rootVC = EMASettings.shared.rootViewController ?? RCTPresentedViewController() else {
|
|
47
|
+
rejecter("NO_VC", "No root view controller available", nil)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
EMAManager.shared.showInterstitial(from: rootVC)
|
|
51
|
+
resolver(nil)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// MARK: - AdStatusDelegate
|
|
56
|
+
|
|
57
|
+
func interstitialStatusChanged(_ manager: EmpowerInterstitialManager) {
|
|
58
|
+
sendEvent(withName: "onInterstitialStatusChanged", body: [
|
|
59
|
+
"status": manager.status.rawValue,
|
|
60
|
+
])
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTEventEmitter.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(EmpowerRewardedModule, RCTEventEmitter)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(load:(NSString *)zoneId
|
|
7
|
+
keywords:(NSString *)keywords
|
|
8
|
+
customParameters:(NSDictionary *)customParameters
|
|
9
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
10
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
11
|
+
|
|
12
|
+
RCT_EXTERN_METHOD(isReady:(RCTPromiseResolveBlock)resolver
|
|
13
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
14
|
+
|
|
15
|
+
RCT_EXTERN_METHOD(show:(RCTPromiseResolveBlock)resolver
|
|
16
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
17
|
+
|
|
18
|
+
@end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import EmpowerMobileAds
|
|
4
|
+
|
|
5
|
+
@objc(EmpowerRewardedModule)
|
|
6
|
+
class EmpowerRewardedModule: RCTEventEmitter, AdStatusDelegate {
|
|
7
|
+
|
|
8
|
+
override static func moduleName() -> String! { "EmpowerRewardedModule" }
|
|
9
|
+
override static func requiresMainQueueSetup() -> Bool { true }
|
|
10
|
+
|
|
11
|
+
override func supportedEvents() -> [String]! {
|
|
12
|
+
["onRewardedStatusChanged"]
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
@objc func load(_ zoneId: String?, keywords: String?, customParameters: NSDictionary?,
|
|
16
|
+
resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
17
|
+
DispatchQueue.main.async { [weak self] in
|
|
18
|
+
guard let self = self else { return }
|
|
19
|
+
|
|
20
|
+
var customParams: [String: [String]]? = nil
|
|
21
|
+
if let cp = customParameters as? [String: [String]] {
|
|
22
|
+
customParams = cp
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
EMAManager.shared.loadRewarded(
|
|
26
|
+
zoneId: zoneId,
|
|
27
|
+
delegate: self,
|
|
28
|
+
customParameters: customParams,
|
|
29
|
+
keywords: keywords
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
resolver(nil)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@objc func isReady(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
37
|
+
DispatchQueue.main.async {
|
|
38
|
+
resolver(EMAManager.shared.isRewardedReady())
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@objc func show(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
43
|
+
DispatchQueue.main.async {
|
|
44
|
+
guard let rootVC = EMASettings.shared.rootViewController ?? RCTPresentedViewController() else {
|
|
45
|
+
rejecter("NO_VC", "No root view controller available", nil)
|
|
46
|
+
return
|
|
47
|
+
}
|
|
48
|
+
EMAManager.shared.showRewarded(from: rootVC)
|
|
49
|
+
resolver(nil)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// MARK: - AdStatusDelegate
|
|
54
|
+
|
|
55
|
+
func rewardedStatusChanged(_ manager: EmpowerRewardedManager) {
|
|
56
|
+
let statusString: String
|
|
57
|
+
switch manager.status {
|
|
58
|
+
case .rewarded: statusString = "rewarded"
|
|
59
|
+
case .ready: statusString = "ready"
|
|
60
|
+
case .failed: statusString = "failed"
|
|
61
|
+
case .used: statusString = "used"
|
|
62
|
+
case .willPresent: statusString = "willPresent"
|
|
63
|
+
default: statusString = "unknown"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
sendEvent(withName: "onRewardedStatusChanged", body: [
|
|
67
|
+
"status": statusString,
|
|
68
|
+
])
|
|
69
|
+
}
|
|
70
|
+
}
|