FIRIAMDefaultDisplayImpl.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  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 <Foundation/Foundation.h>
  17. #import <FirebaseCore/FIRAppInternal.h>
  18. #import <FirebaseInAppMessaging/FIRInAppMessaging.h>
  19. #import <FirebaseInAppMessaging/FIRInAppMessagingRendering.h>
  20. #import "FIDBannerViewController.h"
  21. #import "FIDCardViewController.h"
  22. #import "FIDImageOnlyViewController.h"
  23. #import "FIDModalViewController.h"
  24. #import "FIDRenderingWindowHelper.h"
  25. #import "FIDTimeFetcher.h"
  26. #import "FIRCore+InAppMessagingDisplay.h"
  27. #import "FIRIAMDefaultDisplayImpl.h"
  28. @implementation FIRIAMDefaultDisplayImpl
  29. + (void)load {
  30. [[NSNotificationCenter defaultCenter] addObserver:self
  31. selector:@selector(didReceiveConfigureSDKNotification:)
  32. name:kFIRAppReadyToConfigureSDKNotification
  33. object:nil];
  34. }
  35. + (void)didReceiveConfigureSDKNotification:(NSNotification *)notification {
  36. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100010",
  37. @"Got notification for kFIRAppReadyToConfigureSDKNotification. Setting display "
  38. "component on headless SDK.");
  39. FIRIAMDefaultDisplayImpl *display = [[FIRIAMDefaultDisplayImpl alloc] init];
  40. [FIRInAppMessaging inAppMessaging].messageDisplayComponent = display;
  41. }
  42. + (NSBundle *)getViewResourceBundle {
  43. static NSBundle *resourceBundle;
  44. static dispatch_once_t onceToken;
  45. dispatch_once(&onceToken, ^{
  46. // TODO. This logic of finding the resource bundle may need to change once it's open
  47. // sourced
  48. NSBundle *containingBundle = [NSBundle mainBundle];
  49. // This is assuming the display resource bundle is contained in the main bundle
  50. NSURL *bundleURL = [containingBundle URLForResource:@"InAppMessagingDisplayResources"
  51. withExtension:@"bundle"];
  52. resourceBundle = [NSBundle bundleWithURL:bundleURL];
  53. if (resourceBundle == nil) {
  54. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100007",
  55. @"FIAM Display Resource bundle "
  56. "is missing: not contained within bundle %@",
  57. containingBundle);
  58. }
  59. });
  60. return resourceBundle;
  61. }
  62. + (void)displayCardViewWithMessageDefinition:(FIRInAppMessagingCardDisplay *)cardMessage
  63. displayDelegate:(id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  64. NSBundle *resourceBundle = [self getViewResourceBundle];
  65. if (resourceBundle == nil) {
  66. NSError *error =
  67. [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  68. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  69. userInfo:@{NSLocalizedDescriptionKey : @"Resource bundle is missing."}];
  70. [displayDelegate displayErrorForMessage:cardMessage error:error];
  71. return;
  72. }
  73. dispatch_async(dispatch_get_main_queue(), ^{
  74. FIDTimerWithNSDate *timeFetcher = [[FIDTimerWithNSDate alloc] init];
  75. FIDCardViewController *cardVC =
  76. [FIDCardViewController instantiateViewControllerWithResourceBundle:resourceBundle
  77. displayMessage:cardMessage
  78. displayDelegate:displayDelegate
  79. timeFetcher:timeFetcher];
  80. if (cardVC == nil) {
  81. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100011",
  82. @"View controller can not be created.");
  83. NSError *error = [NSError
  84. errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  85. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  86. userInfo:@{NSLocalizedDescriptionKey : @"View controller could not be created"}];
  87. [displayDelegate displayErrorForMessage:cardMessage error:error];
  88. return;
  89. }
  90. UIWindow *displayUIWindow = [FIDRenderingWindowHelper UIWindowForModalView];
  91. displayUIWindow.rootViewController = cardVC;
  92. [displayUIWindow setHidden:NO];
  93. });
  94. }
  95. + (void)displayModalViewWithMessageDefinition:(FIRInAppMessagingModalDisplay *)modalMessage
  96. displayDelegate:
  97. (id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  98. NSBundle *resourceBundle = [self getViewResourceBundle];
  99. if (resourceBundle == nil) {
  100. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  101. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  102. userInfo:@{@"message" : @"resource bundle is missing"}];
  103. [displayDelegate displayErrorForMessage:modalMessage error:error];
  104. return;
  105. }
  106. dispatch_async(dispatch_get_main_queue(), ^{
  107. FIDTimerWithNSDate *timeFetcher = [[FIDTimerWithNSDate alloc] init];
  108. FIDModalViewController *modalVC =
  109. [FIDModalViewController instantiateViewControllerWithResourceBundle:resourceBundle
  110. displayMessage:modalMessage
  111. displayDelegate:displayDelegate
  112. timeFetcher:timeFetcher];
  113. if (modalVC == nil) {
  114. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100004",
  115. @"View controller can not be created.");
  116. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  117. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  118. userInfo:@{}];
  119. [displayDelegate displayErrorForMessage:modalMessage error:error];
  120. return;
  121. }
  122. UIWindow *displayUIWindow = [FIDRenderingWindowHelper UIWindowForModalView];
  123. displayUIWindow.rootViewController = modalVC;
  124. [displayUIWindow setHidden:NO];
  125. });
  126. }
  127. + (void)displayBannerViewWithMessageDefinition:(FIRInAppMessagingBannerDisplay *)bannerMessage
  128. displayDelegate:
  129. (id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  130. NSBundle *resourceBundle = [self getViewResourceBundle];
  131. if (resourceBundle == nil) {
  132. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  133. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  134. userInfo:@{}];
  135. [displayDelegate displayErrorForMessage:bannerMessage error:error];
  136. return;
  137. }
  138. dispatch_async(dispatch_get_main_queue(), ^{
  139. FIDTimerWithNSDate *timeFetcher = [[FIDTimerWithNSDate alloc] init];
  140. FIDBannerViewController *bannerVC =
  141. [FIDBannerViewController instantiateViewControllerWithResourceBundle:resourceBundle
  142. displayMessage:bannerMessage
  143. displayDelegate:displayDelegate
  144. timeFetcher:timeFetcher];
  145. if (bannerVC == nil) {
  146. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100008",
  147. @"Banner view controller can not be created.");
  148. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  149. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  150. userInfo:@{}];
  151. [displayDelegate displayErrorForMessage:bannerMessage error:error];
  152. return;
  153. }
  154. UIWindow *displayUIWindow = [FIDRenderingWindowHelper UIWindowForBannerView];
  155. displayUIWindow.rootViewController = bannerVC;
  156. [displayUIWindow setHidden:NO];
  157. });
  158. }
  159. + (void)displayImageOnlyViewWithMessageDefinition:
  160. (FIRInAppMessagingImageOnlyDisplay *)imageOnlyMessage
  161. displayDelegate:
  162. (id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  163. NSBundle *resourceBundle = [self getViewResourceBundle];
  164. if (resourceBundle == nil) {
  165. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  166. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  167. userInfo:@{}];
  168. [displayDelegate displayErrorForMessage:imageOnlyMessage error:error];
  169. return;
  170. }
  171. dispatch_async(dispatch_get_main_queue(), ^{
  172. FIDTimerWithNSDate *timeFetcher = [[FIDTimerWithNSDate alloc] init];
  173. FIDImageOnlyViewController *imageOnlyVC =
  174. [FIDImageOnlyViewController instantiateViewControllerWithResourceBundle:resourceBundle
  175. displayMessage:imageOnlyMessage
  176. displayDelegate:displayDelegate
  177. timeFetcher:timeFetcher];
  178. if (imageOnlyVC == nil) {
  179. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100006",
  180. @"Image only view controller can not be created.");
  181. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  182. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  183. userInfo:@{}];
  184. [displayDelegate displayErrorForMessage:imageOnlyMessage error:error];
  185. return;
  186. }
  187. UIWindow *displayUIWindow = [FIDRenderingWindowHelper UIWindowForImageOnlyView];
  188. displayUIWindow.rootViewController = imageOnlyVC;
  189. [displayUIWindow setHidden:NO];
  190. });
  191. }
  192. #pragma mark - protocol FIRInAppMessagingDisplay
  193. - (void)displayMessage:(FIRInAppMessagingDisplayMessage *)messageForDisplay
  194. displayDelegate:(id<FIRInAppMessagingDisplayDelegate>)displayDelegate {
  195. if ([messageForDisplay isKindOfClass:[FIRInAppMessagingModalDisplay class]]) {
  196. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100000", @"Display a modal message.");
  197. [self.class displayModalViewWithMessageDefinition:(FIRInAppMessagingModalDisplay *)
  198. messageForDisplay
  199. displayDelegate:displayDelegate];
  200. } else if ([messageForDisplay isKindOfClass:[FIRInAppMessagingBannerDisplay class]]) {
  201. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100001", @"Display a banner message.");
  202. [self.class displayBannerViewWithMessageDefinition:(FIRInAppMessagingBannerDisplay *)
  203. messageForDisplay
  204. displayDelegate:displayDelegate];
  205. } else if ([messageForDisplay isKindOfClass:[FIRInAppMessagingImageOnlyDisplay class]]) {
  206. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100002", @"Display an image only message.");
  207. [self.class displayImageOnlyViewWithMessageDefinition:(FIRInAppMessagingImageOnlyDisplay *)
  208. messageForDisplay
  209. displayDelegate:displayDelegate];
  210. } else if ([messageForDisplay isKindOfClass:[FIRInAppMessagingCardDisplay class]]) {
  211. FIRLogDebug(kFIRLoggerInAppMessagingDisplay, @"I-FID100009", @"Display a card message.");
  212. [self.class displayCardViewWithMessageDefinition:(FIRInAppMessagingCardDisplay *)
  213. messageForDisplay
  214. displayDelegate:displayDelegate];
  215. } else {
  216. FIRLogWarning(kFIRLoggerInAppMessagingDisplay, @"I-FID100003",
  217. @"Unknown message type %@ "
  218. "Don't know how to handle it.",
  219. messageForDisplay.class);
  220. NSError *error = [NSError errorWithDomain:kFirebaseInAppMessagingDisplayErrorDomain
  221. code:FIAMDisplayRenderErrorTypeUnspecifiedError
  222. userInfo:@{}];
  223. [displayDelegate displayErrorForMessage:messageForDisplay error:error];
  224. }
  225. }
  226. @end