Bug fixes

This commit is contained in:
Scott Pfeil 2023-04-19 16:36:16 -04:00
parent e61b9ed8f1
commit 7df6882907
6 changed files with 74 additions and 24 deletions

View File

@ -16,7 +16,11 @@ public class AlertHandler {
}
/// The operation queue of alert operations.
private var queue = OperationQueue()
private var queue = {
let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1
return queue
}()
public init() {}

View File

@ -24,16 +24,28 @@ public class AlertOperation: MVMCoreOperation {
}
}
private var properties = Properties()
private var cancellable: Cancellable?
public let alertController: AlertController
private var alDescription: String = ""
public let alertObject: AlertObject
/// For tracking isVisible changes of the alert controller.
private var cancellable: Cancellable?
/// Blocks the navigation queue to ensure no other navigation happens while an alert is displayed.
private var blockingOperation: MVMCoreOperation?
public init(with alert: AlertController, alertObject: AlertObject) {
self.alertController = alert
self.alertObject = alertObject
super.init()
MVMCoreDispatchUtility.performSyncBlock(onMainThread: {
self.alDescription = alert.description
})
}
deinit {
@ -46,24 +58,38 @@ public class AlertOperation: MVMCoreOperation {
// Observe for when it is removed.
observeForCurrentAlertViewDismissal()
print("---\nTTTTTT alertOperation present: \(self.description)\ncontroller:\(self.alDescription)\nobject: \(alertObject.alertModel.id)\n---")
// Adds the presentation to the animation queue.
MVMCoreNavigationHandler.shared()?.present(alertController, animated: true, delegate: nil) { [weak self] in
guard let self = self else { return }
Task {
// We finished but it was not displayed yet. It's possible that it was cancelled. Finish this task
if await !self.properties.getIsDisplayed() {
self.markAsFinished()
} else {
(CoreUIObject.sharedInstance()?.loggingDelegate as? MVMCoreUILoggingDelegateProtocol)?.logAlert(with: self.alertObject)
if self.isCancelled {
await self.dismissAlertView()
let blockingOperation = MVMCoreOperation()
self.blockingOperation = blockingOperation
Task { @MainActor in
MVMCoreNavigationHandler.shared()?.present(alertController, animated: true, delegate: nil) { [weak self] in
guard let self = self else {
blockingOperation.markAsFinished()
return
}
Task {
// We finished but it was not displayed yet. It's possible that it was cancelled. Finish this task
if await !self.properties.getIsDisplayed() {
self.markAsFinished()
} else {
(CoreUIObject.sharedInstance()?.loggingDelegate as? MVMCoreUILoggingDelegateProtocol)?.logAlert(with: self.alertObject)
if self.isCancelled {
await self.dismissAlertView()
}
}
}
}
// Block navigations until this alert is removed.
MVMCoreNavigationHandler.shared()?.addNavigationOperation(blockingOperation)
}
}
public override func cancel() {
print("---\nTTTTTT alertOperation cancelled: \(self.description)\ncontroller: \(self.alDescription)\nobject: \(self.alertObject.alertModel.id)\n---")
super.cancel()
Task { @MainActor in
self.alertObject.alertDelegate?.alertCancelled(self.alertController)
@ -75,13 +101,22 @@ public class AlertOperation: MVMCoreOperation {
guard await properties.getIsDisplayed() else { return }
await withCheckedContinuation { continuation in
Task { @MainActor in
print("---\nTTTTTT alertOperation beginDismiss: \(self.description)\ncontroller: \(self.alDescription)\nobject: \(self.alertObject.alertModel.id)\n---")
MVMCoreNavigationHandler.shared()?.dismiss(alertController, animated: true, delegate: nil) {
print("---\nTTTTTT alertOperation endDismiss: \(self.description)\ncontroller: \(self.alDescription)\nobject: \(self.alertObject.alertModel.id)\n---")
continuation.resume()
}
}
}
}
public override func markAsFinished() {
blockingOperation?.markAsFinished()
super.markAsFinished()
}
// MARK: Observer Functions
private func observeForCurrentAlertViewDismissal() {
@ -93,8 +128,12 @@ public class AlertOperation: MVMCoreOperation {
await self.properties.set(displayed: visible)
Task { @MainActor in
if visible {
print("---\nTTTTTT alertOperation visible true: \(self.description)\ncontroller:\(self.alDescription)\nobject: \(self.alertObject.alertModel.id)\n---")
self.alertObject.alertDelegate?.alertShown(self.alertController)
} else {
print("---\nTTTTTT alertOperation visible false: \(self.description)\ncontroller:\(self.alDescription)\nobject: \(self.alertObject.alertModel.id)\n---")
self.alertObject.alertDelegate?.alertDismissed(self.alertController)
// Is visible was set to NO, meaning that the alertview is no longer visible.

View File

@ -148,7 +148,7 @@ public class TopNotificationHandler {
guard operation.isExecuting,
let operation = operation as? MVMCoreTopAlertOperation else { return false }
return operation.topAlertObject.persistent && operation.topAlertObject.type == type
}) as? MVMCoreTopAlertOperation == nil
}) as? MVMCoreTopAlertOperation != nil
}
/// Shows the top alert with the json.

View File

@ -30,6 +30,9 @@
@property (nonatomic, strong) dispatch_source_t timerSource;
// A reference to the show operation so it can be cancelled.
@property (nonatomic, weak) NSOperation *operation;
@end
@implementation MVMCoreTopAlertOperation
@ -177,7 +180,7 @@
}
UIView <MVMCoreTopAlertViewProtocol>*topAlertView = [[CoreUIObject sharedInstance].globalTopAlertDelegate getTopAlertView];
[topAlertView showWithTopAlertObject:self.topAlertObject animationDelegate:self completionHandler:^(BOOL finished) {
self.operation = [topAlertView showWithTopAlertObject:self.topAlertObject animationDelegate:self completionHandler:^(BOOL finished) {
self.displayed = YES;
if (self.isCancelled) {
@ -226,6 +229,8 @@
- (void)cancel {
[super cancel];
[self.operation cancel];
// Do nothing if animating.
if (!self.isAnimating) {

View File

@ -14,7 +14,7 @@
@optional
/// Show based on the object
- (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
- (nonnull NSOperation *)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;
/// Removes the notification
- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler;

View File

@ -141,7 +141,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
}
}
- (void)showAlertView:(nullable UIView *)view topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
- (nonnull NSOperation *)showAlertView:(nullable UIView *)view topAlertObject:(nonnull MVMCoreTopAlertObject *)topAlertObject completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
__weak typeof(self) weakSelf = self;
MVMCoreBlockOperation *operation = [MVMCoreBlockOperation blockOperationWithBlock:^(MVMCoreBlockOperation * _Nonnull operation) {
@ -176,6 +176,7 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
}];
}];
[[MVMCoreNavigationHandler sharedNavigationHandler] addNavigationOperation:operation];
return operation;
}
@ -190,11 +191,11 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
#pragma mark - MVMCoreTopAlertViewProtocol
- (void)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
- (nonnull NSOperation *)showWithTopAlertObject:(nullable MVMCoreTopAlertObject *)topAlertObject animationDelegate:(nonnull id <MVMCoreTopAlertAnimationDelegateProtocol>)animationDelegate completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {
self.animationDelegate = animationDelegate;
dispatch_async(dispatch_get_main_queue(), ^{
__block NSOperation *operation = nil;
[MVMCoreDispatchUtility performSyncBlockOnMainThread:^{
self.topAlertObject = topAlertObject;
self.topAlertClearspotView = nil;
@ -208,8 +209,9 @@ NSString * const MFAccTopAlertClosed = @"Top alert notification is closed.";
self.currentAlertOverridingStatusBar = YES;
[[MVMCoreUISplitViewController mainSplitViewController] setStatusBarBackgroundColor:statusBarColor style:statusBarStyle];
}
[self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler];
});
operation = [self showAlertView:view topAlertObject:topAlertObject completionHandler:completionHandler];
}];
return operation;
}
- (void)hideAlertView:(BOOL)forceful completionHandler:(void (^ __nullable)(BOOL finished))completionHandler {