103 lines
3.6 KiB
Swift
103 lines
3.6 KiB
Swift
//
|
|
// AlertHandler.swift
|
|
// MVMCore
|
|
//
|
|
// Created by Scott Pfeil on 4/10/23.
|
|
// Copyright © 2023 myverizon. All rights reserved.
|
|
//
|
|
|
|
import MVMCore
|
|
|
|
public class AlertHandler {
|
|
|
|
/// Returns the handler stored in the CoreUIObject
|
|
public static func shared() -> Self {
|
|
return MVMCoreActionUtility.fatalClassCheck(object: CoreUIObject.sharedInstance()?.alertHandler)
|
|
}
|
|
|
|
/// The operation queue of alert operations.
|
|
private var queue = {
|
|
let queue = OperationQueue()
|
|
queue.maxConcurrentOperationCount = 1
|
|
return queue
|
|
}()
|
|
|
|
public init() {}
|
|
|
|
/// Returns if an alert is currently showing in the hierarchy, even if it is not the top presented view.
|
|
public func isAlertShowing() -> Bool {
|
|
return queue.operations.contains(where: { operation in
|
|
return !operation.isCancelled &&
|
|
!operation.isFinished &&
|
|
operation.isExecuting
|
|
})
|
|
}
|
|
|
|
/// Returns if a greedy alert is currently showing in the hierarchy, even if it is not the top presented view.
|
|
public func isGreedyAlertShowing() -> Bool {
|
|
return queue.operations.contains(where: { operation in
|
|
return !operation.isCancelled &&
|
|
!operation.isFinished &&
|
|
operation.isExecuting &&
|
|
(operation as? AlertOperation)?.alertObject.isGreedy ?? false
|
|
})
|
|
}
|
|
|
|
@MainActor
|
|
public func createAlertController(with alertModel: AlertModel) -> AlertController {
|
|
// ActionSheets are not supported on iPad interfaces without a source rect (i.e. a source element) which isn't currently supported for our generic handling.
|
|
// TODO: Find a way to support this.
|
|
var alertStyle = alertModel.style
|
|
if alertStyle == .actionSheet, UIDevice.current.userInterfaceIdiom != .phone {
|
|
alertStyle = .alert
|
|
}
|
|
|
|
// Create the alert. Adds the actions one by one.
|
|
let alertController = AlertController(title: alertModel.title, message: alertModel.message, preferredStyle: alertStyle)
|
|
for action in alertModel.actions {
|
|
alertController.addAction(action)
|
|
}
|
|
return alertController
|
|
}
|
|
|
|
/// Shows an alert using the alert object.
|
|
@MainActor
|
|
public func queueAlertToShow(with alertObject: AlertObject) -> UIAlertController {
|
|
|
|
// It's a greedy alert! Clear all alerts that are queued up and the one that is showing
|
|
if alertObject.isGreedy {
|
|
removeAllAlertViews()
|
|
}
|
|
|
|
let alertController = createAlertController(with: alertObject.alertModel)
|
|
let alertOperation = AlertOperation(with: alertController, alertObject: alertObject)
|
|
queue.addOperation(alertOperation)
|
|
return alertController
|
|
}
|
|
|
|
/// Cancel Alert with ID.
|
|
public func cancelAlert(with id: String) {
|
|
queue.operations.first { operation in
|
|
guard let operation = operation as? AlertOperation,
|
|
operation.alertObject.alertModel.id == id else { return false }
|
|
return true
|
|
}?.cancel()
|
|
}
|
|
|
|
/** Iterates through all scheduled alerts and cancels any that match the provided predicate.
|
|
* @param predicate The predicate block to decide whether to cancel an alert.
|
|
*/
|
|
public func cancelAlert(using predicate: ((AlertObject) -> Bool)) {
|
|
for case let operation as AlertOperation in queue.operations {
|
|
if predicate(operation.alertObject) {
|
|
operation.cancel()
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Cancels all current alerts
|
|
public func removeAllAlertViews() {
|
|
queue.cancelAllOperations()
|
|
}
|
|
}
|