mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
233 lines
12 KiB
Swift
233 lines
12 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import AsyncDisplayKit
|
|
|
|
public class NavigationController: NavigationControllerProxy, WindowContentController, UIGestureRecognizerDelegate {
|
|
private var _navigationBar: NavigationBar?
|
|
private var navigationTransitionCoordinator: NavigationTransitionCoordinator?
|
|
|
|
public override init() {
|
|
super.init()
|
|
self._navigationBar = NavigationBar()
|
|
self._navigationBar?.frame = CGRect(x: 0.0, y: 0.0, width: 320.0, height: 44.0)
|
|
self._navigationBar?.proxy = self.navigationBar as? NavigationBarProxy
|
|
self._navigationBar?.backPressed = { [weak self] in
|
|
if self?.viewControllers.count > 1 {
|
|
self?.popViewControllerAnimated(true)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
|
|
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
|
|
}
|
|
|
|
public required init(coder aDecoder: NSCoder) {
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
|
|
public override func loadView() {
|
|
super.loadView()
|
|
|
|
if let _navigationBar = self._navigationBar {
|
|
self.navigationBar.superview?.insertSubview(_navigationBar.view, aboveSubview: self.navigationBar)
|
|
}
|
|
self.navigationBar.removeFromSuperview()
|
|
|
|
self._navigationBar?.frame = navigationBarFrame(self.view.frame.size)
|
|
|
|
let panRecognizer = InteractiveTransitionGestureRecognizer(target: self, action: Selector("panGesture:"))
|
|
panRecognizer.delegate = self
|
|
panRecognizer.cancelsTouchesInView = true
|
|
self.view.addGestureRecognizer(panRecognizer)
|
|
|
|
if self.topViewController != nil {
|
|
self.topViewController?.view.frame = CGRect(origin: CGPoint(), size: self.view.frame.size)
|
|
}
|
|
}
|
|
|
|
func panGesture(recognizer: UIPanGestureRecognizer) {
|
|
switch recognizer.state {
|
|
case UIGestureRecognizerState.Began:
|
|
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
|
|
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
|
|
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
|
|
|
|
topController.viewWillDisappear(true)
|
|
let topView = topController.view
|
|
bottomController.viewWillAppear(true)
|
|
let bottomView = bottomController.view
|
|
|
|
let navigationTransitionCoordinator = NavigationTransitionCoordinator(container: self.view, topView: topView, bottomView: bottomView, navigationBar: self._navigationBar!)
|
|
self.navigationTransitionCoordinator = navigationTransitionCoordinator
|
|
|
|
self._navigationBar?.beginInteractivePopProgress(bottomController.navigationItem, evenMorePreviousItem: self.viewControllers.count >= 3 ? (self.viewControllers[self.viewControllers.count - 3] as UIViewController).navigationItem : nil)
|
|
}
|
|
case UIGestureRecognizerState.Changed:
|
|
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
|
|
let translation = recognizer.translationInView(self.view).x
|
|
navigationTransitionCoordinator.progress = max(0.0, min(1.0, translation / self.view.frame.width))
|
|
}
|
|
case UIGestureRecognizerState.Ended:
|
|
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
|
|
let velocity = recognizer.velocityInView(self.view).x
|
|
|
|
if velocity > 1000 || navigationTransitionCoordinator.progress > 0.2 {
|
|
navigationTransitionCoordinator.animateCompletion(velocity, completion: {
|
|
self.navigationTransitionCoordinator = nil
|
|
|
|
self._navigationBar?.endInteractivePopProgress()
|
|
|
|
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
|
|
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
|
|
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
|
|
|
|
topController.setIgnoreAppearanceMethodInvocations(true)
|
|
bottomController.setIgnoreAppearanceMethodInvocations(true)
|
|
self.popViewControllerAnimated(false)
|
|
topController.setIgnoreAppearanceMethodInvocations(false)
|
|
bottomController.setIgnoreAppearanceMethodInvocations(false)
|
|
|
|
topController.viewDidDisappear(true)
|
|
bottomController.viewDidAppear(true)
|
|
}
|
|
})
|
|
}
|
|
else {
|
|
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
|
|
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
|
|
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
|
|
|
|
topController.viewWillAppear(true)
|
|
bottomController.viewWillDisappear(true)
|
|
}
|
|
|
|
navigationTransitionCoordinator.animateCancel({
|
|
self.navigationTransitionCoordinator = nil
|
|
|
|
self._navigationBar?.endInteractivePopProgress()
|
|
|
|
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
|
|
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
|
|
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
|
|
|
|
topController.viewDidAppear(true)
|
|
bottomController.viewDidDisappear(true)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
case .Cancelled:
|
|
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
|
|
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
|
|
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
|
|
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
|
|
|
|
topController.viewWillAppear(true)
|
|
bottomController.viewWillDisappear(true)
|
|
}
|
|
|
|
navigationTransitionCoordinator.animateCancel({
|
|
self.navigationTransitionCoordinator = nil
|
|
|
|
if self.viewControllers.count >= 2 && self.navigationTransitionCoordinator == nil {
|
|
let topController = self.viewControllers[self.viewControllers.count - 1] as UIViewController
|
|
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
|
|
|
|
topController.viewDidAppear(true)
|
|
bottomController.viewDidDisappear(true)
|
|
}
|
|
})
|
|
}
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
public override func pushViewController(viewController: UIViewController, animated: Bool) {
|
|
var controllers = self.viewControllers
|
|
controllers.append(viewController)
|
|
self.setViewControllers(controllers, animated: animated)
|
|
}
|
|
|
|
public override func popViewControllerAnimated(animated: Bool) -> UIViewController? {
|
|
var controller: UIViewController?
|
|
var controllers = self.viewControllers
|
|
if controllers.count != 0 {
|
|
controller = controllers[controllers.count - 1] as UIViewController
|
|
controllers.removeAtIndex(controllers.count - 1)
|
|
self.setViewControllers(controllers, animated: animated)
|
|
}
|
|
return controller
|
|
}
|
|
|
|
public override func setViewControllers(viewControllers: [UIViewController], animated: Bool) {
|
|
if viewControllers.count > 0 {
|
|
let topViewController = viewControllers[viewControllers.count - 1] as UIViewController
|
|
|
|
if let controller = topViewController as? WindowContentController {
|
|
controller.setViewSize(self.view.bounds.size, duration: 0.0)
|
|
} else {
|
|
topViewController.view.frame = CGRect(origin: CGPoint(), size: self.view.bounds.size)
|
|
}
|
|
}
|
|
|
|
super.setViewControllers(viewControllers, animated: animated)
|
|
}
|
|
|
|
private func navigationBarFrame(size: CGSize) -> CGRect {
|
|
let condensedBar = (size.height < size.width || size.height <= 320.0) && size.height < 768.0
|
|
return CGRect(x: 0.0, y: 0.0, width: size.width, height: 20.0 + (size.height >= size.width ? 44.0 : 32.0))
|
|
}
|
|
|
|
public func setViewSize(toSize: CGSize, duration: NSTimeInterval) {
|
|
if duration > DBL_EPSILON {
|
|
animateRotation(self.view, toFrame: CGRect(x: 0.0, y: 0.0, width: toSize.width, height: toSize.height), duration: duration)
|
|
}
|
|
else {
|
|
self.view.frame = CGRect(x: 0.0, y: 0.0, width: toSize.width, height: toSize.height)
|
|
}
|
|
|
|
if duration > DBL_EPSILON {
|
|
animateRotation(self._navigationBar, toFrame: self.navigationBarFrame(toSize), duration: duration)
|
|
}
|
|
else {
|
|
self._navigationBar?.frame = self.navigationBarFrame(toSize)
|
|
}
|
|
|
|
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
|
|
//navigationTransitionView.frame = CGRectMake(0.0, 0.0, toSize.width, toSize.height)
|
|
|
|
if self.viewControllers.count >= 2 {
|
|
let bottomController = self.viewControllers[self.viewControllers.count - 2] as UIViewController
|
|
|
|
if let controller = bottomController as? WindowContentController {
|
|
controller.setViewSize(toSize, duration: duration)
|
|
}
|
|
bottomController.view.frame = CGRectMake(0.0, 0.0, toSize.width, toSize.height)
|
|
}
|
|
}
|
|
|
|
if let topViewController = self.topViewController {
|
|
if let controller = topViewController as? WindowContentController {
|
|
controller.setViewSize(toSize, duration: duration)
|
|
} else {
|
|
topViewController.view.frame = CGRectMake(0.0, 0.0, toSize.width, toSize.height)
|
|
}
|
|
}
|
|
|
|
if let navigationTransitionCoordinator = self.navigationTransitionCoordinator {
|
|
navigationTransitionCoordinator.updateProgress()
|
|
}
|
|
}
|
|
|
|
public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
return false
|
|
}
|
|
|
|
public func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailByGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
return true
|
|
}
|
|
}
|