novvy-ads-react-native 1.0.0-beta.1
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/LICENSE +21 -0
- package/README.md +210 -0
- package/android/build.gradle +84 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +4 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdContainerView.kt +63 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdsModule.kt +390 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyAdsPackage.kt +46 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyPauseAdViewManager.kt +68 -0
- package/android/src/main/java/ai/novvy/reactnative/NovvyScrollAdViewManager.kt +72 -0
- package/android/src/main/java/ai/novvy/reactnative/RnPlayerAdapter.kt +18 -0
- package/android/src/main/java/ai/novvy/reactnative/ViewReadyEvent.kt +26 -0
- package/app.plugin.js +4 -0
- package/ios/NovvyAds.mm +168 -0
- package/ios/NovvyAdsImpl.swift +409 -0
- package/ios/NovvyPauseAdView.mm +79 -0
- package/ios/NovvyScrollAdView.mm +80 -0
- package/ios/RnPlayerAdapter.swift +14 -0
- package/lib/commonjs/NovvyAds.js +87 -0
- package/lib/commonjs/NovvyAds.js.map +1 -0
- package/lib/commonjs/ads/NovvyAd.js +121 -0
- package/lib/commonjs/ads/NovvyAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyEndAd.js +19 -0
- package/lib/commonjs/ads/NovvyEndAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyFullScreenAd.js +49 -0
- package/lib/commonjs/ads/NovvyFullScreenAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyInterstitialAd.js +19 -0
- package/lib/commonjs/ads/NovvyInterstitialAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyMidAd.js +19 -0
- package/lib/commonjs/ads/NovvyMidAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyPauseAd.js +116 -0
- package/lib/commonjs/ads/NovvyPauseAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyRewardedAd.js +53 -0
- package/lib/commonjs/ads/NovvyRewardedAd.js.map +1 -0
- package/lib/commonjs/ads/NovvyScrollAd.js +136 -0
- package/lib/commonjs/ads/NovvyScrollAd.js.map +1 -0
- package/lib/commonjs/eventBus.js +60 -0
- package/lib/commonjs/eventBus.js.map +1 -0
- package/lib/commonjs/index.js +90 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/spec/NativeNovvyAds.js +27 -0
- package/lib/commonjs/spec/NativeNovvyAds.js.map +1 -0
- package/lib/commonjs/spec/NovvyPauseAdViewNativeComponent.js +16 -0
- package/lib/commonjs/spec/NovvyPauseAdViewNativeComponent.js.map +1 -0
- package/lib/commonjs/spec/NovvyScrollAdViewNativeComponent.js +17 -0
- package/lib/commonjs/spec/NovvyScrollAdViewNativeComponent.js.map +1 -0
- package/lib/commonjs/spec/codegen-event-emitter.d.js +2 -0
- package/lib/commonjs/spec/codegen-event-emitter.d.js.map +1 -0
- package/lib/commonjs/types.js +54 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/views/NovvyPauseAdView.js +76 -0
- package/lib/commonjs/views/NovvyPauseAdView.js.map +1 -0
- package/lib/commonjs/views/NovvyScrollAdView.js +63 -0
- package/lib/commonjs/views/NovvyScrollAdView.js.map +1 -0
- package/lib/module/NovvyAds.js +83 -0
- package/lib/module/NovvyAds.js.map +1 -0
- package/lib/module/ads/NovvyAd.js +117 -0
- package/lib/module/ads/NovvyAd.js.map +1 -0
- package/lib/module/ads/NovvyEndAd.js +15 -0
- package/lib/module/ads/NovvyEndAd.js.map +1 -0
- package/lib/module/ads/NovvyFullScreenAd.js +45 -0
- package/lib/module/ads/NovvyFullScreenAd.js.map +1 -0
- package/lib/module/ads/NovvyInterstitialAd.js +15 -0
- package/lib/module/ads/NovvyInterstitialAd.js.map +1 -0
- package/lib/module/ads/NovvyMidAd.js +15 -0
- package/lib/module/ads/NovvyMidAd.js.map +1 -0
- package/lib/module/ads/NovvyPauseAd.js +112 -0
- package/lib/module/ads/NovvyPauseAd.js.map +1 -0
- package/lib/module/ads/NovvyRewardedAd.js +49 -0
- package/lib/module/ads/NovvyRewardedAd.js.map +1 -0
- package/lib/module/ads/NovvyScrollAd.js +132 -0
- package/lib/module/ads/NovvyScrollAd.js.map +1 -0
- package/lib/module/eventBus.js +55 -0
- package/lib/module/eventBus.js.map +1 -0
- package/lib/module/index.js +22 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/spec/NativeNovvyAds.js +28 -0
- package/lib/module/spec/NativeNovvyAds.js.map +1 -0
- package/lib/module/spec/NovvyPauseAdViewNativeComponent.js +13 -0
- package/lib/module/spec/NovvyPauseAdViewNativeComponent.js.map +1 -0
- package/lib/module/spec/NovvyScrollAdViewNativeComponent.js +14 -0
- package/lib/module/spec/NovvyScrollAdViewNativeComponent.js.map +1 -0
- package/lib/module/spec/codegen-event-emitter.d.js +2 -0
- package/lib/module/spec/codegen-event-emitter.d.js.map +1 -0
- package/lib/module/types.js +56 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/views/NovvyPauseAdView.js +70 -0
- package/lib/module/views/NovvyPauseAdView.js.map +1 -0
- package/lib/module/views/NovvyScrollAdView.js +57 -0
- package/lib/module/views/NovvyScrollAdView.js.map +1 -0
- package/lib/typescript/NovvyAds.d.ts +69 -0
- package/lib/typescript/NovvyAds.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyAd.d.ts +57 -0
- package/lib/typescript/ads/NovvyAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyEndAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyEndAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyFullScreenAd.d.ts +19 -0
- package/lib/typescript/ads/NovvyFullScreenAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyInterstitialAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyInterstitialAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyMidAd.d.ts +7 -0
- package/lib/typescript/ads/NovvyMidAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyPauseAd.d.ts +45 -0
- package/lib/typescript/ads/NovvyPauseAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyRewardedAd.d.ts +19 -0
- package/lib/typescript/ads/NovvyRewardedAd.d.ts.map +1 -0
- package/lib/typescript/ads/NovvyScrollAd.d.ts +57 -0
- package/lib/typescript/ads/NovvyScrollAd.d.ts.map +1 -0
- package/lib/typescript/eventBus.d.ts +15 -0
- package/lib/typescript/eventBus.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +15 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/spec/NativeNovvyAds.d.ts +73 -0
- package/lib/typescript/spec/NativeNovvyAds.d.ts.map +1 -0
- package/lib/typescript/spec/NovvyPauseAdViewNativeComponent.d.ts +18 -0
- package/lib/typescript/spec/NovvyPauseAdViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/spec/NovvyScrollAdViewNativeComponent.d.ts +19 -0
- package/lib/typescript/spec/NovvyScrollAdViewNativeComponent.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +77 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/lib/typescript/views/NovvyPauseAdView.d.ts +21 -0
- package/lib/typescript/views/NovvyPauseAdView.d.ts.map +1 -0
- package/lib/typescript/views/NovvyScrollAdView.d.ts +22 -0
- package/lib/typescript/views/NovvyScrollAdView.d.ts.map +1 -0
- package/novvy-ads-react-native.podspec +71 -0
- package/package.json +84 -0
- package/plugin/build/index.d.ts +11 -0
- package/plugin/build/index.js +53 -0
- package/react-native.config.js +7 -0
- package/src/NovvyAds.ts +98 -0
- package/src/ads/NovvyAd.ts +125 -0
- package/src/ads/NovvyEndAd.ts +13 -0
- package/src/ads/NovvyFullScreenAd.ts +46 -0
- package/src/ads/NovvyInterstitialAd.ts +13 -0
- package/src/ads/NovvyMidAd.ts +13 -0
- package/src/ads/NovvyPauseAd.ts +125 -0
- package/src/ads/NovvyRewardedAd.ts +49 -0
- package/src/ads/NovvyScrollAd.ts +138 -0
- package/src/eventBus.ts +59 -0
- package/src/index.tsx +29 -0
- package/src/spec/NativeNovvyAds.ts +134 -0
- package/src/spec/NovvyPauseAdViewNativeComponent.ts +20 -0
- package/src/spec/NovvyScrollAdViewNativeComponent.ts +21 -0
- package/src/spec/codegen-event-emitter.d.ts +10 -0
- package/src/types.ts +82 -0
- package/src/views/NovvyPauseAdView.tsx +80 -0
- package/src/views/NovvyScrollAdView.tsx +71 -0
package/ios/NovvyAds.mm
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#import <React/RCTBridgeModule.h>
|
|
2
|
+
#import <React/RCTUtils.h>
|
|
3
|
+
|
|
4
|
+
// Swift implementation (generated umbrella header for this pod's Swift module).
|
|
5
|
+
#import "NovvyAdsReactNative-Swift.h"
|
|
6
|
+
|
|
7
|
+
// Codegen'd TurboModule spec (present when the new architecture is enabled).
|
|
8
|
+
#import "NovvyAdsSpec.h"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* TurboModule entry point. All business logic lives in the Swift
|
|
12
|
+
* `NovvyAdsImpl` (which calls the NovvyAds SDK); this thin ObjC++ layer only
|
|
13
|
+
* bridges codegen method calls and the `onAdEvent` emitter to it.
|
|
14
|
+
*/
|
|
15
|
+
@interface NovvyAds : NativeNovvyAdsSpecBase <NativeNovvyAdsSpec>
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
@implementation NovvyAds {
|
|
19
|
+
NovvyAdsImpl *_impl;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
RCT_EXPORT_MODULE(NovvyAds)
|
|
23
|
+
|
|
24
|
+
- (instancetype)init {
|
|
25
|
+
if (self = [super init]) {
|
|
26
|
+
_impl = NovvyAdsImpl.shared;
|
|
27
|
+
__weak NovvyAds *weakSelf = self;
|
|
28
|
+
_impl.eventSink = ^(NSDictionary *value) {
|
|
29
|
+
[weakSelf emitOnAdEvent:value];
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
return self;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
36
|
+
return NO;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// All methods touch UIKit views (Fabric containers) or the Novvy SDK's inline
|
|
40
|
+
// player, both of which are main-thread-only. Force every TurboModule call
|
|
41
|
+
// onto the main queue instead of RN's default serial GCD queue.
|
|
42
|
+
- (dispatch_queue_t)methodQueue {
|
|
43
|
+
return dispatch_get_main_queue();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// MARK: - SDK & context
|
|
47
|
+
|
|
48
|
+
RCT_EXPORT_METHOD(initialize:(NSString *)appId
|
|
49
|
+
endpoint:(NSString *)endpoint
|
|
50
|
+
apiKey:(NSString *)apiKey
|
|
51
|
+
userContext:(NSDictionary *)userContext
|
|
52
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
53
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
54
|
+
[_impl initializeWithAppId:appId
|
|
55
|
+
endpoint:endpoint
|
|
56
|
+
apiKey:apiKey
|
|
57
|
+
userContext:userContext
|
|
58
|
+
completion:^(BOOL success) { resolve(@(success)); }];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
RCT_EXPORT_METHOD(setUserContext:(NSDictionary *)context) {
|
|
62
|
+
[_impl setUserContext:context];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
RCT_EXPORT_METHOD(updateUserContext:(NSDictionary *)partial) {
|
|
66
|
+
[_impl updateUserContext:partial];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
RCT_EXPORT_METHOD(setContentContext:(NSDictionary *)context) {
|
|
70
|
+
[_impl setContentContext:context];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
RCT_EXPORT_METHOD(updateContentContext:(NSDictionary *)partial) {
|
|
74
|
+
[_impl updateContentContext:partial];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// MARK: - Full-screen ads
|
|
78
|
+
|
|
79
|
+
RCT_EXPORT_METHOD(loadInterstitialAd:(NSString *)adUnitId adObjectId:(NSString *)adObjectId) {
|
|
80
|
+
[_impl loadInterstitialAdWithAdUnitId:adUnitId adObjectId:adObjectId];
|
|
81
|
+
}
|
|
82
|
+
RCT_EXPORT_METHOD(showInterstitialAd:(NSString *)adObjectId) {
|
|
83
|
+
[_impl showInterstitialAdWithAdObjectId:adObjectId];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
RCT_EXPORT_METHOD(loadRewardedAd:(NSString *)adUnitId adObjectId:(NSString *)adObjectId) {
|
|
87
|
+
[_impl loadRewardedAdWithAdUnitId:adUnitId adObjectId:adObjectId];
|
|
88
|
+
}
|
|
89
|
+
RCT_EXPORT_METHOD(showRewardedAd:(NSString *)adObjectId) {
|
|
90
|
+
[_impl showRewardedAdWithAdObjectId:adObjectId];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
RCT_EXPORT_METHOD(loadMidAd:(NSString *)adUnitId adObjectId:(NSString *)adObjectId) {
|
|
94
|
+
[_impl loadMidAdWithAdUnitId:adUnitId adObjectId:adObjectId];
|
|
95
|
+
}
|
|
96
|
+
RCT_EXPORT_METHOD(showMidAd:(NSString *)adObjectId) {
|
|
97
|
+
[_impl showMidAdWithAdObjectId:adObjectId];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
RCT_EXPORT_METHOD(loadEndAd:(NSString *)adUnitId adObjectId:(NSString *)adObjectId) {
|
|
101
|
+
[_impl loadEndAdWithAdUnitId:adUnitId adObjectId:adObjectId];
|
|
102
|
+
}
|
|
103
|
+
RCT_EXPORT_METHOD(showEndAd:(NSString *)adObjectId) {
|
|
104
|
+
[_impl showEndAdWithAdObjectId:adObjectId];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// MARK: - Scroll
|
|
108
|
+
|
|
109
|
+
RCT_EXPORT_METHOD(loadScrollAd:(NSString *)adUnitId
|
|
110
|
+
adObjectId:(NSString *)adObjectId
|
|
111
|
+
episodeNumber:(NSNumber *)episodeNumber) {
|
|
112
|
+
[_impl loadScrollAdWithAdUnitId:adUnitId adObjectId:adObjectId episodeNumber:episodeNumber];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
RCT_EXPORT_METHOD(attachScrollAd:(NSString *)adObjectId
|
|
116
|
+
durationSeconds:(NSNumber *)durationSeconds
|
|
117
|
+
useDefaultSwipeOverlay:(BOOL)useDefaultSwipeOverlay) {
|
|
118
|
+
[_impl attachScrollAdWithAdObjectId:adObjectId
|
|
119
|
+
durationSeconds:durationSeconds
|
|
120
|
+
useDefaultSwipeOverlay:useDefaultSwipeOverlay];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
RCT_EXPORT_METHOD(setScrollAdPlaying:(NSString *)adObjectId playing:(BOOL)playing) {
|
|
124
|
+
[_impl setScrollAdPlayingWithAdObjectId:adObjectId playing:playing];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
RCT_EXPORT_METHOD(detachScrollAd:(NSString *)adObjectId) {
|
|
128
|
+
[_impl detachScrollAdWithAdObjectId:adObjectId];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// MARK: - Pause
|
|
132
|
+
|
|
133
|
+
RCT_EXPORT_METHOD(attachPauseAd:(NSString *)adUnitId
|
|
134
|
+
adObjectId:(NSString *)adObjectId
|
|
135
|
+
positionMs:(double)positionMs
|
|
136
|
+
isPlaying:(BOOL)isPlaying) {
|
|
137
|
+
[_impl attachPauseAdWithAdUnitId:adUnitId
|
|
138
|
+
adObjectId:adObjectId
|
|
139
|
+
positionMs:(int64_t)positionMs
|
|
140
|
+
isPlaying:isPlaying];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
RCT_EXPORT_METHOD(updatePauseAdPlayerState:(NSString *)adObjectId
|
|
144
|
+
positionMs:(double)positionMs
|
|
145
|
+
isPlaying:(BOOL)isPlaying) {
|
|
146
|
+
[_impl updatePauseAdPlayerStateWithAdObjectId:adObjectId
|
|
147
|
+
positionMs:(int64_t)positionMs
|
|
148
|
+
isPlaying:isPlaying];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
RCT_EXPORT_METHOD(detachPauseAd:(NSString *)adObjectId) {
|
|
152
|
+
[_impl detachPauseAdWithAdObjectId:adObjectId];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// MARK: - Common
|
|
156
|
+
|
|
157
|
+
RCT_EXPORT_METHOD(disposeAd:(NSString *)adObjectId) {
|
|
158
|
+
[_impl disposeAdWithAdObjectId:adObjectId];
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// MARK: - TurboModule
|
|
162
|
+
|
|
163
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
164
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params {
|
|
165
|
+
return std::make_shared<facebook::react::NativeNovvyAdsSpecJSI>(params);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@end
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
import NovvyAds
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Business logic bridging the Novvy iOS ad SDK to React Native.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors the Flutter plugin's `NovvyAdsApiImpl.swift` one-to-one. A single
|
|
9
|
+
* `eventSink` closure multiplexes every ad's lifecycle events to JS as an
|
|
10
|
+
* `NSDictionary`; each JS ad object filters by its own `adObjectId`.
|
|
11
|
+
*
|
|
12
|
+
* A process-wide `shared` instance lets the Fabric view classes register their
|
|
13
|
+
* containers with the same object the TurboModule drives.
|
|
14
|
+
*/
|
|
15
|
+
@objc public final class NovvyAdsImpl: NSObject {
|
|
16
|
+
|
|
17
|
+
@objc public static let shared = NovvyAdsImpl()
|
|
18
|
+
|
|
19
|
+
/// Set by the TurboModule; forwards event dictionaries to `emitOnAdEvent`.
|
|
20
|
+
@objc public var eventSink: ((NSDictionary) -> Void)?
|
|
21
|
+
|
|
22
|
+
private var adMap: [String: AnyObject] = [:]
|
|
23
|
+
private var scrollContainerMap: [String: UIView] = [:]
|
|
24
|
+
private var pauseContainerMap: [String: UIView] = [:]
|
|
25
|
+
private var pauseAdapterMap: [String: RnPlayerAdapter] = [:]
|
|
26
|
+
/// The SDK holds delegates weakly, so retain them here per ad.
|
|
27
|
+
private var delegateMap: [String: AnyObject] = [:]
|
|
28
|
+
|
|
29
|
+
// Event name constants — must match the NovvyAdEvent string union in TS.
|
|
30
|
+
private enum Ev {
|
|
31
|
+
static let loaded = "loaded"
|
|
32
|
+
static let failed = "failedToLoad"
|
|
33
|
+
static let showed = "showed"
|
|
34
|
+
static let dismissed = "dismissed"
|
|
35
|
+
static let hidden = "hidden"
|
|
36
|
+
static let earnedReward = "earnedReward"
|
|
37
|
+
static let playbackTick = "playbackTick"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// MARK: - Event emission
|
|
41
|
+
|
|
42
|
+
private func emit(
|
|
43
|
+
_ adObjectId: String,
|
|
44
|
+
_ adUnitId: String,
|
|
45
|
+
_ event: String,
|
|
46
|
+
error: String? = nil,
|
|
47
|
+
remainingSeconds: Int? = nil
|
|
48
|
+
) {
|
|
49
|
+
let dict = NSMutableDictionary()
|
|
50
|
+
dict["adObjectId"] = adObjectId
|
|
51
|
+
dict["adUnitId"] = adUnitId
|
|
52
|
+
dict["event"] = event
|
|
53
|
+
if let error { dict["error"] = error }
|
|
54
|
+
if let remainingSeconds { dict["remainingSeconds"] = remainingSeconds }
|
|
55
|
+
let sink = eventSink
|
|
56
|
+
if Thread.isMainThread {
|
|
57
|
+
sink?(dict)
|
|
58
|
+
} else {
|
|
59
|
+
DispatchQueue.main.async { sink?(dict) }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
private func makeEmit(_ adObjectId: String, _ adUnitId: String)
|
|
64
|
+
-> (String, String?, Int?) -> Void {
|
|
65
|
+
return { [weak self] event, error, remaining in
|
|
66
|
+
self?.emit(adObjectId, adUnitId, event, error: error, remainingSeconds: remaining)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// MARK: - Initialization & context
|
|
71
|
+
|
|
72
|
+
@objc public func initialize(
|
|
73
|
+
appId: String,
|
|
74
|
+
endpoint: String,
|
|
75
|
+
apiKey: String,
|
|
76
|
+
userContext: NSDictionary?,
|
|
77
|
+
completion: @escaping (Bool) -> Void
|
|
78
|
+
) {
|
|
79
|
+
NovvySDK.shared.initialize(
|
|
80
|
+
appId: appId,
|
|
81
|
+
endpoint: endpoint,
|
|
82
|
+
apiKey: apiKey,
|
|
83
|
+
userContext: userContext?.toSdkUserContext(),
|
|
84
|
+
completion: { success in
|
|
85
|
+
if Thread.isMainThread { completion(success) }
|
|
86
|
+
else { DispatchQueue.main.async { completion(success) } }
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@objc public func setUserContext(_ context: NSDictionary) {
|
|
92
|
+
NovvySDK.shared.setUserContext(context.toSdkUserContext())
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@objc public func updateUserContext(_ partial: NSDictionary) {
|
|
96
|
+
NovvySDK.shared.updateUserContext(
|
|
97
|
+
userId: partial.optString("userId"),
|
|
98
|
+
hashedEmail: partial.optString("hashedEmail"),
|
|
99
|
+
isPaidUser: partial.optBool("isPaidUser"),
|
|
100
|
+
age: partial.optInt("age"),
|
|
101
|
+
gender: partial.optString("gender"),
|
|
102
|
+
dramaWatchHistory: (partial["dramaWatchHistory"] as? [NSDictionary])?.toSdkRecords(),
|
|
103
|
+
maximumAdsInOneDrama: partial.optInt("maximumAdsInOneDrama")
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@objc public func setContentContext(_ context: NSDictionary) {
|
|
108
|
+
NovvySDK.shared.setContentContext(NovvyAds.NovvyContentContext(
|
|
109
|
+
seriesName: context.optString("seriesName"),
|
|
110
|
+
episodeNumber: context.optInt("episodeNumber"),
|
|
111
|
+
url: context.optString("url")
|
|
112
|
+
))
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@objc public func updateContentContext(_ partial: NSDictionary) {
|
|
116
|
+
NovvySDK.shared.updateContentContext(
|
|
117
|
+
seriesName: partial.optString("seriesName"),
|
|
118
|
+
episodeNumber: partial.optInt("episodeNumber"),
|
|
119
|
+
url: partial.optString("url")
|
|
120
|
+
)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// MARK: - Interstitial
|
|
124
|
+
|
|
125
|
+
@objc public func loadInterstitialAd(adUnitId: String, adObjectId: String) {
|
|
126
|
+
let ad = NovvyInterstitialAd(adUnitId: adUnitId)
|
|
127
|
+
let delegate = InterstitialDelegate(emit: makeEmit(adObjectId, adUnitId))
|
|
128
|
+
ad.delegate = delegate
|
|
129
|
+
adMap[adObjectId] = ad
|
|
130
|
+
delegateMap[adObjectId] = delegate
|
|
131
|
+
ad.load()
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@objc public func showInterstitialAd(adObjectId: String) {
|
|
135
|
+
guard let ad = adMap[adObjectId] as? NovvyInterstitialAd else { return }
|
|
136
|
+
guard let vc = Self.topViewController() else {
|
|
137
|
+
emit(adObjectId, ad.adUnitId, Ev.failed, error: "No active ViewController available")
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
ad.show(from: vc)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// MARK: - Rewarded
|
|
144
|
+
|
|
145
|
+
@objc public func loadRewardedAd(adUnitId: String, adObjectId: String) {
|
|
146
|
+
let ad = NovvyRewardedAd(adUnitId: adUnitId)
|
|
147
|
+
let delegate = RewardedDelegate(emit: makeEmit(adObjectId, adUnitId))
|
|
148
|
+
ad.delegate = delegate
|
|
149
|
+
adMap[adObjectId] = ad
|
|
150
|
+
delegateMap[adObjectId] = delegate
|
|
151
|
+
ad.load()
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@objc public func showRewardedAd(adObjectId: String) {
|
|
155
|
+
guard let ad = adMap[adObjectId] as? NovvyRewardedAd else { return }
|
|
156
|
+
guard let vc = Self.topViewController() else {
|
|
157
|
+
emit(adObjectId, ad.adUnitId, Ev.failed, error: "No active ViewController available")
|
|
158
|
+
return
|
|
159
|
+
}
|
|
160
|
+
ad.show(from: vc)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// MARK: - Mid-roll
|
|
164
|
+
|
|
165
|
+
@objc public func loadMidAd(adUnitId: String, adObjectId: String) {
|
|
166
|
+
let ad = NovvyMidAd(adUnitId: adUnitId)
|
|
167
|
+
let delegate = MidDelegate(emit: makeEmit(adObjectId, adUnitId))
|
|
168
|
+
ad.delegate = delegate
|
|
169
|
+
adMap[adObjectId] = ad
|
|
170
|
+
delegateMap[adObjectId] = delegate
|
|
171
|
+
ad.load()
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@objc public func showMidAd(adObjectId: String) {
|
|
175
|
+
guard let ad = adMap[adObjectId] as? NovvyMidAd else { return }
|
|
176
|
+
guard let vc = Self.topViewController() else {
|
|
177
|
+
emit(adObjectId, ad.adUnitId, Ev.failed, error: "No active ViewController available")
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
ad.show(from: vc)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// MARK: - End-roll
|
|
184
|
+
|
|
185
|
+
@objc public func loadEndAd(adUnitId: String, adObjectId: String) {
|
|
186
|
+
let ad = NovvyEndAd(adUnitId: adUnitId)
|
|
187
|
+
let delegate = EndDelegate(emit: makeEmit(adObjectId, adUnitId))
|
|
188
|
+
ad.delegate = delegate
|
|
189
|
+
adMap[adObjectId] = ad
|
|
190
|
+
delegateMap[adObjectId] = delegate
|
|
191
|
+
ad.load()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
@objc public func showEndAd(adObjectId: String) {
|
|
195
|
+
guard let ad = adMap[adObjectId] as? NovvyEndAd else { return }
|
|
196
|
+
guard let vc = Self.topViewController() else {
|
|
197
|
+
emit(adObjectId, ad.adUnitId, Ev.failed, error: "No active ViewController available")
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
ad.show(from: vc)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// MARK: - Scroll (inline feed)
|
|
204
|
+
|
|
205
|
+
@objc public func loadScrollAd(adUnitId: String, adObjectId: String, episodeNumber: NSNumber?) {
|
|
206
|
+
let ad = NovvyScrollAd(adUnitId: adUnitId, episode: episodeNumber?.intValue)
|
|
207
|
+
let delegate = ScrollDelegate(emit: makeEmit(adObjectId, adUnitId))
|
|
208
|
+
ad.delegate = delegate
|
|
209
|
+
adMap[adObjectId] = ad
|
|
210
|
+
delegateMap[adObjectId] = delegate
|
|
211
|
+
ad.load()
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
@objc public func attachScrollAd(adObjectId: String, durationSeconds: NSNumber?, useDefaultSwipeOverlay: Bool) {
|
|
215
|
+
guard let ad = adMap[adObjectId] as? NovvyScrollAd,
|
|
216
|
+
let container = scrollContainerMap[adObjectId] else { return }
|
|
217
|
+
ad.attach(
|
|
218
|
+
to: container,
|
|
219
|
+
durationSeconds: durationSeconds?.intValue,
|
|
220
|
+
useDefaultSwipeOverlay: useDefaultSwipeOverlay,
|
|
221
|
+
onAdPlaybackTick: { [weak self] remaining in
|
|
222
|
+
self?.emit(adObjectId, "", Ev.playbackTick, remainingSeconds: remaining)
|
|
223
|
+
}
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@objc public func setScrollAdPlaying(adObjectId: String, playing: Bool) {
|
|
228
|
+
(adMap[adObjectId] as? NovvyScrollAd)?.setPlaying(playing)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@objc public func detachScrollAd(adObjectId: String) {
|
|
232
|
+
(adMap[adObjectId] as? NovvyScrollAd)?.detach()
|
|
233
|
+
scrollContainerMap.removeValue(forKey: adObjectId)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// MARK: - Pause (realtime pause card)
|
|
237
|
+
|
|
238
|
+
@objc public func attachPauseAd(adUnitId: String, adObjectId: String, positionMs: Int64, isPlaying: Bool) {
|
|
239
|
+
guard let container = pauseContainerMap[adObjectId] else { return }
|
|
240
|
+
let adapter = RnPlayerAdapter()
|
|
241
|
+
adapter.currentPositionMs = positionMs
|
|
242
|
+
adapter.isPlaying = isPlaying
|
|
243
|
+
pauseAdapterMap[adObjectId] = adapter
|
|
244
|
+
|
|
245
|
+
let ad = NovvyPauseAd(adUnitId: adUnitId)
|
|
246
|
+
let delegate = PauseDelegate(emit: makeEmit(adObjectId, adUnitId))
|
|
247
|
+
ad.delegate = delegate
|
|
248
|
+
adMap[adObjectId] = ad
|
|
249
|
+
delegateMap[adObjectId] = delegate
|
|
250
|
+
ad.attach(to: container, player: adapter)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@objc public func updatePauseAdPlayerState(adObjectId: String, positionMs: Int64, isPlaying: Bool) {
|
|
254
|
+
guard let adapter = pauseAdapterMap[adObjectId] else { return }
|
|
255
|
+
adapter.currentPositionMs = positionMs
|
|
256
|
+
adapter.isPlaying = isPlaying
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@objc public func detachPauseAd(adObjectId: String) {
|
|
260
|
+
(adMap[adObjectId] as? NovvyPauseAd)?.detach()
|
|
261
|
+
pauseContainerMap.removeValue(forKey: adObjectId)
|
|
262
|
+
pauseAdapterMap.removeValue(forKey: adObjectId)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// MARK: - Dispose
|
|
266
|
+
|
|
267
|
+
@objc public func disposeAd(adObjectId: String) {
|
|
268
|
+
switch adMap[adObjectId] {
|
|
269
|
+
case let ad as NovvyPauseAd:
|
|
270
|
+
ad.detach(); ad.destroy()
|
|
271
|
+
pauseContainerMap.removeValue(forKey: adObjectId)
|
|
272
|
+
pauseAdapterMap.removeValue(forKey: adObjectId)
|
|
273
|
+
case let ad as NovvyScrollAd:
|
|
274
|
+
ad.detach(); ad.destroy()
|
|
275
|
+
scrollContainerMap.removeValue(forKey: adObjectId)
|
|
276
|
+
case let ad as NovvyRewardedAd: ad.destroy()
|
|
277
|
+
case let ad as NovvyInterstitialAd: ad.destroy()
|
|
278
|
+
case let ad as NovvyMidAd: ad.destroy()
|
|
279
|
+
case let ad as NovvyEndAd: ad.destroy()
|
|
280
|
+
default: break
|
|
281
|
+
}
|
|
282
|
+
adMap.removeValue(forKey: adObjectId)
|
|
283
|
+
delegateMap.removeValue(forKey: adObjectId)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// MARK: - Platform view helpers (called by Fabric view classes)
|
|
287
|
+
|
|
288
|
+
@objc public func registerScrollContainer(adObjectId: String, container: UIView) {
|
|
289
|
+
scrollContainerMap[adObjectId] = container
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
@objc public func registerPauseContainer(adObjectId: String, container: UIView) {
|
|
293
|
+
pauseContainerMap[adObjectId] = container
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@objc public func onScrollViewDisposed(adObjectId: String) {
|
|
297
|
+
detachScrollAd(adObjectId: adObjectId)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@objc public func onPauseViewDisposed(adObjectId: String) {
|
|
301
|
+
detachPauseAd(adObjectId: adObjectId)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// MARK: - Helpers
|
|
305
|
+
|
|
306
|
+
private static func topViewController() -> UIViewController? {
|
|
307
|
+
let scenes = UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }
|
|
308
|
+
let activeScene = scenes.first(where: { $0.activationState == .foregroundActive }) ?? scenes.first
|
|
309
|
+
let keyWindow = activeScene?.windows.first(where: { $0.isKeyWindow }) ?? activeScene?.windows.first
|
|
310
|
+
var top = keyWindow?.rootViewController
|
|
311
|
+
while let presented = top?.presentedViewController {
|
|
312
|
+
top = presented
|
|
313
|
+
}
|
|
314
|
+
return top
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// MARK: - NSDictionary parsing helpers
|
|
319
|
+
|
|
320
|
+
private extension NSDictionary {
|
|
321
|
+
func optString(_ key: String) -> String? { self[key] as? String }
|
|
322
|
+
func optBool(_ key: String) -> Bool? { (self[key] as? NSNumber)?.boolValue }
|
|
323
|
+
func optInt(_ key: String) -> Int? { (self[key] as? NSNumber)?.intValue }
|
|
324
|
+
|
|
325
|
+
func toSdkUserContext() -> NovvyAds.NovvyUserContext {
|
|
326
|
+
NovvyAds.NovvyUserContext(
|
|
327
|
+
userId: optString("userId"),
|
|
328
|
+
hashedEmail: optString("hashedEmail"),
|
|
329
|
+
isPaidUser: optBool("isPaidUser"),
|
|
330
|
+
age: optInt("age"),
|
|
331
|
+
gender: optString("gender"),
|
|
332
|
+
dramaWatchHistory: (self["dramaWatchHistory"] as? [NSDictionary])?.toSdkRecords(),
|
|
333
|
+
maximumAdsInOneDrama: optInt("maximumAdsInOneDrama")
|
|
334
|
+
)
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
private extension Array where Element == NSDictionary {
|
|
339
|
+
func toSdkRecords() -> [NovvyAds.NovvyDramaRecord] {
|
|
340
|
+
compactMap { record in
|
|
341
|
+
guard let seriesId = record["seriesId"] as? String else { return nil }
|
|
342
|
+
return NovvyAds.NovvyDramaRecord(
|
|
343
|
+
dramaTitle: record["dramaTitle"] as? String,
|
|
344
|
+
seriesId: seriesId,
|
|
345
|
+
lastWatchedEpisode: (record["lastWatchedEpisode"] as? NSNumber)?.intValue ?? 0,
|
|
346
|
+
unlockedEpisode: (record["unlockedEpisode"] as? NSNumber)?.intValue ?? 0
|
|
347
|
+
)
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// MARK: - Delegate adapters
|
|
353
|
+
//
|
|
354
|
+
// Each captures an `emit` closure translating SDK delegate callbacks into
|
|
355
|
+
// event strings. Retained in `delegateMap` because the SDK holds delegates weakly.
|
|
356
|
+
|
|
357
|
+
private final class InterstitialDelegate: NSObject, NovvyInterstitialAdDelegate {
|
|
358
|
+
let emit: (String, String?, Int?) -> Void
|
|
359
|
+
init(emit: @escaping (String, String?, Int?) -> Void) { self.emit = emit }
|
|
360
|
+
func interstitialAdDidLoad(_ ad: NovvyInterstitialAd) { emit("loaded", nil, nil) }
|
|
361
|
+
func interstitialAd(_ ad: NovvyInterstitialAd, didFailToLoadWithError error: NovvyError) { emit("failedToLoad", error.localizedDescription, nil) }
|
|
362
|
+
func interstitialAdDidShow(_ ad: NovvyInterstitialAd) { emit("showed", nil, nil) }
|
|
363
|
+
func interstitialAdDidClose(_ ad: NovvyInterstitialAd) { emit("dismissed", nil, nil) }
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
private final class RewardedDelegate: NSObject, NovvyRewardedAdDelegate {
|
|
367
|
+
let emit: (String, String?, Int?) -> Void
|
|
368
|
+
init(emit: @escaping (String, String?, Int?) -> Void) { self.emit = emit }
|
|
369
|
+
func rewardedAdDidLoad(_ ad: NovvyRewardedAd) { emit("loaded", nil, nil) }
|
|
370
|
+
func rewardedAd(_ ad: NovvyRewardedAd, didFailToLoadWithError error: NovvyError) { emit("failedToLoad", error.localizedDescription, nil) }
|
|
371
|
+
func rewardedAdDidShow(_ ad: NovvyRewardedAd) { emit("showed", nil, nil) }
|
|
372
|
+
func rewardedAd(_ ad: NovvyRewardedAd, didEarnReward reward: NovvyReward) { emit("earnedReward", nil, nil) }
|
|
373
|
+
func rewardedAdDidClose(_ ad: NovvyRewardedAd) { emit("dismissed", nil, nil) }
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
private final class MidDelegate: NSObject, NovvyMidAdDelegate {
|
|
377
|
+
let emit: (String, String?, Int?) -> Void
|
|
378
|
+
init(emit: @escaping (String, String?, Int?) -> Void) { self.emit = emit }
|
|
379
|
+
func midAdDidLoad(_ ad: NovvyMidAd) { emit("loaded", nil, nil) }
|
|
380
|
+
func midAd(_ ad: NovvyMidAd, didFailToLoadWithError error: NovvyError) { emit("failedToLoad", error.localizedDescription, nil) }
|
|
381
|
+
func midAdDidShow(_ ad: NovvyMidAd) { emit("showed", nil, nil) }
|
|
382
|
+
func midAdDidClose(_ ad: NovvyMidAd) { emit("dismissed", nil, nil) }
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
private final class EndDelegate: NSObject, NovvyEndAdDelegate {
|
|
386
|
+
let emit: (String, String?, Int?) -> Void
|
|
387
|
+
init(emit: @escaping (String, String?, Int?) -> Void) { self.emit = emit }
|
|
388
|
+
func endAdDidLoad(_ ad: NovvyEndAd) { emit("loaded", nil, nil) }
|
|
389
|
+
func endAd(_ ad: NovvyEndAd, didFailToLoadWithError error: NovvyError) { emit("failedToLoad", error.localizedDescription, nil) }
|
|
390
|
+
func endAdDidShow(_ ad: NovvyEndAd) { emit("showed", nil, nil) }
|
|
391
|
+
func endAdDidClose(_ ad: NovvyEndAd) { emit("dismissed", nil, nil) }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
private final class ScrollDelegate: NSObject, NovvyScrollAdDelegate {
|
|
395
|
+
let emit: (String, String?, Int?) -> Void
|
|
396
|
+
init(emit: @escaping (String, String?, Int?) -> Void) { self.emit = emit }
|
|
397
|
+
func scrollAdDidLoad(_ ad: NovvyScrollAd) { emit("loaded", nil, nil) }
|
|
398
|
+
func scrollAd(_ ad: NovvyScrollAd, didFailToLoadWithError error: NovvyError) { emit("failedToLoad", error.localizedDescription, nil) }
|
|
399
|
+
func scrollAdDidShow(_ ad: NovvyScrollAd) { emit("showed", nil, nil) }
|
|
400
|
+
func scrollAdDidClose(_ ad: NovvyScrollAd) { emit("hidden", nil, nil) }
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
private final class PauseDelegate: NSObject, NovvyPauseAdDelegate {
|
|
404
|
+
let emit: (String, String?, Int?) -> Void
|
|
405
|
+
init(emit: @escaping (String, String?, Int?) -> Void) { self.emit = emit }
|
|
406
|
+
func pauseAd(_ ad: NovvyPauseAd, didFailToLoadWithError error: NovvyError) { emit("failedToLoad", error.localizedDescription, nil) }
|
|
407
|
+
func pauseAdDidShow(_ ad: NovvyPauseAd) { emit("showed", nil, nil) }
|
|
408
|
+
func pauseAdDidFinish(_ ad: NovvyPauseAd) { emit("hidden", nil, nil) }
|
|
409
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#import "NovvyAdsReactNative-Swift.h"
|
|
2
|
+
|
|
3
|
+
#import <React/RCTViewComponentView.h>
|
|
4
|
+
#import <react/renderer/components/NovvyAdsSpec/ComponentDescriptors.h>
|
|
5
|
+
#import <react/renderer/components/NovvyAdsSpec/EventEmitters.h>
|
|
6
|
+
#import <react/renderer/components/NovvyAdsSpec/Props.h>
|
|
7
|
+
#import <react/renderer/components/NovvyAdsSpec/RCTComponentViewHelpers.h>
|
|
8
|
+
|
|
9
|
+
using namespace facebook::react;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Fabric component for the inline realtime pause-card ad container.
|
|
13
|
+
*
|
|
14
|
+
* Registers a transparent container with `NovvyAdsImpl` keyed by `adObjectId`,
|
|
15
|
+
* then fires `onViewReady` so JS issues `attachPauseAd` (no load step). Mirrors
|
|
16
|
+
* the Flutter plugin's `NovvyPausePlatformView`.
|
|
17
|
+
*/
|
|
18
|
+
@interface NovvyPauseAdView : RCTViewComponentView
|
|
19
|
+
@end
|
|
20
|
+
|
|
21
|
+
@implementation NovvyPauseAdView {
|
|
22
|
+
UIView *_container;
|
|
23
|
+
NSString *_adObjectId;
|
|
24
|
+
// Fabric calls `updateProps` BEFORE `updateEventEmitter`, so the emitter is
|
|
25
|
+
// nil at the moment we learn the adObjectId. Buffer the ready-emit and fire
|
|
26
|
+
// it from `finalizeUpdates:`, which runs after both are set.
|
|
27
|
+
BOOL _viewReadyPending;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
31
|
+
return concreteComponentDescriptorProvider<NovvyPauseAdViewComponentDescriptor>();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
35
|
+
if (self = [super initWithFrame:frame]) {
|
|
36
|
+
static const auto defaultProps = std::make_shared<const NovvyPauseAdViewProps>();
|
|
37
|
+
_props = defaultProps;
|
|
38
|
+
_container = [[UIView alloc] initWithFrame:self.bounds];
|
|
39
|
+
_container.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
40
|
+
_container.backgroundColor = UIColor.clearColor;
|
|
41
|
+
self.contentView = _container;
|
|
42
|
+
}
|
|
43
|
+
return self;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps {
|
|
47
|
+
const auto &newProps = *std::static_pointer_cast<const NovvyPauseAdViewProps>(props);
|
|
48
|
+
NSString *adObjectId = [NSString stringWithUTF8String:newProps.adObjectId.c_str()];
|
|
49
|
+
if (adObjectId.length > 0 && ![adObjectId isEqualToString:_adObjectId]) {
|
|
50
|
+
_adObjectId = adObjectId;
|
|
51
|
+
[NovvyAdsImpl.shared registerPauseContainerWithAdObjectId:adObjectId container:_container];
|
|
52
|
+
_viewReadyPending = YES;
|
|
53
|
+
}
|
|
54
|
+
[super updateProps:props oldProps:oldProps];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
- (void)finalizeUpdates:(RNComponentViewUpdateMask)updateMask {
|
|
58
|
+
[super finalizeUpdates:updateMask];
|
|
59
|
+
if (_viewReadyPending && _eventEmitter && _adObjectId.length > 0) {
|
|
60
|
+
_viewReadyPending = NO;
|
|
61
|
+
auto emitter = std::static_pointer_cast<const NovvyPauseAdViewEventEmitter>(_eventEmitter);
|
|
62
|
+
emitter->onViewReady({.adObjectId = std::string(_adObjectId.UTF8String)});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
- (void)prepareForRecycle {
|
|
67
|
+
if (_adObjectId != nil) {
|
|
68
|
+
[NovvyAdsImpl.shared onPauseViewDisposedWithAdObjectId:_adObjectId];
|
|
69
|
+
_adObjectId = nil;
|
|
70
|
+
}
|
|
71
|
+
_viewReadyPending = NO;
|
|
72
|
+
[super prepareForRecycle];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@end
|
|
76
|
+
|
|
77
|
+
Class<RCTComponentViewProtocol> NovvyPauseAdViewCls(void) {
|
|
78
|
+
return NovvyPauseAdView.class;
|
|
79
|
+
}
|