// // AlertViewController.swift // VDS // // Created by Matt Bruce on 6/24/24. // import Foundation import UIKit import Combine import VDSCoreTokens @objcMembers @objc(VDSAlertViewController) open class AlertViewController: UIViewController, Surfaceable { /// Set of Subscribers for any Publishers for this Control. open var subscribers = Set() //-------------------------------------------------- // MARK: - Private Properties //-------------------------------------------------- private var onClickSubscriber: AnyCancellable? { willSet { if let onClickSubscriber { onClickSubscriber.cancel() } } } //-------------------------------------------------- // MARK: - Public Properties //-------------------------------------------------- /// Current Surface and this is used to pass down to child objects that implement Surfacable open var surface: Surface = .light { didSet { updateView() }} open var presenter: UIView? { didSet { updateView() }} open var dialog: UIView! //-------------------------------------------------- // MARK: - Configuration //-------------------------------------------------- private let backgroundColorConfiguration = SurfaceColorConfiguration(VDSColor.backgroundPrimaryDark, VDSColor.backgroundPrimaryLight) //-------------------------------------------------- // MARK: - Lifecycle //-------------------------------------------------- open override func viewDidLoad() { super.viewDidLoad() isModalInPresentation = true setup() } open override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) UIAccessibility.post(notification: .screenChanged, argument: dialog) } private func dismiss() { dismiss(animated: true) { [weak self] in guard let self, let presenter else { return } UIAccessibility.post(notification: .layoutChanged, argument: presenter) } } open func setup() { guard let dialog else { return } view.accessibilityElements = [dialog] view.addSubview(dialog) // Activate constraints NSLayoutConstraint.activate([ // Constraints for the floating modal view dialog.centerXAnchor.constraint(equalTo: view.centerXAnchor), dialog.centerYAnchor.constraint(equalTo: view.centerYAnchor), dialog.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 10), dialog.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -10), dialog.topAnchor.constraint(greaterThanOrEqualTo: view.topAnchor, constant: 10), dialog.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor, constant: -10) ]) } open override func touchesBegan(_ touches: Set, with event: UIEvent?) { guard let touch = touches.first else { return } let location = touch.location(in: view) if dialog.frame.contains(location) { super.touchesBegan(touches, with: event) } else { dismiss() } } /// Used to make changes to the View based off a change events or from local properties. open func updateView() { view.backgroundColor = backgroundColorConfiguration.getColor(self).withAlphaComponent(0.3) if var dialog = dialog as? Surfaceable { dialog.surface = surface } } }