diff --git a/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler.m b/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler.m index e6932bf..94211c8 100644 --- a/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler.m +++ b/MVMCore/MVMCore/ActionHandling/MVMCoreActionHandler.m @@ -219,7 +219,7 @@ NSString * const KeyActionTypeOpen = @"openPage"; NSDictionary *responseInfo = [jsonDictionary dict:KeyResponseInfo]; if (responseInfo) { MVMCoreAlertObject *alertObject = [MVMCoreAlertObject alertObjectForPageType:pageTypeForTopAlert responseInfo:responseInfo additionalData:additionalData actionDelegate:delegate]; - if ([delegate respondsToSelector:@selector(willShowPopupWithAlertObject:alertJson:)]) { + if ([delegate respondsToSelector:@selector(willShowTopAlertWithAlertObject:alertJson:)]) { alertObject = [delegate willShowTopAlertWithAlertObject:alertObject alertJson:jsonDictionary]; } [alertObject showAlert]; diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.h b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.h index 977911f..e38bedf 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.h +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.h @@ -8,9 +8,11 @@ // Used by our alert handler. Not for subclassing. Simply keeps track of if it's visible. Tries to parallel the UIAlertView to make it easier for the MVMCoreAlertHandler. #import +@class MVMCoreAlertObject; @interface MVMCoreAlertController : UIAlertController @property (nonatomic, readonly, getter=isVisible) BOOL visible; +@property (nullable, nonatomic, strong) MVMCoreAlertObject *alertObject; @end diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.m b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.m index 89352a4..673c591 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.m +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertController.m @@ -7,6 +7,7 @@ // #import "MVMCoreAlertController.h" +#import "MVMCoreLoggingHandler.h" @interface MVMCoreAlertController () @@ -22,6 +23,7 @@ [self willChangeValueForKey:@"isVisible"]; self.visible = YES; [self didChangeValueForKey:@"isVisible"]; + [MVMCoreLoggingHandler logAlertForAlertController:self]; } - (void)viewDidDisappear:(BOOL)animated { diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertDelegateProtocol.h b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertDelegateProtocol.h index 2bd6a6b..f4f05e5 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertDelegateProtocol.h +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertDelegateProtocol.h @@ -8,11 +8,15 @@ // Called for popup style alerts. #import +@class MVMCoreAlertObject; @protocol MVMCoreAlertDelegateProtocol @optional +// helps tracking alert state +- (nullable NSDictionary *)additionalAlertDataToTrackForAlertWithObject:(nullable MVMCoreAlertObject *)alertObject; + // All are performed on the main thread. - (void)alertShown:(nonnull UIAlertController *)alertController; - (void)alertCancelled:(nonnull UIAlertController *)alertController; diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m index bbbda62..5d5f93b 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m @@ -102,7 +102,9 @@ } - (nonnull UIAlertController *)showAlertWithAlertObject:(nonnull MVMCoreAlertObject *)alertObject { - return [self showAlertWithTitle:alertObject.title message:alertObject.message actions:alertObject.actions alertStyle:alertObject.alertStyle isGreedy:alertObject.isGreedy alertDelegate:alertObject.alertDelegate]; + MVMCoreAlertController *controller = (MVMCoreAlertController *)[self showAlertWithTitle:alertObject.title message:alertObject.message actions:alertObject.actions alertStyle:alertObject.alertStyle isGreedy:alertObject.isGreedy alertDelegate:alertObject.alertDelegate]; + controller.alertObject = alertObject; + return controller; } - (void)removeAllAlertViews { diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.h b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.h index 4b9d12c..9735c7c 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.h +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.h @@ -28,6 +28,7 @@ typedef void (^TextFieldErrorHandler)(NSArray * _Nonnull fieldErrors); @interface MVMCoreAlertObject : NSObject @property (nullable, strong, nonatomic) NSString *title; +@property (nullable, copy, nonatomic) NSDictionary *pageJson; @property (nullable, strong, nonatomic) NSString *message; @property (nonnull, strong, nonatomic) NSArray *actions; @property (nonatomic) BOOL isGreedy; diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.m b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.m index 5599049..0a5d8ca 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.m +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject.m @@ -71,7 +71,7 @@ // Perform a popup. alert.type = MFAlertTypePopup; alert.alertStyle = UIAlertControllerStyleAlert; - + // Check if we have a popup driven by page object (otherwise by default it will just use response info title message with an OK button). NSString *pageTypeForPopup = [responseInfo stringForKey:@"popupPageType"]; [[MVMCoreCache sharedCache] fetchJSONForPageType:pageTypeForPopup queue:nil waitUntilFinished:YES completionHandler:^(NSDictionary * _Nullable jsonDictionary) { @@ -99,6 +99,7 @@ alert.alertStyle = UIAlertControllerStyleAlert; } } + alert.alertDelegate = actionDelegate; return alert; } @@ -145,6 +146,7 @@ MVMCoreAlertObject *alert = [[MVMCoreAlertObject alloc] init]; alert.title = [page stringForKey:KeyTitle]; + alert.pageJson = page; alert.message = [page stringForKey:KeyMessage]; alert.isGreedy = isGreedy; alert.type = MFAlertTypePopup; diff --git a/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.h b/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.h index ed5931f..6ae8fc6 100644 --- a/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.h +++ b/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.h @@ -24,6 +24,9 @@ - (CGFloat)floatForKey:(nonnull id)key; - (double)doubleForKey:(nonnull id)key; +// Not strict, can accept either string or boolean. +- (BOOL)lenientBoolForKey:(nonnull id)key; + // Gets an object that is nested using a series of keys or indexes to reach it. // All keys should be of type NSString and is used for nested dictionaries. // All indexes should be of type NSNumber and is used for nested arrays. diff --git a/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.m b/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.m index 8de5180..f4e087d 100644 --- a/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.m +++ b/MVMCore/MVMCore/Categories/NSDictionary+MFConvenience.m @@ -32,6 +32,15 @@ return [[self objectForKey:key ofType:[NSNumber class]] boolValue]; } +- (BOOL)lenientBoolForKey:(nonnull id)key { + NSObject *object = [self objectForKey:key]; + if ([object isKindOfClass:[NSString class]]) { + return [((NSString *)object) isEqualToString:@"true"]; + } else { + return [((NSNumber *)([object isKindOfClass:[NSNumber class]] ? object : nil)) boolValue]; + } +} + - (CGFloat)floatForKey:(nonnull id)key { return [[self objectForKey:key ofType:[NSNumber class]] floatValue]; } diff --git a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h index 014e4ba..6699e27 100644 --- a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h +++ b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h @@ -23,6 +23,9 @@ // The data for hte page that was loaded @property (nullable, strong, nonatomic) NSDictionary *pageJSON; +// Contains the button map +@property (nullable, nonatomic, strong, readonly) NSDictionary *buttonMap; + // the modules that are needed @property (nullable, strong, nonatomic) NSDictionary *modulesJSON; diff --git a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.m b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.m index 388f911..5c56b3a 100644 --- a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.m +++ b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.m @@ -22,6 +22,10 @@ return self; } +- (NSDictionary *)buttonMap { + return [self.pageJSON dict:KeyButtonMap]; +} + - (nullable instancetype)initWithRequestParameters:(nullable MVMCoreRequestParameters *)requestParameters dataForPage:(nullable NSDictionary *)dataForPage delegate:(nullable NSObject*)delegate { if (self = [self initWithDelegate:delegate]) { self.requestParameters = requestParameters; diff --git a/MVMCore/MVMCore/LoadHandling/MVMCoreRequestParameters.m b/MVMCore/MVMCore/LoadHandling/MVMCoreRequestParameters.m index 8524bf3..b72132a 100644 --- a/MVMCore/MVMCore/LoadHandling/MVMCoreRequestParameters.m +++ b/MVMCore/MVMCore/LoadHandling/MVMCoreRequestParameters.m @@ -67,6 +67,7 @@ if (self = [self initWithPageType:[actionMap stringForKey:KeyPageType] additionalModules:[actionMap array:KeyModuleList] extraParameters:[actionMap dict:KeyExtraParameters]]) { self.contextRoot = [actionMap string:KeyContextRoot]; self.actionMap = actionMap; + self.customTimeoutTime = [actionMap objectForKey:@"customTimeoutTime" ofType:[NSNumber class]]; self.openSupportPanel = [actionMap boolForKey:KeyOpenSupport]; // Right now server is sending default.... can't uncomment this until they remove default @@ -132,6 +133,7 @@ copyObject.alternateBaseURL = self.alternateBaseURL; copyObject.openSupportPanel = self.openSupportPanel; copyObject.imageData = self.imageData; + copyObject.customTimeoutTime = self.customTimeoutTime; return copyObject; } diff --git a/MVMCore/MVMCore/MainProtocols/MVMCoreLoggingDelegateProtocol.h b/MVMCore/MVMCore/MainProtocols/MVMCoreLoggingDelegateProtocol.h index fc0e353..b8ae254 100644 --- a/MVMCore/MVMCore/MainProtocols/MVMCoreLoggingDelegateProtocol.h +++ b/MVMCore/MVMCore/MainProtocols/MVMCoreLoggingDelegateProtocol.h @@ -7,6 +7,7 @@ // #import +@class MVMCoreAlertController; @protocol MVMCoreLoggingDelegateProtocol @@ -24,4 +25,7 @@ // Log that the load has finished. - (void)logLoadFinished:(nullable MVMCoreLoadObject *)loadObject loadedViewController:(nullable UIViewController *)loadedViewController error:(nullable MVMCoreErrorObject *)error; +// Log alert +- (void)logAlertForAlertController:(nullable MVMCoreAlertController *)alertController; + @end diff --git a/MVMCore/MVMCore/MainStructure/PanelProtocol.h b/MVMCore/MVMCore/MainStructure/PanelProtocol.h index 5ab0ae3..2db89c7 100644 --- a/MVMCore/MVMCore/MainStructure/PanelProtocol.h +++ b/MVMCore/MVMCore/MainStructure/PanelProtocol.h @@ -14,6 +14,9 @@ @optional +// The panel can return if it should be available or not. +- (BOOL)panelAvailable; + - (void)panel:(UIViewController *_Nullable)panel viewWillAppear:(BOOL)animated; - (void)panel:(UIViewController *_Nullable)panel viewDidAppear:(BOOL)animated; - (void)panel:(UIViewController *_Nullable)panel viewWillDisappear:(BOOL)animated; diff --git a/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.h b/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.h index 48700ec..12d0e2a 100644 --- a/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.h +++ b/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.h @@ -10,6 +10,7 @@ #import #import #import +@class MVMCoreAlertController; #define MVMCoreLog(fmt, ...) \ [MVMCoreLoggingHandler logDebugMessageWithDelegate:[NSString stringWithFormat:(@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__]]; @@ -20,5 +21,6 @@ + (void)logDebugMessageWithDelegate:(nullable NSString *)message; + (void)logWithDelegateWithObject:(nullable id)object withName:(nullable NSString *)name withExtraInfo:(nullable NSDictionary *)extra; + (void)logWithDelegateLoadFinished:(nullable MVMCoreLoadObject *)loadObject loadedViewController:(nullable UIViewController *)loadedViewController error:(nullable MVMCoreErrorObject *)error; ++ (void)logAlertForAlertController:(nullable MVMCoreAlertController *)alertController; @end diff --git a/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.m b/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.m index 3c1daf8..65e2659 100644 --- a/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.m +++ b/MVMCore/MVMCore/OtherHandlers/MVMCoreLoggingHandler.m @@ -35,5 +35,11 @@ } } ++ (void)logAlertForAlertController:(nullable MVMCoreAlertController *)alertController { + if ([[MVMCoreObject sharedInstance].loggingDelegate respondsToSelector:@selector(logAlertForAlertController:)]) { + [[MVMCoreObject sharedInstance].loggingDelegate logAlertForAlertController:alertController]; + } +} + @end