UNPKG

7.49 kBPlain TextView Raw
1#import <EXAdsFacebook/EXNativeAdManager.h>
2#import <EXAdsFacebook/EXNativeAdView.h>
3
4#import <FBAudienceNetwork/FBAudienceNetwork.h>
5#import <UMCore/UMUtilities.h>
6#import <UMCore/UMUIManager.h>
7#import <UMCore/UMEventEmitterService.h>
8
9@class EXAdManagerDelegate;
10
11@interface EXNativeAdManager ()
12
13@property (nonatomic, weak) UMModuleRegistry *moduleRegistry;
14@property (nonatomic, strong) NSMutableDictionary<NSString*, FBNativeAdsManager*> *adsManagers;
15@property (nonatomic, strong) NSMutableDictionary<NSString*, EXAdManagerDelegate*> *adsManagersDelegates;
16
17- (void)nativeAdsLoaded;
18- (void)nativeAdForPlacementId:(NSString *)placementId failedToLoadWithError:(NSError *)error;
19
20@end
21
22// A light delegate object responsible for delivering information
23// about errors to EXNativeAdManager, but with a specific placement ID
24// for which the error has happened. FBNativeAdsManagerDelegate protocol
25// does not provide such information, we only get the error. Proxying
26// the event through this middleman lets us assign specific placement ID
27// to each error.
28
29@interface EXAdManagerDelegate : NSObject <FBNativeAdsManagerDelegate>
30
31@property (nonatomic, weak) EXNativeAdManager *manager;
32@property (nonatomic, strong) NSString *placementId;
33
34@end
35
36@implementation EXAdManagerDelegate
37
38- (instancetype)initWithPlacementId:(NSString *)placementId andManager:(EXNativeAdManager *)manager
39{
40 if (self = [super init]) {
41 _manager = manager;
42 _placementId = placementId;
43 }
44 return self;
45}
46
47- (void)nativeAdsLoaded
48{
49 [_manager nativeAdsLoaded];
50}
51
52- (void)nativeAdsFailedToLoadWithError:(NSError *)errors
53{
54 [_manager nativeAdForPlacementId:_placementId failedToLoadWithError:errors];
55}
56
57@end
58
59@implementation EXNativeAdManager
60
61UM_EXPORT_MODULE(CTKNativeAdManager)
62
63- (instancetype)init
64{
65 self = [super init];
66 if (self) {
67 _adsManagers = [NSMutableDictionary new];
68 _adsManagersDelegates = [NSMutableDictionary new];
69 }
70 return self;
71}
72
73- (NSString *)viewName
74{
75 return @"CTKNativeAd";
76}
77
78- (void)setModuleRegistry:(UMModuleRegistry *)moduleRegistry
79{
80 _moduleRegistry = moduleRegistry;
81}
82
83- (NSArray<NSString *> *)supportedEvents
84{
85 return @[@"CTKNativeAdsManagersChanged", @"CTKNativeAdManagerErrored", @"onAdLoaded"];
86}
87
88UM_EXPORT_METHOD_AS(registerViewsForInteraction,
89 registerViewsForInteraction:(NSNumber *)nativeAdViewTag
90 mediaViewTag:(NSNumber *)mediaViewTag
91 adIconViewTag:(NSNumber *)adIconViewTag
92 clickableViewsTags:(NSArray *)tags
93 resolve:(UMPromiseResolveBlock)resolve
94 reject:(UMPromiseRejectBlock)reject)
95{
96 id<UMUIManager> uiManager = [_moduleRegistry getModuleImplementingProtocol:@protocol(UMUIManager)];
97 [uiManager executeUIBlock:^(NSDictionary<id,UIView *> * viewRegistry) {
98 UIView *mediaView = nil;
99 UIView *adIconView = nil;
100 UIView *nativeAdView = nil;
101 NSMutableArray<UIView *> *clickableViews = [NSMutableArray new];
102
103 mediaView = viewRegistry[mediaViewTag];
104 adIconView = viewRegistry[adIconViewTag];
105 nativeAdView = viewRegistry[nativeAdViewTag];
106 for (id tag in tags) {
107 if (viewRegistry[tag]) {
108 [clickableViews addObject:viewRegistry[tag]];
109 }
110 }
111
112 if (!clickableViews) {
113 reject(@"E_INVALID_VIEW_TAG", @"Could not find view for one of the clickable views tags", nil);
114 return;
115 }
116
117 if (mediaView == nil) {
118 reject(@"E_NO_VIEW_FOR_TAG", @"Could not find mediaView", nil);
119 return;
120 }
121
122 if (nativeAdView == nil) {
123 reject(@"E_NO_NATIVEAD_VIEW", @"Could not find nativeAdView", nil);
124 return;
125 }
126
127 if (![mediaView isKindOfClass:[FBMediaView class]]) {
128 reject(@"E_INVALID_VIEW_CLASS", @"View returned for passed media view tag is not an instance of FBMediaView", nil);
129 return;
130 }
131
132 if (![nativeAdView isKindOfClass:[EXNativeAdView class]]) {
133 reject(@"E_INVALID_VIEW_CLASS", @"View returned for passed native ad view tag is not an instance of EXNativeAdView", nil);
134 return;
135 }
136
137 if (adIconView) {
138 if (![adIconView isKindOfClass:[FBMediaView class]]) {
139 reject(@"E_INVALID_VIEW_CLASS", @"View returned for passed ad icon view tag is not an instance of FBMediaView", nil);
140 return;
141 }
142 }
143
144 [clickableViews addObject:mediaView];
145 [clickableViews addObject:adIconView];
146
147 [(EXNativeAdView *)nativeAdView registerViewsForInteraction:(FBMediaView *)mediaView adIcon:(FBAdIconView *)adIconView clickableViews:clickableViews];
148 resolve(@[]);
149 }];
150}
151
152UM_EXPORT_METHOD_AS(init,
153 init:(NSString *)placementId
154 withAdsToRequest:(NSNumber *)adsToRequest
155 resolve:(UMPromiseResolveBlock)resolve
156 reject:(UMPromiseRejectBlock)reject)
157{
158 FBNativeAdsManager *adsManager = [[FBNativeAdsManager alloc] initWithPlacementID:placementId
159 forNumAdsRequested:[adsToRequest intValue]];
160
161 EXAdManagerDelegate *delegate = [[EXAdManagerDelegate alloc] initWithPlacementId:placementId andManager:self];
162 _adsManagersDelegates[placementId] = delegate;
163 [adsManager setDelegate:delegate];
164
165 [UMUtilities performSynchronouslyOnMainThread:^{
166 [adsManager loadAds];
167 }];
168
169 [_adsManagers setValue:adsManager forKey:placementId];
170 resolve(nil);
171}
172
173UM_EXPORT_METHOD_AS(setMediaCachePolicy,
174 setMediaCachePolicy:(NSString *)placementId
175 cachePolicy:(NSString *)cachePolicy
176 resolve:(UMPromiseResolveBlock)resolve
177 reject:(UMPromiseRejectBlock)reject)
178{
179 FBNativeAdsCachePolicy policy = [@{
180 @"none": @(FBNativeAdsCachePolicyNone),
181 @"all": @(FBNativeAdsCachePolicyAll),
182 }[cachePolicy] integerValue] ?: FBNativeAdsCachePolicyNone;
183 [_adsManagers[placementId] setMediaCachePolicy:policy];
184 resolve(nil);
185}
186
187UM_EXPORT_METHOD_AS(disableAutoRefresh,
188 disableAutoRefresh:(NSString*)placementId
189 resolve:(UMPromiseResolveBlock)resolve
190 reject:(UMPromiseRejectBlock)reject)
191{
192 [_adsManagers[placementId] disableAutoRefresh];
193 resolve(nil);
194}
195
196- (void)nativeAdsLoaded
197{
198 NSMutableDictionary<NSString*, NSNumber*> *adsManagersState = [NSMutableDictionary new];
199
200 [_adsManagers enumerateKeysAndObjectsUsingBlock:^(NSString* key, FBNativeAdsManager* adManager, __unused BOOL* stop) {
201 [adsManagersState setValue:@([adManager isValid]) forKey:key];
202 }];
203
204 [[_moduleRegistry getModuleImplementingProtocol:@protocol(UMEventEmitterService)] sendEventWithName:@"CTKNativeAdsManagersChanged" body:adsManagersState];
205}
206
207- (void)nativeAdForPlacementId:(NSString *)placementId failedToLoadWithError:(NSError *)error
208{
209 [[_moduleRegistry getModuleImplementingProtocol:@protocol(UMEventEmitterService)] sendEventWithName:@"CTKNativeAdManagerErrored" body:@{
210 @"placementId": placementId,
211 @"error": @{
212 @"message": error.localizedDescription ?: error.description,
213 @"code": @(error.code)
214 },
215 }];
216}
217
218- (UIView *)view
219{
220 return [[EXNativeAdView alloc] initWithModuleRegistry:_moduleRegistry];
221}
222
223UM_VIEW_PROPERTY(adsManager, NSString *, EXNativeAdView)
224{
225 [view setNativeAd:[_adsManagers[value] nextNativeAd]];
226}
227
228- (void)startObserving {
229}
230
231- (void)stopObserving {
232}
233
234@end