FIRIAMDefaultDisplayImpl.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /*
  2. * Copyright 2018 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import <TargetConditionals.h>
  17. #if TARGET_OS_IOS
  18. #import <Foundation/Foundation.h>
  19. #import "FirebaseCore/Sources/Private/FirebaseCoreInternal.h"
  20. #import "FirebaseInAppMessaging/Sources/DefaultUI/Banner/FIRIAMBannerViewController.h"
  21. #import "FirebaseInAppMessaging/Sources/DefaultUI/Card/FIRIAMCardViewController.h"
  22. #import "FirebaseInAppMessaging/Sources/DefaultUI/FIRCore+InAppMessagingDisplay.h"
  23. #import "FirebaseInAppMessaging/Sources/DefaultUI/FIRIAMDefaultDisplayImpl.h"
  24. #import "FirebaseInAppMessaging/Sources/DefaultUI/FIRIAMRenderingWindowHelper.h"
  25. #import "FirebaseInAppMessaging/Sources/DefaultUI/ImageOnly/FIRIAMImageOnlyViewController.h"
  26. #import "FirebaseInAppMessaging/Sources/DefaultUI/Modal/FIRIAMModalViewController.h"
  27. #import "FirebaseInAppMessaging/Sources/Private/Util/FIRIAMTimeFetcher.h"
  28. #import "FirebaseInAppMessaging/Sources/Public/FirebaseInAppMessaging/FIRInAppMessaging.h"
  29. #import "FirebaseInAppMessaging/Sources/Public/FirebaseInAppMessaging/FIRInAppMessagingRendering.h"
  30. @implementation FIRIAMDefaultDisplayImpl
  31. + (void)load {
  32. [[NSNotificationCenter defaultCenter] addObserver:self
  33. selector:@selector(didReceiveConfigureSDKNotification:)
  34. name:kFIRAppReadyToConfigureSDKNotification
  35. object:nil];
  36. }
  37. + (void)didReceiveConfigureSDKNotification:(NSNotification *)notification {
  38. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100010",
  39. @"Got notification for kFIRAppReadyToConfigureSDKNotification. Setting display "
  40. "component on headless SDK.");
  41. FIRIAMDefaultDisplayImpl *display = [[FIRIAMDefaultDisplayImpl alloc] init];
  42. [FIRInAppMessaging inAppMessaging].messageDisplayComponent = display;
  43. }
  44. + (NSBundle *)getViewResourceBundle {
  45. static NSBundle *resourceBundle;
  46. static dispatch_once_t onceToken;
  47. Class myClass = [self class];
  48. dispatch_once(&onceToken, ^{
  49. NSBundle *containingBundle;
  50. NSURL *bundleURL;
  51. // The containing bundle is different whether FIAM is statically or dynamically linked.
  52. for (containingBundle in @[ [NSBundle mainBundle], [NSBundle bundleForClass:myClass] ]) {
  53. bundleURL = [containingBundle URLForResource:@"InAppMessagingDisplayResources"
  54. withExtension:@"bundle"];
  55. if (bundleURL != nil) break;
  56. }
  57. if (bundleURL == nil) {
  58. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100007",
  59. @"FIAM Display Resource bundle "
  60. "is missing: not contained within bundle %@",
  61. containingBundle);
  62. return;
  63. }
  64. resourceBundle = [NSBundle bundleWithURL:bundleURL];
  65. if (resourceBundle == nil) {
  66. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100007",
  67. @"FIAM Display Resource bundle "
  68. "is missing: not contained within bundle %@",
  69. containingBundle);
  70. }
  71. });
  72. return resourceBundle;
  73. }
  74. + (void)displayCardViewWithMessageDefinition:(FIRInAppMessagingCardDisplay *)cardMessage
  75. displayDelegate:(id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  76. dispatch_async(dispatch_get_main_queue(), ^{
  77. NSBundle *resourceBundle = [self getViewResourceBundle];
  78. if (resourceBundle == nil) {
  79. NSError *error =
  80. [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  81. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  82. userInfo:@{NSLocalizedDescriptionKey : @"Resource bundle is missing."}];
  83. [displayDelegate displayErrorForMessage:cardMessage error:error];
  84. return;
  85. }
  86. FIRIAMTimerWithNSDate *timeFetcher = [[FIRIAMTimerWithNSDate alloc] init];
  87. FIRIAMCardViewController *cardVC =
  88. [FIRIAMCardViewController instantiateViewControllerWithResourceBundle:resourceBundle
  89. displayMessage:cardMessage
  90. displayDelegate:displayDelegate
  91. timeFetcher:timeFetcher];
  92. if (cardVC == nil) {
  93. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100011",
  94. @"View controller can not be created.");
  95. NSError *error = [NSError
  96. errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  97. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  98. userInfo:@{NSLocalizedDescriptionKey : @"View controller could not be created"}];
  99. [displayDelegate displayErrorForMessage:cardMessage error:error];
  100. return;
  101. }
  102. UIWindow *displayUIWindow = [FIRIAMRenderingWindowHelper UIWindowForModalView];
  103. displayUIWindow.rootViewController = cardVC;
  104. [displayUIWindow setHidden:NO];
  105. });
  106. }
  107. + (void)displayModalViewWithMessageDefinition:(FIRInAppMessagingModalDisplay *)modalMessage
  108. displayDelegate:
  109. (id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  110. dispatch_async(dispatch_get_main_queue(), ^{
  111. NSBundle *resourceBundle = [self getViewResourceBundle];
  112. if (resourceBundle == nil) {
  113. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  114. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  115. userInfo:@{@"message" : @"resource bundle is missing"}];
  116. [displayDelegate displayErrorForMessage:modalMessage error:error];
  117. return;
  118. }
  119. FIRIAMTimerWithNSDate *timeFetcher = [[FIRIAMTimerWithNSDate alloc] init];
  120. FIRIAMModalViewController *modalVC =
  121. [FIRIAMModalViewController instantiateViewControllerWithResourceBundle:resourceBundle
  122. displayMessage:modalMessage
  123. displayDelegate:displayDelegate
  124. timeFetcher:timeFetcher];
  125. if (modalVC == nil) {
  126. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100004",
  127. @"View controller can not be created.");
  128. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  129. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  130. userInfo:@{}];
  131. [displayDelegate displayErrorForMessage:modalMessage error:error];
  132. return;
  133. }
  134. UIWindow *displayUIWindow = [FIRIAMRenderingWindowHelper UIWindowForModalView];
  135. displayUIWindow.rootViewController = modalVC;
  136. [displayUIWindow setHidden:NO];
  137. });
  138. }
  139. + (void)displayBannerViewWithMessageDefinition:(FIRInAppMessagingBannerDisplay *)bannerMessage
  140. displayDelegate:
  141. (id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  142. dispatch_async(dispatch_get_main_queue(), ^{
  143. NSBundle *resourceBundle = [self getViewResourceBundle];
  144. if (resourceBundle == nil) {
  145. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  146. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  147. userInfo:@{}];
  148. [displayDelegate displayErrorForMessage:bannerMessage error:error];
  149. return;
  150. }
  151. FIRIAMTimerWithNSDate *timeFetcher = [[FIRIAMTimerWithNSDate alloc] init];
  152. FIRIAMBannerViewController *bannerVC =
  153. [FIRIAMBannerViewController instantiateViewControllerWithResourceBundle:resourceBundle
  154. displayMessage:bannerMessage
  155. displayDelegate:displayDelegate
  156. timeFetcher:timeFetcher];
  157. if (bannerVC == nil) {
  158. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100008",
  159. @"Banner view controller can not be created.");
  160. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  161. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  162. userInfo:@{}];
  163. [displayDelegate displayErrorForMessage:bannerMessage error:error];
  164. return;
  165. }
  166. UIWindow *displayUIWindow = [FIRIAMRenderingWindowHelper UIWindowForBannerView];
  167. displayUIWindow.rootViewController = bannerVC;
  168. [displayUIWindow setHidden:NO];
  169. });
  170. }
  171. + (void)displayImageOnlyViewWithMessageDefinition:
  172. (FIRInAppMessagingImageOnlyDisplay *)imageOnlyMessage
  173. displayDelegate:
  174. (id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  175. dispatch_async(dispatch_get_main_queue(), ^{
  176. NSBundle *resourceBundle = [self getViewResourceBundle];
  177. if (resourceBundle == nil) {
  178. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  179. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  180. userInfo:@{}];
  181. [displayDelegate displayErrorForMessage:imageOnlyMessage error:error];
  182. return;
  183. }
  184. FIRIAMTimerWithNSDate *timeFetcher = [[FIRIAMTimerWithNSDate alloc] init];
  185. FIRIAMImageOnlyViewController *imageOnlyVC =
  186. [FIRIAMImageOnlyViewController instantiateViewControllerWithResourceBundle:resourceBundle
  187. displayMessage:imageOnlyMessage
  188. displayDelegate:displayDelegate
  189. timeFetcher:timeFetcher];
  190. if (imageOnlyVC == nil) {
  191. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100006",
  192. @"Image only view controller can not be created.");
  193. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  194. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  195. userInfo:@{}];
  196. [displayDelegate displayErrorForMessage:imageOnlyMessage error:error];
  197. return;
  198. }
  199. UIWindow *displayUIWindow = [FIRIAMRenderingWindowHelper UIWindowForImageOnlyView];
  200. displayUIWindow.rootViewController = imageOnlyVC;
  201. [displayUIWindow setHidden:NO];
  202. });
  203. }
  204. #pragma mark - protocol FIRInAppMessagingDisplay
  205. - (void)displayMessage:(FIRInAppMessagingDisplayMessage *)messageForDisplay
  206. displayDelegate:(id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  207. if ([messageForDisplay isKindOfClass:[FIRInAppMessagingModalDisplay class]]) {
  208. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100000", @"Display a modal message.");
  209. [self.class displayModalViewWithMessageDefinition:(FIRInAppMessagingModalDisplay *)
  210. messageForDisplay
  211. displayDelegate:displayDelegate];
  212. } else if ([messageForDisplay isKindOfClass:[FIRInAppMessagingBannerDisplay class]]) {
  213. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100001", @"Display a banner message.");
  214. [self.class displayBannerViewWithMessageDefinition:(FIRInAppMessagingBannerDisplay *)
  215. messageForDisplay
  216. displayDelegate:displayDelegate];
  217. } else if ([messageForDisplay isKindOfClass:[FIRInAppMessagingImageOnlyDisplay class]]) {
  218. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100002", @"Display an image only message.");
  219. [self.class displayImageOnlyViewWithMessageDefinition:(FIRInAppMessagingImageOnlyDisplay *)
  220. messageForDisplay
  221. displayDelegate:displayDelegate];
  222. } else if ([messageForDisplay isKindOfClass:[FIRInAppMessagingCardDisplay class]]) {
  223. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100009", @"Display a card message.");
  224. [self.class displayCardViewWithMessageDefinition:(FIRInAppMessagingCardDisplay *)
  225. messageForDisplay
  226. displayDelegate:displayDelegate];
  227. } else {
  228. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100003",
  229. @"Unknown message type %@ "
  230. "Don't know how to handle it.",
  231. messageForDisplay.class);
  232. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  233. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  234. userInfo:@{}];
  235. [displayDelegate displayErrorForMessage:messageForDisplay error:error];
  236. }
  237. }
  238. @end
  239. #endif // TARGET_OS_IOS