element-ios/Riot/Modules/SlidingModal/SlidingModalPresentationCon...

98 lines
3.8 KiB
Swift

/*
Copyright 2019-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/
import UIKit
/// `SlidingModalPresentationController` handles sliding transition presentation life cycle.
final class SlidingModalPresentationController: UIPresentationController {
// MARK: - Properties
private var slidingModalContainerView: SlidingModalContainerView? {
return self.containerView?.subviews.first(where: { (view) -> Bool in
view is SlidingModalContainerView
}) as? SlidingModalContainerView
}
// MARK: - Setup
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
}
// MARK: - Life cycle
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
if let slidingModalPresentable = self.presentedViewController as? SlidingModalPresentable, let slidingModalContainerView = self.slidingModalContainerView {
let slidingModalContainerViewContentViewWidth = slidingModalContainerView.contentViewWidthFittingSize(size)
let presentableHeight = slidingModalPresentable.layoutHeightFittingWidth(slidingModalContainerViewContentViewWidth)
slidingModalContainerView.updateContentViewMaxHeight(presentableHeight)
}
coordinator.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) -> Void in
self.slidingModalContainerView?.updateContentViewLayout()
}, completion: { _ in
})
}
override func presentationTransitionWillBegin() {
guard let coordinator = presentedViewController.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: { [weak self] _ in
// Update status bar appearance of presented view controller (if presenting view controller allowed it, see `modalPresentationCapturesStatusBarAppearance` property)
self?.presentedViewController.setNeedsStatusBarAppearanceUpdate()
}, completion: nil)
}
override func presentationTransitionDidEnd(_ completed: Bool) {
self.slidingModalContainerView?.delegate = self
}
override func dismissalTransitionWillBegin() {
guard let coordinator = presentedViewController.transitionCoordinator else {
return
}
coordinator.animate(alongsideTransition: { [weak self] _ -> Void in
// Update status bar appearance of presenting view controller
self?.presentingViewController.setNeedsStatusBarAppearanceUpdate()
}, completion: nil)
}
override func dismissalTransitionDidEnd(_ completed: Bool) {
if completed {
self.slidingModalContainerView?.removeFromSuperview()
}
}
}
// MARK: - SlidingModalContainerViewDelegate
extension SlidingModalPresentationController: SlidingModalContainerViewDelegate {
func slidingModalContainerViewDidTapBackground(_ view: SlidingModalContainerView) {
let isDismissOnBackgroundTapAllowed: Bool
if let slidingModalPresentable = self.presentedViewController as? SlidingModalPresentable {
isDismissOnBackgroundTapAllowed = slidingModalPresentable.allowsDismissOnBackgroundTap()
} else {
isDismissOnBackgroundTapAllowed = true
}
if isDismissOnBackgroundTapAllowed {
self.presentedViewController.dismiss(animated: true, completion: nil)
}
}
}