mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Refactor PasswordSetupUI, PassportUI, GalleryUI and related modules
This commit is contained in:
531
submodules/LegacyUI/Sources/LegacyController.swift
Normal file
531
submodules/LegacyUI/Sources/LegacyController.swift
Normal file
@@ -0,0 +1,531 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import LegacyComponents
|
||||
import TelegramPresentationData
|
||||
|
||||
public enum LegacyControllerPresentation {
|
||||
case custom
|
||||
case modal(animateIn: Bool)
|
||||
case navigation
|
||||
}
|
||||
|
||||
private func passControllerAppearanceAnimated(in: Bool, presentation: LegacyControllerPresentation) -> Bool {
|
||||
switch presentation {
|
||||
case let .modal(animateIn):
|
||||
if `in` {
|
||||
return animateIn
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private final class LegacyComponentsOverlayWindowManagerImpl: NSObject, LegacyComponentsOverlayWindowManager {
|
||||
private weak var contentController: UIViewController?
|
||||
private weak var parentController: ViewController?
|
||||
private var controller: LegacyController?
|
||||
private var boundController = false
|
||||
|
||||
init(parentController: ViewController?, theme: PresentationTheme?) {
|
||||
self.parentController = parentController
|
||||
self.controller = LegacyController(presentation: .custom, theme: theme)
|
||||
|
||||
super.init()
|
||||
|
||||
if let parentController = parentController {
|
||||
if parentController.statusBar.statusBarStyle == .Hide {
|
||||
self.controller?.statusBar.statusBarStyle = parentController.statusBar.statusBarStyle
|
||||
}
|
||||
if parentController.view.disablesInteractiveTransitionGestureRecognizer {
|
||||
self.controller?.view.disablesInteractiveTransitionGestureRecognizer = true
|
||||
}
|
||||
self.controller?.view.frame = parentController.view.bounds
|
||||
}
|
||||
}
|
||||
|
||||
func managesWindow() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func bindController(_ controller: UIViewController!) {
|
||||
self.contentController = controller
|
||||
if controller.prefersStatusBarHidden {
|
||||
self.controller?.statusBar.statusBarStyle = .Hide
|
||||
}
|
||||
|
||||
controller.state_setNeedsStatusBarAppearanceUpdate({ [weak self, weak controller] in
|
||||
if let parentController = self?.parentController, let controller = controller {
|
||||
if parentController.statusBar.statusBarStyle != .Hide && !controller.prefersStatusBarHidden {
|
||||
self?.controller?.statusBar.statusBarStyle = StatusBarStyle(systemStyle: controller.preferredStatusBarStyle)
|
||||
}
|
||||
}
|
||||
})
|
||||
if let parentController = self.parentController {
|
||||
if parentController.statusBar.statusBarStyle != .Hide && !controller.prefersStatusBarHidden {
|
||||
self.controller?.statusBar.statusBarStyle = StatusBarStyle(systemStyle: controller.preferredStatusBarStyle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func context() -> LegacyComponentsContext! {
|
||||
return self.controller?.context
|
||||
}
|
||||
|
||||
func setHidden(_ hidden: Bool, window: UIWindow!) {
|
||||
if hidden {
|
||||
self.controller?.dismiss()
|
||||
self.controller = nil
|
||||
} else if let contentController = self.contentController, let parentController = self.parentController, let controller = self.controller {
|
||||
if !self.boundController {
|
||||
controller.bind(controller: contentController)
|
||||
self.boundController = true
|
||||
}
|
||||
parentController.present(controller, in: .window(.root))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class LegacyControllerContext: NSObject, LegacyComponentsContext {
|
||||
public private(set) weak var controller: ViewController?
|
||||
private let theme: PresentationTheme?
|
||||
|
||||
public init(controller: ViewController?, theme: PresentationTheme?) {
|
||||
self.controller = controller
|
||||
self.theme = theme
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
public func fullscreenBounds() -> CGRect {
|
||||
if let controller = self.controller {
|
||||
return controller.view.bounds
|
||||
} else {
|
||||
return CGRect()
|
||||
}
|
||||
}
|
||||
|
||||
public func keyCommandController() -> TGKeyCommandController! {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func rootCallStatusBarHidden() -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public func statusBarFrame() -> CGRect {
|
||||
return legacyComponentsApplication!.statusBarFrame
|
||||
}
|
||||
|
||||
public func isStatusBarHidden() -> Bool {
|
||||
if let controller = self.controller {
|
||||
return controller.statusBar.isHidden
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
public func setStatusBarHidden(_ hidden: Bool, with animation: UIStatusBarAnimation) {
|
||||
if let controller = self.controller {
|
||||
controller.statusBar.isHidden = hidden
|
||||
self.updateDeferScreenEdgeGestures()
|
||||
}
|
||||
}
|
||||
|
||||
public func forceSetStatusBarHidden(_ hidden: Bool, with animation: UIStatusBarAnimation) {
|
||||
if let controller = self.controller {
|
||||
controller.statusBar.isHidden = hidden
|
||||
}
|
||||
}
|
||||
|
||||
public func statusBarStyle() -> UIStatusBarStyle {
|
||||
if let controller = self.controller {
|
||||
switch controller.statusBar.statusBarStyle {
|
||||
case .Black:
|
||||
return .default
|
||||
case .White:
|
||||
return .lightContent
|
||||
default:
|
||||
return .default
|
||||
}
|
||||
} else {
|
||||
return .default
|
||||
}
|
||||
}
|
||||
|
||||
public func setStatusBarStyle(_ statusBarStyle: UIStatusBarStyle, animated: Bool) {
|
||||
if let controller = self.controller {
|
||||
switch statusBarStyle {
|
||||
case .default:
|
||||
controller.statusBar.statusBarStyle = .Black
|
||||
case .lightContent:
|
||||
controller.statusBar.statusBarStyle = .White
|
||||
default:
|
||||
controller.statusBar.statusBarStyle = .Black
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func forceStatusBarAppearanceUpdate() {
|
||||
}
|
||||
|
||||
public func currentlyInSplitView() -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public func currentSizeClass() -> UIUserInterfaceSizeClass {
|
||||
if let controller = self.controller as? LegacyController, let validLayout = controller.validLayout {
|
||||
if case .regular = validLayout.metrics.widthClass, case .regular = validLayout.metrics.heightClass {
|
||||
return .regular
|
||||
}
|
||||
}
|
||||
return .compact
|
||||
}
|
||||
|
||||
public func currentHorizontalSizeClass() -> UIUserInterfaceSizeClass {
|
||||
if let controller = self.controller as? LegacyController, let validLayout = controller.validLayout {
|
||||
if case .regular = validLayout.metrics.widthClass {
|
||||
return .regular
|
||||
}
|
||||
}
|
||||
return .compact
|
||||
}
|
||||
|
||||
public func currentVerticalSizeClass() -> UIUserInterfaceSizeClass {
|
||||
if let controller = self.controller as? LegacyController, let validLayout = controller.validLayout {
|
||||
if case .regular = validLayout.metrics.heightClass {
|
||||
return .regular
|
||||
}
|
||||
}
|
||||
return .compact
|
||||
}
|
||||
|
||||
public func sizeClassSignal() -> SSignal! {
|
||||
if let controller = self.controller as? LegacyController, let validLayout = controller.validLayout {
|
||||
if case .regular = validLayout.metrics.heightClass {
|
||||
return SSignal.single(UIUserInterfaceSizeClass.regular.rawValue as NSNumber)
|
||||
}
|
||||
}
|
||||
if let controller = self.controller as? LegacyController, controller.enableSizeClassSignal {
|
||||
//return controller.sizeClassSignal
|
||||
}
|
||||
return SSignal.single(UIUserInterfaceSizeClass.compact.rawValue as NSNumber)
|
||||
}
|
||||
|
||||
public func canOpen(_ url: URL!) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
public func open(_ url: URL!) {
|
||||
}
|
||||
|
||||
public func serverMediaData(forAssetUrl url: String!) -> [AnyHashable : Any]! {
|
||||
return nil
|
||||
}
|
||||
|
||||
public func presentActionSheet(_ actions: [LegacyComponentsActionSheetAction]!, view: UIView!, completion: ((LegacyComponentsActionSheetAction?) -> Void)!) {
|
||||
|
||||
}
|
||||
|
||||
public func presentActionSheet(_ actions: [LegacyComponentsActionSheetAction]!, view: UIView!, sourceRect: (() -> CGRect)!, completion: ((LegacyComponentsActionSheetAction?) -> Void)!) {
|
||||
|
||||
}
|
||||
|
||||
public func makeOverlayWindowManager() -> LegacyComponentsOverlayWindowManager! {
|
||||
return LegacyComponentsOverlayWindowManagerImpl(parentController: self.controller, theme: self.theme)
|
||||
}
|
||||
|
||||
public func applicationStatusBarAlpha() -> CGFloat {
|
||||
if let controller = self.controller {
|
||||
return controller.statusBar.alpha
|
||||
}
|
||||
return 0.0
|
||||
}
|
||||
|
||||
public func setApplicationStatusBarAlpha(_ alpha: CGFloat) {
|
||||
if let controller = self.controller {
|
||||
controller.statusBar.alpha = alpha
|
||||
self.updateDeferScreenEdgeGestures()
|
||||
}
|
||||
}
|
||||
|
||||
private func updateDeferScreenEdgeGestures() {
|
||||
if let controller = self.controller {
|
||||
if controller.statusBar.isHidden || controller.statusBar.alpha.isZero {
|
||||
controller.deferScreenEdgeGestures = [.top]
|
||||
} else {
|
||||
controller.deferScreenEdgeGestures = []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func animateApplicationStatusBarAppearance(_ statusBarAnimation: Int32, delay: TimeInterval, duration: TimeInterval, completion: (() -> Void)!) {
|
||||
completion?()
|
||||
}
|
||||
|
||||
public func animateApplicationStatusBarAppearance(_ statusBarAnimation: Int32, duration: TimeInterval, completion: (() -> Void)!) {
|
||||
self.animateApplicationStatusBarAppearance(statusBarAnimation, delay: 0.0, duration: duration, completion: completion)
|
||||
}
|
||||
|
||||
public func animateApplicationStatusBarStyleTransition(withDuration duration: TimeInterval) {
|
||||
}
|
||||
|
||||
public func safeAreaInset() -> UIEdgeInsets {
|
||||
if let controller = self.controller as? LegacyController, let validLayout = controller.validLayout {
|
||||
var safeInsets = validLayout.safeInsets
|
||||
if safeInsets.top.isEqual(to: 44.0) {
|
||||
safeInsets.bottom = 34.0
|
||||
}
|
||||
if validLayout.intrinsicInsets.bottom.isEqual(to: 21.0) {
|
||||
safeInsets.bottom = 21.0
|
||||
}
|
||||
return safeInsets
|
||||
}
|
||||
return UIEdgeInsets()
|
||||
}
|
||||
|
||||
public func prefersLightStatusBar() -> Bool {
|
||||
if let controller = self.controller {
|
||||
switch controller.statusBar.statusBarStyle {
|
||||
case .Black:
|
||||
return false
|
||||
case .White:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class LegacyController: ViewController, PresentableController {
|
||||
public private(set) var legacyController: UIViewController!
|
||||
private let presentation: LegacyControllerPresentation
|
||||
|
||||
private var controllerNode: LegacyControllerNode {
|
||||
return self.displayNode as! LegacyControllerNode
|
||||
}
|
||||
|
||||
private var contextImpl: LegacyControllerContext!
|
||||
public var context: LegacyComponentsContext {
|
||||
return self.contextImpl!
|
||||
}
|
||||
|
||||
fileprivate var validLayout: ContainerViewLayout?
|
||||
|
||||
public var controllerLoaded: (() -> Void)?
|
||||
public var presentationCompleted: (() -> Void)?
|
||||
|
||||
private let sizeClass: SVariable = SVariable()
|
||||
public var enableSizeClassSignal: Bool = false
|
||||
public var sizeClassSignal: SSignal {
|
||||
return self.sizeClass.signal()!
|
||||
}
|
||||
private var enableContainerLayoutUpdates = false
|
||||
|
||||
public var disposables = DisposableSet()
|
||||
|
||||
public init(presentation: LegacyControllerPresentation, theme: PresentationTheme? = nil, strings: PresentationStrings? = nil, initialLayout: ContainerViewLayout? = nil) {
|
||||
self.sizeClass.set(SSignal.single(UIUserInterfaceSizeClass.compact.rawValue as NSNumber))
|
||||
self.presentation = presentation
|
||||
self.validLayout = initialLayout
|
||||
|
||||
let navigationBarPresentationData: NavigationBarPresentationData?
|
||||
if let theme = theme, let strings = strings, case .navigation = presentation {
|
||||
navigationBarPresentationData = NavigationBarPresentationData(theme: NavigationBarTheme(rootControllerTheme: theme), strings: NavigationBarStrings(presentationStrings: strings))
|
||||
} else {
|
||||
navigationBarPresentationData = nil
|
||||
}
|
||||
super.init(navigationBarPresentationData: navigationBarPresentationData)
|
||||
|
||||
if let theme = theme {
|
||||
self.statusBar.statusBarStyle = theme.rootController.statusBarStyle.style
|
||||
}
|
||||
|
||||
let contextImpl = LegacyControllerContext(controller: self, theme: theme)
|
||||
self.contextImpl = contextImpl
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.disposables.dispose()
|
||||
}
|
||||
|
||||
required public init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
public func bind(controller: UIViewController) {
|
||||
self.legacyController = controller
|
||||
if let controller = controller as? TGViewController {
|
||||
controller.customRemoveFromParentViewController = { [weak self] in
|
||||
self?.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override open func loadDisplayNode() {
|
||||
self.displayNode = LegacyControllerNode()
|
||||
self.displayNodeDidLoad()
|
||||
}
|
||||
|
||||
override open func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
if self.ignoreAppearanceMethodInvocations() {
|
||||
return
|
||||
}
|
||||
|
||||
if self.controllerNode.controllerView == nil {
|
||||
self.controllerNode.controllerView = self.legacyController.view
|
||||
if let legacyController = self.legacyController as? TGViewController {
|
||||
legacyController.ignoreAppearEvents = true
|
||||
}
|
||||
self.controllerNode.view.insertSubview(self.legacyController.view, at: 0)
|
||||
if let legacyController = self.legacyController as? TGViewController {
|
||||
legacyController.ignoreAppearEvents = false
|
||||
}
|
||||
|
||||
if let controllerLoaded = self.controllerLoaded {
|
||||
controllerLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
self.legacyController.viewWillAppear(animated && passControllerAppearanceAnimated(in: true, presentation: self.presentation))
|
||||
}
|
||||
|
||||
override open func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
|
||||
if self.ignoreAppearanceMethodInvocations() {
|
||||
return
|
||||
}
|
||||
|
||||
self.legacyController.viewWillDisappear(animated && passControllerAppearanceAnimated(in: false, presentation: self.presentation))
|
||||
}
|
||||
|
||||
private var viewDidAppearProcessed = false
|
||||
|
||||
override open func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
self.enableContainerLayoutUpdates = true
|
||||
if self.ignoreAppearanceMethodInvocations() {
|
||||
return
|
||||
}
|
||||
self.viewDidAppear(animated: animated, completion: {})
|
||||
}
|
||||
|
||||
public func viewDidAppear(completion: @escaping () -> Void) {
|
||||
self.viewDidAppear(animated: false, completion: completion)
|
||||
}
|
||||
|
||||
private func viewDidAppear(animated: Bool, completion: @escaping () -> Void) {
|
||||
if self.viewDidAppearProcessed {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
self.viewDidAppearProcessed = true
|
||||
switch self.presentation {
|
||||
case let .modal(animateIn):
|
||||
if animateIn {
|
||||
self.controllerNode.animateModalIn(completion: { [weak self] in
|
||||
self?.presentationCompleted?()
|
||||
completion()
|
||||
})
|
||||
} else {
|
||||
self.presentationCompleted?()
|
||||
completion()
|
||||
}
|
||||
self.legacyController.viewDidAppear(animated && animateIn)
|
||||
case .custom, .navigation:
|
||||
self.legacyController.viewDidAppear(animated)
|
||||
self.presentationCompleted?()
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
override open func viewDidDisappear(_ animated: Bool) {
|
||||
super.viewDidDisappear(animated)
|
||||
self.viewDidAppearProcessed = false
|
||||
|
||||
if self.ignoreAppearanceMethodInvocations() {
|
||||
return
|
||||
}
|
||||
|
||||
self.legacyController.viewDidDisappear(animated && passControllerAppearanceAnimated(in: false, presentation: self.presentation))
|
||||
}
|
||||
|
||||
override open func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
let previousSizeClass: UIUserInterfaceSizeClass
|
||||
if let validLayout = self.validLayout, case .regular = validLayout.metrics.widthClass {
|
||||
previousSizeClass = .regular
|
||||
} else {
|
||||
previousSizeClass = .compact
|
||||
}
|
||||
self.validLayout = layout
|
||||
|
||||
super.containerLayoutUpdated(layout, transition: transition)
|
||||
|
||||
self.controllerNode.containerLayoutUpdated(layout, navigationBarHeight: self.navigationHeight, transition: transition)
|
||||
if let legacyTelegramController = self.legacyController as? TGViewController {
|
||||
var duration: TimeInterval = 0.0
|
||||
if case let .animated(transitionDuration, _) = transition {
|
||||
duration = transitionDuration
|
||||
}
|
||||
|
||||
var orientation = UIInterfaceOrientation.portrait
|
||||
if layout.size.width > layout.size.height {
|
||||
orientation = .landscapeRight
|
||||
}
|
||||
|
||||
legacyTelegramController._updateInset(for: orientation, force: false, notify: true)
|
||||
if self.enableContainerLayoutUpdates {
|
||||
legacyTelegramController.layoutController(for: layout.size, duration: duration)
|
||||
}
|
||||
}
|
||||
let updatedSizeClass: UIUserInterfaceSizeClass
|
||||
if case .regular = layout.metrics.widthClass {
|
||||
updatedSizeClass = .regular
|
||||
} else {
|
||||
updatedSizeClass = .compact
|
||||
}
|
||||
if previousSizeClass != updatedSizeClass {
|
||||
self.sizeClass.set(SSignal.single(updatedSizeClass.rawValue as NSNumber))
|
||||
}
|
||||
}
|
||||
|
||||
override open func dismiss(completion: (() -> Void)? = nil) {
|
||||
self.view.endEditing(true)
|
||||
switch self.presentation {
|
||||
case .modal:
|
||||
self.controllerNode.animateModalOut { [weak self] in
|
||||
if let controller = self?.legacyController as? TGViewController {
|
||||
//controller.didDismiss()
|
||||
} else if let controller = self?.legacyController as? TGNavigationController {
|
||||
//controller.didDismiss()
|
||||
}
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: completion)
|
||||
}
|
||||
case .custom:
|
||||
if let controller = self.legacyController as? TGViewController {
|
||||
//controller.didDismiss()
|
||||
} else if let controller = self.legacyController as? TGNavigationController {
|
||||
//controller.didDismiss()
|
||||
}
|
||||
self.presentingViewController?.dismiss(animated: false, completion: completion)
|
||||
|
||||
case .navigation:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func dismissWithAnimation() {
|
||||
self.controllerNode.animateModalOut { [weak self] in
|
||||
self?.presentingViewController?.dismiss(animated: false, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user