Merge branch 'feature/cancellable_top_alert_timer' into 'develop'
Feature/cancellable top alert timer See merge request BPHV_MIPS/mvm_core!119
This commit is contained in:
commit
11d7fcb4d7
@ -36,43 +36,60 @@ public extension MVMCoreAlertHandler {
|
||||
operation.addDependency(pagesOperation)
|
||||
}
|
||||
|
||||
/// checks top alerts for page dependencies with the new pageType
|
||||
@objc func checkPagesDependency(for pageType: String?) {
|
||||
// If the current running operation should not show on the current page, cancel it. If it's persistent, re-add it. If another operation has had the dependency remove previously, add it back.
|
||||
/// Updates the pages requirement for the operation
|
||||
@objc func updatePages(for operation: MVMCoreTopAlertOperation, with topAlertObject: MVMCoreTopAlertObject) {
|
||||
// Add new dependencies, remove old.
|
||||
let previousPages = operation.dependencies.filter { $0 as? NotificationPagesOperation != nil }
|
||||
addPagesDependency(to: operation)
|
||||
for pageOperation in previousPages {
|
||||
pageOperation.cancel()
|
||||
operation.removeDependency(pageOperation)
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles page dependencies for all top alerts with the new pageType
|
||||
@objc func handleAllPagesDependency(for pageType: String?) {
|
||||
var currentOperation: MVMCoreTopAlertOperation? = nil
|
||||
for case let operation as MVMCoreTopAlertOperation in topAlertQueue.operations {
|
||||
if !operation.isCancelled,
|
||||
let pages = operation.topAlertObject.json?.optionalArrayForKey("pages") as? [String],
|
||||
pages.count > 0,
|
||||
(pageType == nil || !pages.contains(pageType!)) {
|
||||
if operation.isExecuting {
|
||||
operation.reAddAfterCancel = operation.topAlertObject.persistent
|
||||
operation.cancel()
|
||||
} else if !operation.dependencies.contains(where: { !$0.isFinished }) {
|
||||
let pagesOperation = NotificationPagesOperation(with: pages)
|
||||
pageOperations.addOperation(pagesOperation)
|
||||
operation.addDependency(pagesOperation)
|
||||
}
|
||||
// Handle the currently executing opration last to avoid race conditions.
|
||||
guard !operation.isExecuting else {
|
||||
currentOperation = operation
|
||||
continue
|
||||
}
|
||||
handlePageDependency(for: operation, with: pageType)
|
||||
}
|
||||
if let operation = currentOperation {
|
||||
handlePageDependency(for: operation, with: pageType)
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the operation based on the page type and its dependencies.
|
||||
@objc func handlePageDependency(for operation: MVMCoreTopAlertOperation, with pageType: String?) {
|
||||
guard !operation.isCancelled else { return }
|
||||
|
||||
if let pages = operation.topAlertObject.json?.optionalArrayForKey("pages") as? [String],
|
||||
pages.count > 0,
|
||||
(pageType == nil || !pages.contains(pageType!)) {
|
||||
if let dependency = operation.dependencies.first(where: { $0.isFinished && ($0 as? NotificationPagesOperation)?.pages == pages }) {
|
||||
// Re-add the dependency if it was previously cancelled.
|
||||
let pagesOperation = NotificationPagesOperation(with: pages)
|
||||
pageOperations.addOperation(pagesOperation)
|
||||
operation.addDependency(pagesOperation)
|
||||
operation.removeDependency(dependency)
|
||||
}
|
||||
if operation.isExecuting {
|
||||
// If the current running operation should not show on the current page, cancel it. If it's persistent, re-add it
|
||||
operation.reAddAfterCancel = operation.topAlertObject.persistent
|
||||
operation.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the dependency if it contains the current page.
|
||||
|
||||
// Cancel any dependency if it contains the current page.
|
||||
guard let pageType = pageType else { return }
|
||||
for case let operation as NotificationPagesOperation in pageOperations.operations {
|
||||
for case let operation as NotificationPagesOperation in operation.dependencies {
|
||||
if operation.pages.contains(pageType) {
|
||||
operation.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks for existing top alert object of same type and updates it. Only happens for molecular top alerts. Returns true if we updated.
|
||||
@objc func checkAndUpdateExisting(with topAlertObject: MVMCoreTopAlertObject) -> Bool {
|
||||
// ToDo: do pages and priority.
|
||||
for case let operation as MVMCoreTopAlertOperation in topAlertQueue.operations {
|
||||
guard topAlertObject.json != nil,
|
||||
operation.topAlertObject.type == topAlertObject.type else { continue }
|
||||
operation.update(with: topAlertObject)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
#import <MVMCore/MVMCoreAlertDelegateProtocol.h>
|
||||
|
||||
@class MVMCoreAlertObject;
|
||||
@class MVMCoreTopAlertOperation;
|
||||
|
||||
@interface MVMCoreAlertHandler : NSObject
|
||||
|
||||
@ -88,9 +89,12 @@
|
||||
|
||||
#pragma mark - Top Alert Functions
|
||||
|
||||
/// Show based on the object. Will be used by the architecture.
|
||||
/// Show based on the object. Will be used by the architecture. Creates an operation and calls addTopAlertOperation.
|
||||
- (void)showTopAlertWithObject:(nullable MVMCoreTopAlertObject *)topAlertObject;
|
||||
|
||||
/// Adds the top alert operation to the queue.
|
||||
- (void)addTopAlertOperation:(nonnull MVMCoreTopAlertOperation *)topAlertOperation;
|
||||
|
||||
/// Convenience functions
|
||||
- (void)showTopAlertErrorWithMessage:(nullable NSString *)message;
|
||||
- (void)showTopAlertConfirmationWithMessage:(nullable NSString *)message;
|
||||
|
||||
@ -158,39 +158,38 @@
|
||||
|
||||
#pragma mark - Top Alert Functions
|
||||
|
||||
- (void)showTopAlertWithObject:(nullable MVMCoreTopAlertObject *)topAlertObject {
|
||||
- (void)addTopAlertOperation:(nonnull MVMCoreTopAlertOperation *)topAlertOperation {
|
||||
__block MVMCoreTopAlertOperation *alertOperation = topAlertOperation;
|
||||
__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) {
|
||||
MVMCoreTopAlertOperation *newOperation = [alertOperation copy];
|
||||
newOperation.reAddAfterCancel = NO;
|
||||
[weakSelf addTopAlertOperation:newOperation];
|
||||
}
|
||||
alertOperation = nil;
|
||||
}];
|
||||
|
||||
// Check if we need to add a new operation.
|
||||
if (topAlertObject && ![self checkAndUpdateExistingWith:topAlertObject]) {
|
||||
[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.
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
|
||||
__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) {
|
||||
[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.
|
||||
for (MVMCoreTopAlertOperation *operation in self.topAlertQueue.operations) {
|
||||
|
||||
if (operation.isExecuting && !operation.isCancelled && operation.topAlertObject.persistent && operation.queuePriority < alertOperation.queuePriority) {
|
||||
operation.reAddAfterCancel = YES;
|
||||
[operation cancel];
|
||||
break;
|
||||
}
|
||||
if (operation.isExecuting && !operation.isCancelled && operation.topAlertObject.persistent && operation.queuePriority < alertOperation.queuePriority && alertOperation.isReady) {
|
||||
operation.reAddAfterCancel = YES;
|
||||
[operation cancel];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)showTopAlertWithObject:(nullable MVMCoreTopAlertObject *)topAlertObject {
|
||||
MVMCoreTopAlertOperation *alertOperation = [[MVMCoreTopAlertOperation alloc] initWithTopAlertObject:topAlertObject];
|
||||
[self addTopAlertOperation:alertOperation];
|
||||
}
|
||||
|
||||
- (void)showTopAlertErrorWithMessage:(nullable NSString *)message {
|
||||
|
||||
MVMCoreTopAlertObject *topAlertObject = [[MVMCoreTopAlertObject alloc] initWithType:ValueTypeError message:message];
|
||||
|
||||
@ -247,4 +247,18 @@
|
||||
[self dismissAlertView:YES forceful:YES];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(nullable NSZone *)zone {
|
||||
MVMCoreTopAlertOperation *copyObject = [[MVMCoreTopAlertOperation alloc] init];
|
||||
copyObject.topAlertObject = self.topAlertObject;
|
||||
copyObject.paused = self.paused;
|
||||
copyObject.reAddAfterCancel = self.reAddAfterCancel;
|
||||
copyObject.queuePriority = self.queuePriority;
|
||||
for (NSOperation *dependency in self.dependencies) {
|
||||
[copyObject addDependency:dependency];
|
||||
}
|
||||
copyObject.name = self.name;
|
||||
copyObject.qualityOfService = self.qualityOfService;
|
||||
return copyObject;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Loading…
Reference in New Issue
Block a user