// // API.swift // Duckable // // Created by Shadowfacts on 11/7/22. // import UIKit @MainActor public protocol DuckableViewController: UIViewController { func duckableViewControllerShouldDuck() -> DuckAttemptAction func duckableViewControllerMayAttemptToDuck() func duckableViewControllerWillAnimateDuck(withDuration duration: CGFloat, afterDelay delay: CGFloat) func duckableViewControllerDidFinishAnimatingDuck() } extension DuckableViewController { public func duckableViewControllerShouldDuck() -> DuckAttemptAction { .duck } public func duckableViewControllerMayAttemptToDuck() {} public func duckableViewControllerWillAnimateDuck(withDuration duration: CGFloat, afterDelay delay: CGFloat) {} public func duckableViewControllerDidFinishAnimatingDuck() {} } public enum DuckAttemptAction { case duck case dismiss case block } extension UIViewController { @available(iOS 16.0, *) public func presentDuckable(_ viewController: DuckableViewController, animated: Bool, isDucked: Bool = false) -> Bool { var cur: UIViewController? = self while let vc = cur { if let container = vc as? DuckableContainerViewController { container.presentDuckable(viewController, animated: animated, isDucked: isDucked, completion: nil) return true } else { cur = vc.parent } } return false } }