mvm_core_ui/MVMCoreUI/Notification/NotificationContainerView.swift

114 lines
4.2 KiB
Swift

//
// MVMCoreUITopAlertView+Extension.swift
// MVMCoreUI
//
// Created by Scott Pfeil on 9/11/20.
// Copyright © 2020 Verizon Wireless. All rights reserved.
//
import Foundation
import MVMCore
/// A simple container view that shows and hides a notification.
public class NotificationContainerView: UIView {
public var currentModel: NotificationModel?
public var currentNotificationView: UIView?
lazy private var height = heightAnchor.constraint(equalToConstant: 0)
public init() {
super.init(frame: .zero)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
/// Posts a layout change with taking the arguments from the view following the AccessibilityProtocol.
private func updateAccessibilityForTopAlert(_ view: UIView) {
// Update accessibility with top alert
var accessibilityArgument: Any? = view
if let view = view as? AccessibilityProtocol {
accessibilityArgument = view.getAccessibilityLayoutChangedArgument()
}
UIAccessibility.post(notification: .layoutChanged, argument: accessibilityArgument)
}
}
extension NotificationContainerView: NotificationTransitionDelegateProtocol {
@MainActor
public func show(notification: UIView) async {
currentNotificationView?.removeFromSuperview()
addSubview(notification)
NSLayoutConstraint.constraintPinSubview(toSuperview: notification)
currentNotificationView = notification
if let conformer = notification as? MVMCoreViewProtocol {
conformer.updateView(bounds.width)
}
superview?.layoutIfNeeded()
await withCheckedContinuation { continuation in
UIView.animate(withDuration: 0.5) {
self.height.isActive = false
self.superview?.layoutIfNeeded()
} completion: { finished in
self.superview?.layoutIfNeeded()
self.updateAccessibilityForTopAlert(notification)
continuation.resume()
}
}
}
@MainActor
public func hide(notification: UIView) async {
// accessibility - below line added to notify VI user through voiceover user when the top alert is closed
UIAccessibility.post(notification: .screenChanged, argument: MVMCoreUIUtility.hardcodedString(withKey: "AccTopAlertClosed"))
await withCheckedContinuation { continuation in
UIView.animate(withDuration: 0.5) {
self.height.isActive = true
self.superview?.layoutIfNeeded()
} completion: { finished in
UIAccessibility.post(notification: .layoutChanged, argument: nil)
self.currentNotificationView?.removeFromSuperview()
self.currentNotificationView = nil
continuation.resume()
}
}
}
@MainActor
public func update(with model: NotificationModel, delegateObject: MVMCoreUIDelegateObject?) {
guard let currentModel = currentModel,
currentModel.type == model.type else { return }
guard let molecule = currentNotificationView as? MoleculeViewProtocol,
currentModel.molecule.moleculeName == model.molecule.moleculeName else {
// Log that we couldn't update.
if let errorObject = MVMCoreErrorObject(title: nil, message: nil, messageToLog: nil, code: ErrorCode.parsingJSON.rawValue, domain: ErrorDomainNative, location: "TopNotification update \(String(describing: model.type))") {
MVMCoreUILoggingHandler.addError(toLog: errorObject)
}
return
}
// Update molecule
molecule.reset()
molecule.set(with: model.molecule, delegateObject, nil)
(molecule as? MVMCoreViewProtocol)?.updateView(self.bounds.width)
}
}
extension NotificationContainerView: MVMCoreViewProtocol {
public func updateView(_ size: CGFloat) {
(currentNotificationView as? MVMCoreViewProtocol)?.updateView(size)
}
public func setupView() {
translatesAutoresizingMaskIntoConstraints = false
clipsToBounds = true
height.isActive = true
}
}