mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-08 05:55:13 +00:00
Manage global overlay controllers via NavigationController
This commit is contained in:
@@ -3,7 +3,7 @@ import UIKit
|
||||
import AsyncDisplayKit
|
||||
import SwiftSignalKit
|
||||
|
||||
private func isViewVisibleInHierarchy(_ view: UIView, _ initial: Bool = true) -> Bool {
|
||||
func isViewVisibleInHierarchy(_ view: UIView, _ initial: Bool = true) -> Bool {
|
||||
guard let window = view.window else {
|
||||
return false
|
||||
}
|
||||
@@ -182,6 +182,7 @@ final class GlobalOverlayPresentationContext {
|
||||
self.readyChanged(wasReady: wasReady)
|
||||
} else if self.ready {
|
||||
for controller in self.controllers {
|
||||
transition.updateFrame(node: controller.displayNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
controller.containerLayoutUpdated(layout, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,26 +19,6 @@ private func getFirstResponder(_ view: UIView) -> UIView? {
|
||||
}
|
||||
}
|
||||
|
||||
private func isViewVisibleInHierarchy(_ view: UIView, _ initial: Bool = true) -> Bool {
|
||||
guard let window = view.window else {
|
||||
return false
|
||||
}
|
||||
if view.isHidden || view.alpha == 0.0 {
|
||||
return false
|
||||
}
|
||||
if view.superview === window {
|
||||
return true
|
||||
} else if let superview = view.superview {
|
||||
if initial && view.frame.minY >= superview.frame.height {
|
||||
return false
|
||||
} else {
|
||||
return isViewVisibleInHierarchy(superview, false)
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
class KeyboardManager {
|
||||
private let host: StatusBarHost
|
||||
|
||||
|
||||
@@ -92,6 +92,19 @@ private enum RootContainer {
|
||||
case split(NavigationSplitContainer)
|
||||
}
|
||||
|
||||
private final class GlobalOverlayContainerParent: ASDisplayNode {
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if let subnodes = self.subnodes {
|
||||
for node in subnodes.reversed() {
|
||||
if let result = node.view.hitTest(point, with: event) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
open class NavigationController: UINavigationController, ContainableController, UIGestureRecognizerDelegate {
|
||||
public var isOpaqueWhenInOverlay: Bool = true
|
||||
public var blocksBackgroundWhenInOverlay: Bool = true
|
||||
@@ -128,6 +141,8 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
private var rootModalFrame: NavigationModalFrame?
|
||||
private var modalContainers: [NavigationModalContainer] = []
|
||||
private var overlayContainers: [NavigationOverlayContainer] = []
|
||||
private var globalOverlayContainers: [NavigationOverlayContainer] = []
|
||||
private var globalOverlayContainerParent: GlobalOverlayContainerParent?
|
||||
private var validLayout: ContainerViewLayout?
|
||||
private var validStatusBarStyle: NavigationStatusBarStyle?
|
||||
private var validStatusBarHidden: Bool = false
|
||||
@@ -239,6 +254,18 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
supportedOrientations = supportedOrientations.intersection(controller.supportedOrientations)
|
||||
}
|
||||
}
|
||||
for overlayContrainer in self.globalOverlayContainers {
|
||||
let controller = overlayContrainer.controller
|
||||
if controller.lockOrientation {
|
||||
if let lockedOrientation = controller.lockedOrientation {
|
||||
supportedOrientations = supportedOrientations.intersection(ViewControllerSupportedOrientations(regularSize: lockedOrientation, compactSize: lockedOrientation))
|
||||
} else {
|
||||
supportedOrientations = supportedOrientations.intersection(ViewControllerSupportedOrientations(regularSize: currentOrientationToLock, compactSize: currentOrientationToLock))
|
||||
}
|
||||
} else {
|
||||
supportedOrientations = supportedOrientations.intersection(controller.supportedOrientations)
|
||||
}
|
||||
}
|
||||
return supportedOrientations
|
||||
}
|
||||
|
||||
@@ -286,6 +313,35 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
}
|
||||
|
||||
var overlayLayout = layout
|
||||
|
||||
if let globalOverlayContainerParent = self.globalOverlayContainerParent {
|
||||
let portraitSize = CGSize(width: min(layout.size.width, layout.size.height), height: max(layout.size.width, layout.size.height))
|
||||
let screenSize = UIScreen.main.bounds.size
|
||||
let portraitScreenSize = CGSize(width: min(screenSize.width, screenSize.height), height: max(screenSize.width, screenSize.height))
|
||||
if portraitSize.width != portraitScreenSize.width || portraitSize.height != portraitScreenSize.height {
|
||||
if globalOverlayContainerParent.view.superview != self.displayNode.view {
|
||||
self.displayNode.addSubnode(globalOverlayContainerParent)
|
||||
}
|
||||
|
||||
overlayLayout.size.height = overlayLayout.size.height - (layout.inputHeight ?? 0.0)
|
||||
overlayLayout.inputHeight = nil
|
||||
overlayLayout.inputHeightIsInteractivellyChanging = false
|
||||
} else if layout.inputHeight == nil {
|
||||
if globalOverlayContainerParent.view.superview != self.displayNode.view {
|
||||
self.displayNode.addSubnode(globalOverlayContainerParent)
|
||||
}
|
||||
} else {
|
||||
if let statusBarHost = self.statusBarHost, let keyboardWindow = statusBarHost.keyboardWindow, let keyboardView = statusBarHost.keyboardView, !keyboardView.frame.height.isZero, isViewVisibleInHierarchy(keyboardView) {
|
||||
if globalOverlayContainerParent.view.superview != keyboardWindow {
|
||||
keyboardWindow.addSubnode(globalOverlayContainerParent)
|
||||
}
|
||||
} else if globalOverlayContainerParent.view.superview !== self.displayNode.view {
|
||||
self.displayNode.addSubnode(globalOverlayContainerParent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let globalScrollToTopNode = self.globalScrollToTopNode {
|
||||
globalScrollToTopNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -1.0), size: CGSize(width: layout.size.width, height: 1.0))
|
||||
}
|
||||
@@ -301,6 +357,10 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self.inCallStatusBar?.frame = inCallStatusBarFrame
|
||||
}
|
||||
|
||||
if let globalOverlayContainerParent = self.globalOverlayContainerParent {
|
||||
transition.updateFrame(node: globalOverlayContainerParent, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
}
|
||||
|
||||
let navigationLayout = makeNavigationLayout(mode: self.mode, layout: layout, controllers: self._viewControllers)
|
||||
|
||||
var transition = transition
|
||||
@@ -375,8 +435,51 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
}
|
||||
self.modalContainers = modalContainers
|
||||
|
||||
var previousOverlayContainer: NavigationOverlayContainer?
|
||||
var topVisibleOverlayContainerWithStatusBar: NavigationOverlayContainer?
|
||||
|
||||
var previousGlobalOverlayContainer: NavigationOverlayContainer?
|
||||
for i in (0 ..< self.globalOverlayContainers.count).reversed() {
|
||||
let overlayContainer = self.globalOverlayContainers[i]
|
||||
|
||||
let containerTransition: ContainedViewLayoutTransition
|
||||
if overlayContainer.supernode == nil {
|
||||
containerTransition = .immediate
|
||||
} else {
|
||||
containerTransition = transition
|
||||
}
|
||||
|
||||
containerTransition.updateFrame(node: overlayContainer, frame: CGRect(origin: CGPoint(), size: overlayLayout.size))
|
||||
overlayContainer.update(layout: overlayLayout, transition: containerTransition)
|
||||
|
||||
if overlayContainer.supernode == nil && overlayContainer.isReady {
|
||||
if let previousGlobalOverlayContainer = previousGlobalOverlayContainer {
|
||||
self.globalOverlayContainerParent?.insertSubnode(overlayContainer, belowSubnode: previousGlobalOverlayContainer)
|
||||
} else {
|
||||
self.globalOverlayContainerParent?.addSubnode(overlayContainer)
|
||||
}
|
||||
overlayContainer.transitionIn()
|
||||
}
|
||||
|
||||
if overlayContainer.supernode != nil {
|
||||
previousGlobalOverlayContainer = overlayContainer
|
||||
let controllerStatusBarStyle = overlayContainer.controller.statusBar.statusBarStyle
|
||||
switch controllerStatusBarStyle {
|
||||
case .Black, .White, .Hide:
|
||||
if topVisibleOverlayContainerWithStatusBar == nil {
|
||||
topVisibleOverlayContainerWithStatusBar = overlayContainer
|
||||
}
|
||||
if case .Hide = controllerStatusBarStyle {
|
||||
statusBarHidden = true
|
||||
} else {
|
||||
statusBarHidden = overlayContainer.controller.statusBar.alpha.isZero
|
||||
}
|
||||
case .Ignore:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var previousOverlayContainer: NavigationOverlayContainer?
|
||||
for i in (0 ..< self.overlayContainers.count).reversed() {
|
||||
let overlayContainer = self.overlayContainers[i]
|
||||
|
||||
@@ -395,7 +498,9 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
self.displayNode.insertSubnode(overlayContainer, belowSubnode: previousOverlayContainer)
|
||||
} else if let globalScrollToTopNode = self.globalScrollToTopNode {
|
||||
self.displayNode.insertSubnode(overlayContainer, belowSubnode: globalScrollToTopNode)
|
||||
} else {
|
||||
} else if let globalOverlayContainerParent = self.globalOverlayContainerParent {
|
||||
self.displayNode.insertSubnode(overlayContainer, belowSubnode: globalOverlayContainerParent)
|
||||
}else {
|
||||
self.displayNode.addSubnode(overlayContainer)
|
||||
}
|
||||
overlayContainer.transitionIn()
|
||||
@@ -814,6 +919,10 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
})
|
||||
self.displayNode.addSubnode(globalScrollToTopNode)
|
||||
self.globalScrollToTopNode = globalScrollToTopNode
|
||||
|
||||
let globalOverlayContainerParent = GlobalOverlayContainerParent()
|
||||
self.displayNode.addSubnode(globalOverlayContainerParent)
|
||||
self.globalOverlayContainerParent = globalOverlayContainerParent
|
||||
}
|
||||
|
||||
public func pushViewController(_ controller: ViewController) {
|
||||
@@ -957,12 +1066,23 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
for i in 0 ..< strongSelf.overlayContainers.count {
|
||||
let overlayContainer = strongSelf.overlayContainers[i]
|
||||
if overlayContainer.controller === controller {
|
||||
overlayContainer.removeFromSupernode()
|
||||
strongSelf.overlayContainers.remove(at: i)
|
||||
break
|
||||
if inGlobal {
|
||||
for i in 0 ..< strongSelf.globalOverlayContainers.count {
|
||||
let overlayContainer = strongSelf.globalOverlayContainers[i]
|
||||
if overlayContainer.controller === controller {
|
||||
overlayContainer.removeFromSupernode()
|
||||
strongSelf.globalOverlayContainers.remove(at: i)
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i in 0 ..< strongSelf.overlayContainers.count {
|
||||
let overlayContainer = strongSelf.overlayContainers[i]
|
||||
if overlayContainer.controller === controller {
|
||||
overlayContainer.removeFromSupernode()
|
||||
strongSelf.overlayContainers.remove(at: i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if let layout = strongSelf.validLayout {
|
||||
@@ -976,7 +1096,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
||||
strongSelf.updateContainers(layout: layout, transition: transition)
|
||||
}
|
||||
})
|
||||
self.overlayContainers.append(container)
|
||||
if inGlobal {
|
||||
self.globalOverlayContainers.append(container)
|
||||
} else {
|
||||
self.overlayContainers.append(container)
|
||||
}
|
||||
container.isReadyUpdated = { [weak self, weak container] in
|
||||
guard let strongSelf = self, let container = container else {
|
||||
return
|
||||
|
||||
@@ -1106,6 +1106,12 @@ public class Window1 {
|
||||
}
|
||||
|
||||
public func presentInGlobalOverlay(_ controller: ContainableController) {
|
||||
if let controller = controller as? ViewController {
|
||||
if let navigationController = self._rootController as? NavigationController {
|
||||
navigationController.presentOverlay(controller: controller, inGlobal: true)
|
||||
return
|
||||
}
|
||||
}
|
||||
self.overlayPresentationContext.present(controller)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user