Skip to content

Commit c8899e2

Browse files
authored
Firebase In-app messaging callbacks (#2354)
* FIRInAppMessagingDisplayMessage and FIRInAppMessagingDisplayDelegate refactor + downstream changes * More downstream changes from FIRInAppMessagingDisplayDelegate, calling through to app-side delegate from default display executor * Add delegate property on FIRInAppMessaging * Display SDK changes to pass through in app message with callbacks * Headless SDK unit test refactoring * Display test app downstream changes * Pull in headless SDK in display app, no need to have this come in as a framework anymore * Run scripts/style.sh * Remove WIP test * Refactor FIRIAMDIsplayExecutor to take an InAppMessaging object for testing * Depend on FirebaseAnalyticsInterop in UI test app * File imports for FIRInAppMessaging files * Remove FirebaseInAppMessaging imports
1 parent 26f021a commit c8899e2

20 files changed

+547
-187
lines changed

Firebase/InAppMessaging/Flows/FIRIAMDisplayExecutor.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#import "FIRIAMClearcutLogger.h"
2323
#import "FIRIAMMessageClientCache.h"
2424
#import "FIRIAMTimeFetcher.h"
25+
#import "FIRInAppMessaging.h"
2526
#import "FIRInAppMessagingRendering.h"
2627

2728
NS_ASSUME_NONNULL_BEGIN
@@ -39,13 +40,14 @@ NS_ASSUME_NONNULL_BEGIN
3940
// 2 For non-contextual messages, the display interval in display setting is met.
4041
@interface FIRIAMDisplayExecutor : NSObject
4142

42-
- (instancetype)initWithSetting:(FIRIAMDisplaySetting *)setting
43-
messageCache:(FIRIAMMessageClientCache *)cache
44-
timeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher
45-
bookKeeper:(id<FIRIAMBookKeeper>)displayBookKeeper
46-
actionURLFollower:(FIRIAMActionURLFollower *)actionURLFollower
47-
activityLogger:(FIRIAMActivityLogger *)activityLogger
48-
analyticsEventLogger:(id<FIRIAMAnalyticsEventLogger>)analyticsEventLogger;
43+
- (instancetype)initWithInAppMessaging:(FIRInAppMessaging *)inAppMessaging
44+
setting:(FIRIAMDisplaySetting *)setting
45+
messageCache:(FIRIAMMessageClientCache *)cache
46+
timeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher
47+
bookKeeper:(id<FIRIAMBookKeeper>)displayBookKeeper
48+
actionURLFollower:(FIRIAMActionURLFollower *)actionURLFollower
49+
activityLogger:(FIRIAMActivityLogger *)activityLogger
50+
analyticsEventLogger:(id<FIRIAMAnalyticsEventLogger>)analyticsEventLogger;
4951

5052
// Check and display next in-app message eligible for app open trigger
5153
- (void)checkAndDisplayNextAppForegroundMessage;

Firebase/InAppMessaging/Flows/FIRIAMDisplayExecutor.m

Lines changed: 87 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#import "FIRIAMMessageContentData.h"
2323
#import "FIRIAMMessageDefinition.h"
2424
#import "FIRIAMSDKRuntimeErrorCodes.h"
25+
#import "FIRInAppMessaging.h"
2526

2627
@implementation FIRIAMDisplaySetting
2728
@end
@@ -32,6 +33,7 @@ @interface FIRIAMDisplayExecutor () <FIRInAppMessagingDisplayDelegate>
3233
// YES if a message is being rendered at this time
3334
@property(nonatomic) BOOL isMsgBeingDisplayed;
3435
@property(nonatomic) NSTimeInterval lastDisplayTime;
36+
@property(nonatomic, nonnull, readonly) FIRInAppMessaging *inAppMessaging;
3537
@property(nonatomic, nonnull, readonly) FIRIAMDisplaySetting *setting;
3638
@property(nonatomic, nonnull, readonly) FIRIAMMessageClientCache *messageCache;
3739
@property(nonatomic, nonnull, readonly) id<FIRIAMBookKeeper> displayBookKeeper;
@@ -45,7 +47,13 @@ @implementation FIRIAMDisplayExecutor {
4547
}
4648

4749
#pragma mark - FIRInAppMessagingDisplayDelegate methods
48-
- (void)messageClicked {
50+
- (void)messageClicked:(FIRInAppMessagingDisplayMessage *)inAppMessage {
51+
// Call through to app-side delegate.
52+
__weak id<FIRInAppMessagingDisplayDelegate> appSideDelegate = self.inAppMessaging.delegate;
53+
if ([appSideDelegate respondsToSelector:@selector(messageClicked:)]) {
54+
[appSideDelegate messageClicked:inAppMessage];
55+
}
56+
4957
self.isMsgBeingDisplayed = NO;
5058
if (!_currentMsgBeingDisplayed.renderData.messageID) {
5159
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM400030",
@@ -124,7 +132,14 @@ - (void)messageClicked {
124132
}
125133
}
126134

127-
- (void)messageDismissedWithType:(FIRInAppMessagingDismissType)dismissType {
135+
- (void)messageDismissed:(FIRInAppMessagingDisplayMessage *)inAppMessage
136+
dismissType:(FIRInAppMessagingDismissType)dismissType {
137+
// Call through to app-side delegate.
138+
__weak id<FIRInAppMessagingDisplayDelegate> appSideDelegate = self.inAppMessaging.delegate;
139+
if ([appSideDelegate respondsToSelector:@selector(messageDismissed:dismissType:)]) {
140+
[appSideDelegate messageDismissed:inAppMessage dismissType:dismissType];
141+
}
142+
128143
self.isMsgBeingDisplayed = NO;
129144
if (!_currentMsgBeingDisplayed.renderData.messageID) {
130145
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM400014",
@@ -170,7 +185,12 @@ - (void)messageDismissedWithType:(FIRInAppMessagingDismissType)dismissType {
170185
}];
171186
}
172187

173-
- (void)impressionDetected {
188+
- (void)impressionDetectedForMessage:(FIRInAppMessagingDisplayMessage *)inAppMessage {
189+
__weak id<FIRInAppMessagingDisplayDelegate> appSideDelegate = self.inAppMessaging.delegate;
190+
if ([appSideDelegate respondsToSelector:@selector(impressionDetectedForMessage:)]) {
191+
[appSideDelegate impressionDetectedForMessage:inAppMessage];
192+
}
193+
174194
if (!_currentMsgBeingDisplayed.renderData.messageID) {
175195
FIRLogWarning(kFIRLoggerInAppMessaging, @"I-IAM400022",
176196
@"impressionDetected called but "
@@ -189,7 +209,13 @@ - (void)impressionDetected {
189209
}
190210
}
191211

192-
- (void)displayErrorEncountered:(NSError *)error {
212+
- (void)displayErrorForMessage:(FIRInAppMessagingDisplayMessage *)inAppMessage
213+
error:(NSError *)error {
214+
__weak id<FIRInAppMessagingDisplayDelegate> appSideDelegate = self.inAppMessaging.delegate;
215+
if ([appSideDelegate respondsToSelector:@selector(displayErrorForMessage:error:)]) {
216+
[appSideDelegate displayErrorForMessage:inAppMessage error:error];
217+
}
218+
193219
self.isMsgBeingDisplayed = NO;
194220

195221
if (!_currentMsgBeingDisplayed.renderData.messageID) {
@@ -283,14 +309,16 @@ - (void)displayMessageLoadError:(NSError *)error {
283309
completion:nil];
284310
}
285311

286-
- (instancetype)initWithSetting:(FIRIAMDisplaySetting *)setting
287-
messageCache:(FIRIAMMessageClientCache *)cache
288-
timeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher
289-
bookKeeper:(id<FIRIAMBookKeeper>)displayBookKeeper
290-
actionURLFollower:(FIRIAMActionURLFollower *)actionURLFollower
291-
activityLogger:(FIRIAMActivityLogger *)activityLogger
292-
analyticsEventLogger:(id<FIRIAMAnalyticsEventLogger>)analyticsEventLogger {
312+
- (instancetype)initWithInAppMessaging:(FIRInAppMessaging *)inAppMessaging
313+
setting:(FIRIAMDisplaySetting *)setting
314+
messageCache:(FIRIAMMessageClientCache *)cache
315+
timeFetcher:(id<FIRIAMTimeFetcher>)timeFetcher
316+
bookKeeper:(id<FIRIAMBookKeeper>)displayBookKeeper
317+
actionURLFollower:(FIRIAMActionURLFollower *)actionURLFollower
318+
activityLogger:(FIRIAMActivityLogger *)activityLogger
319+
analyticsEventLogger:(id<FIRIAMAnalyticsEventLogger>)analyticsEventLogger {
293320
if (self = [super init]) {
321+
_inAppMessaging = inAppMessaging;
294322
_timeFetcher = timeFetcher;
295323
_lastDisplayTime = displayBookKeeper.lastDisplayTime;
296324
_setting = setting;
@@ -334,43 +362,53 @@ - (void)checkAndDisplayNextContextualMessageForAnalyticsEvent:(NSString *)eventN
334362
[self.messageCache nextOnFirebaseAnalyticEventDisplayMsg:eventName];
335363

336364
if (nextAnalyticsBasedMessage) {
337-
[self displayForMessage:nextAnalyticsBasedMessage];
365+
[self displayForMessage:nextAnalyticsBasedMessage
366+
triggerType:FIRInAppMessagingDisplayTriggerTypeOnAnalyticsEvent];
338367
}
339368
}
340369
}
341370

342371
- (FIRInAppMessagingBannerDisplay *)
343372
bannerMessageWithMessageDefinition:(FIRIAMMessageDefinition *)definition
344-
imageData:(FIRInAppMessagingImageData *)imageData {
373+
imageData:(FIRInAppMessagingImageData *)imageData
374+
triggerType:(FIRInAppMessagingDisplayTriggerType)triggerType {
345375
NSString *title = definition.renderData.contentData.titleText;
346376
NSString *body = definition.renderData.contentData.bodyText;
347377

348378
FIRInAppMessagingBannerDisplay *bannerMessage = [[FIRInAppMessagingBannerDisplay alloc]
349379
initWithMessageID:definition.renderData.messageID
380+
campaignName:definition.renderData.name
350381
renderAsTestMessage:definition.isTestMessage
382+
triggerType:triggerType
351383
titleText:title
352384
bodyText:body
353385
textColor:definition.renderData.renderingEffectSettings.textColor
354386
backgroundColor:definition.renderData.renderingEffectSettings.displayBGColor
355-
imageData:imageData];
387+
imageData:imageData
388+
actionURL:definition.renderData.contentData.actionURL];
356389

357390
return bannerMessage;
358391
}
359392

360393
- (FIRInAppMessagingImageOnlyDisplay *)
361394
imageOnlyMessageWithMessageDefinition:(FIRIAMMessageDefinition *)definition
362-
imageData:(FIRInAppMessagingImageData *)imageData {
363-
FIRInAppMessagingImageOnlyDisplay *imageOnlyMessage =
364-
[[FIRInAppMessagingImageOnlyDisplay alloc] initWithMessageID:definition.renderData.messageID
365-
renderAsTestMessage:definition.isTestMessage
366-
imageData:imageData];
395+
imageData:(FIRInAppMessagingImageData *)imageData
396+
triggerType:(FIRInAppMessagingDisplayTriggerType)triggerType {
397+
FIRInAppMessagingImageOnlyDisplay *imageOnlyMessage = [[FIRInAppMessagingImageOnlyDisplay alloc]
398+
initWithMessageID:definition.renderData.messageID
399+
campaignName:definition.renderData.name
400+
renderAsTestMessage:definition.isTestMessage
401+
triggerType:triggerType
402+
imageData:imageData
403+
actionURL:definition.renderData.contentData.actionURL];
367404

368405
return imageOnlyMessage;
369406
}
370407

371408
- (FIRInAppMessagingModalDisplay *)
372409
modalViewMessageWithMessageDefinition:(FIRIAMMessageDefinition *)definition
373-
imageData:(FIRInAppMessagingImageData *)imageData {
410+
imageData:(FIRInAppMessagingImageData *)imageData
411+
triggerType:(FIRInAppMessagingDisplayTriggerType)triggerType {
374412
// For easier reference in this method.
375413
FIRIAMMessageRenderData *renderData = definition.renderData;
376414

@@ -388,33 +426,44 @@ - (void)checkAndDisplayNextContextualMessageForAnalyticsEvent:(NSString *)eventN
388426

389427
FIRInAppMessagingModalDisplay *modalViewMessage = [[FIRInAppMessagingModalDisplay alloc]
390428
initWithMessageID:definition.renderData.messageID
429+
campaignName:definition.renderData.name
391430
renderAsTestMessage:definition.isTestMessage
431+
triggerType:triggerType
392432
titleText:title
393433
bodyText:body
394434
textColor:renderData.renderingEffectSettings.textColor
395435
backgroundColor:renderData.renderingEffectSettings.displayBGColor
396436
imageData:imageData
397-
actionButton:actionButton];
437+
actionButton:actionButton
438+
actionURL:definition.renderData.contentData.actionURL];
398439

399440
return modalViewMessage;
400441
}
401442

402-
- (FIRInAppMessagingDisplayMessageBase *)
443+
- (FIRInAppMessagingDisplayMessage *)
403444
displayMessageWithMessageDefinition:(FIRIAMMessageDefinition *)definition
404-
imageData:(FIRInAppMessagingImageData *)imageData {
445+
imageData:(FIRInAppMessagingImageData *)imageData
446+
triggerType:(FIRInAppMessagingDisplayTriggerType)triggerType {
405447
switch (definition.renderData.renderingEffectSettings.viewMode) {
406448
case FIRIAMRenderAsBannerView:
407-
return [self bannerMessageWithMessageDefinition:definition imageData:imageData];
449+
return [self bannerMessageWithMessageDefinition:definition
450+
imageData:imageData
451+
triggerType:triggerType];
408452
case FIRIAMRenderAsModalView:
409-
return [self modalViewMessageWithMessageDefinition:definition imageData:imageData];
453+
return [self modalViewMessageWithMessageDefinition:definition
454+
imageData:imageData
455+
triggerType:triggerType];
410456
case FIRIAMRenderAsImageOnlyView:
411-
return [self imageOnlyMessageWithMessageDefinition:definition imageData:imageData];
457+
return [self imageOnlyMessageWithMessageDefinition:definition
458+
imageData:imageData
459+
triggerType:triggerType];
412460
default:
413461
return nil;
414462
}
415463
}
416464

417-
- (void)displayForMessage:(FIRIAMMessageDefinition *)message {
465+
- (void)displayForMessage:(FIRIAMMessageDefinition *)message
466+
triggerType:(FIRInAppMessagingDisplayTriggerType)triggerType {
418467
_currentMsgBeingDisplayed = message;
419468
[message.renderData.contentData
420469
loadImageDataWithBlock:^(NSData *_Nullable imageNSData, NSError *error) {
@@ -424,8 +473,12 @@ - (void)displayForMessage:(FIRIAMMessageDefinition *)message {
424473
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM400019",
425474
@"Error in loading image data for the message.");
426475

476+
FIRInAppMessagingDisplayMessage *erroredMessage =
477+
[self displayMessageWithMessageDefinition:message
478+
imageData:imageData
479+
triggerType:triggerType];
427480
// short-circuit to display error handling
428-
[self displayErrorEncountered:error];
481+
[self displayErrorForMessage:erroredMessage error:error];
429482
return;
430483
} else if (imageNSData != nil) {
431484
imageData = [[FIRInAppMessagingImageData alloc]
@@ -436,8 +489,10 @@ - (void)displayForMessage:(FIRIAMMessageDefinition *)message {
436489
self.impressionRecorded = NO;
437490
self.isMsgBeingDisplayed = YES;
438491

439-
FIRInAppMessagingDisplayMessageBase *displayMessage =
440-
[self displayMessageWithMessageDefinition:message imageData:imageData];
492+
FIRInAppMessagingDisplayMessage *displayMessage =
493+
[self displayMessageWithMessageDefinition:message
494+
imageData:imageData
495+
triggerType:triggerType];
441496
[self.messageDisplayComponent displayMessage:displayMessage displayDelegate:self];
442497
}];
443498
}
@@ -481,7 +536,8 @@ - (void)checkAndDisplayNextAppForegroundMessage {
481536
FIRIAMMessageDefinition *nextForegroundMessage = [self.messageCache nextOnAppOpenDisplayMsg];
482537

483538
if (nextForegroundMessage) {
484-
[self displayForMessage:nextForegroundMessage];
539+
[self displayForMessage:nextForegroundMessage
540+
triggerType:FIRInAppMessagingDisplayTriggerTypeOnAppForeground];
485541
self.lastDisplayTime = [self.timeFetcher currentTimestampInSeconds];
486542
} else {
487543
FIRLogDebug(kFIRLoggerInAppMessaging, @"I-IAM400001",

Firebase/InAppMessaging/Public/FIRInAppMessaging.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,11 @@ NS_SWIFT_NAME(InAppMessaging)
7676
* property so that it can be used for rendering fiam message UIs.
7777
*/
7878
@property(nonatomic) id<FIRInAppMessagingDisplay> messageDisplayComponent;
79+
80+
/**
81+
* This delegate should be set on the app side to receive message lifecycle events in app runtime.
82+
*/
83+
@property(nonatomic, weak) id<FIRInAppMessagingDisplayDelegate> delegate;
84+
7985
@end
8086
NS_ASSUME_NONNULL_END

0 commit comments

Comments
 (0)