diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.h b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.h index a4c44ec..2142d63 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.h +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.h @@ -12,10 +12,19 @@ #import #import +@class NotificationPagesOperation; @class MVMCoreAlertObject; @interface MVMCoreAlertHandler : NSObject +// An operation queue for displaying popup alerts. +@property (nonnull, strong, nonatomic) NSOperationQueue *popupAlertQueue; + +// An operation queue for top alerts +@property (nonnull, strong, nonatomic) NSOperationQueue *topAlertQueue; + +@property (nonnull, strong, nonatomic) NSOperationQueue *pageOperations; + /// Returns the shared instance of this singleton + (nullable instancetype)sharedAlertHandler; diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m index 0c9393a..1e64663 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertHandler.m @@ -14,18 +14,13 @@ #import "MVMCoreJSONConstants.h" #import "NSDictionary+MFConvenience.h" #import "NSArray+MFConvenience.h" +#import @interface MVMCoreAlertHandler () // Flag that keeps track of if the alerts are supressed or not. @property (assign, nonatomic) BOOL mfAlertsSupressed; -// An operation queue for displaying popup alerts. -@property (nonnull, strong, nonatomic) NSOperationQueue *popupAlertQueue; - -// An operation queue for top alerts -@property (nonnull, strong, nonatomic) NSOperationQueue *topAlertQueue; - @end @implementation MVMCoreAlertHandler @@ -47,6 +42,7 @@ self.popupAlertQueue.maxConcurrentOperationCount = 1; self.topAlertQueue = [[NSOperationQueue alloc] init]; self.topAlertQueue.maxConcurrentOperationCount = 1; + self.pageOperations = [[NSOperationQueue alloc] init]; } return self; } @@ -167,14 +163,19 @@ if (topAlertObject) { __block MVMCoreTopAlertOperation *alertOperation = [[MVMCoreTopAlertOperation alloc] initWithTopAlertObject:topAlertObject]; + __weak typeof(self) weakSelf = self; [alertOperation setCompletionBlock:^{ // If the alert was cancelled to show another with higher priority, re-add to the operation when cancelled to the queue. if (alertOperation.reAddAfterCancel) { - [self showTopAlertWithObject:alertOperation.topAlertObject]; + [weakSelf showTopAlertWithObject:alertOperation.topAlertObject]; } alertOperation = nil; }]; + + // This notification may only show for certain pages. + [self addPagesDependencyTo:alertOperation]; + [self.topAlertQueue addOperation:alertOperation]; // If the current running operation is persistent and has a lower queue priority then the added operation, cancel it and re-add it. diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject+Swift.swift b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject+Swift.swift index 162dd2d..b58de05 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject+Swift.swift +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreAlertObject+Swift.swift @@ -43,3 +43,63 @@ public extension MVMCoreAlertObject { return alertObject } } + +// Temporary location +@objcMembers public class NotificationPagesOperation: Operation { + public let pages: [String] + + public init(with pages: [String]) { + self.pages = pages + } + + public override var isReady: Bool { + get { + return super.isReady && isCancelled + } + } +} + +public extension MVMCoreAlertHandler { + @objc func addPagesDependency(to operation: MVMCoreTopAlertOperation) { + // This notification may only show for certain pages. + guard let pages = operation.topAlertObject.json?.optionalArrayForKey("pages") as? [String], + pages.count > 0 else { return } + let pagesOperation = NotificationPagesOperation(with: pages) + pageOperations.addOperation(pagesOperation) + operation.addDependency(pagesOperation) + + print("TYTYT added dependency \(operation)") + } + + @objc func checkPagesDependency(for pageType: String?) { + // TODO: check top alerts that didn't show that had the same page requirement. + + // If the current running operation is persistent and should not show on the current page, cancel it and re-add it. + for case let operation as MVMCoreTopAlertOperation in topAlertQueue.operations { + if !operation.isCancelled, + let pages = operation.topAlertObject.json?.optionalArrayForKey("pages") as? [String], + (pageType == nil || !pages.contains(pageType!)) { + if operation.isExecuting { + operation.reAddAfterCancel = operation.topAlertObject.persistent + operation.cancel() + print("TYTYT cancelled current \(operation)") + } else if !operation.dependencies.contains(where: { !$0.isFinished }) { + let pagesOperation = NotificationPagesOperation(with: pages) + pageOperations.addOperation(pagesOperation) + operation.addDependency(pagesOperation) + print("TYTYT re-added previouly removed \(operation)") + } + } + } + + // Remove the dependency if it contains the page. + // Change to isReady, find a way to get the page type... + guard let pageType = pageType else { return } + for case let operation as NotificationPagesOperation in pageOperations.operations { + if operation.pages.contains(pageType) { + operation.cancel() + print("TYTYT cancel dependency \(operation)") + } + } + } +} diff --git a/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertObject.h b/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertObject.h index 5a4b587..97897cc 100644 --- a/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertObject.h +++ b/MVMCore/MVMCore/AlertHandling/MVMCoreTopAlertObject.h @@ -15,6 +15,7 @@ extern NSUInteger const TopAlertDismissTime; @property (nonatomic) BOOL persistent; @property (nullable, nonatomic) NSString *type; +@property (nonatomic) NSOperationQueuePriority queuePriority; // The text @property (nullable, strong, nonatomic) NSString *title; @@ -49,6 +50,9 @@ extern NSUInteger const TopAlertDismissTime; @property (nullable, strong, nonatomic) UIColor *backgroundColor; @property (nullable, strong, nonatomic) UIColor *textColor; +// For a json driven approach. +@property (nullable, strong, nonatomic) NSDictionary *json; + - (nullable instancetype)initWithResponseInfo:(nullable NSDictionary *)responseInfo; - (nullable instancetype)initWithType:(nullable NSString *)type message:(nullable NSString *)message; diff --git a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h index f167ea7..92063b8 100644 --- a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h +++ b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadObject.h @@ -56,6 +56,9 @@ @property (nonatomic) BOOL pageDataFromCache; @property (nonatomic) BOOL moduleDataFromCache; +// The full response json +@property (nullable, strong, nonatomic) NSDictionary *responseJSON; + - (nullable instancetype)initWithPageJSON:(nullable NSDictionary *)pageJSON modulesJSON:(nullable NSDictionary *)modulesJSON requestParameters:(nullable MVMCoreRequestParameters *)requestParameters dataForPage:(nullable NSDictionary *)dataForPage delegateObject:(nullable DelegateObject *)delegateObject; - (nullable instancetype)initWithRequestParameters:(nullable MVMCoreRequestParameters *)requestParameters dataForPage:(nullable NSDictionary *)dataForPage delegateObject:(nullable DelegateObject *)delegateObject; diff --git a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m index 2f4019b..b6e0ca9 100644 --- a/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m +++ b/MVMCore/MVMCore/LoadHandling/MVMCoreLoadRequestOperation.m @@ -354,6 +354,8 @@ return; } + loadObject.responseJSON = jsonDictionary; + // Store the new page data if we didn't load page data from the cache. NSDictionary *pageJSON = [jsonDictionary objectForKey:KeyPage ofType:[NSDictionary class]]; if (!loadObject.pageDataFromCache) {