mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
Stream improvements
This commit is contained in:
@@ -1,134 +1,3 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
|
||||
public final class RootHostView<EnvironmentType: Equatable>: UIViewController {
|
||||
private let content: AnyComponent<(NavigationLayout, EnvironmentType)>
|
||||
|
||||
private var keyboardWillChangeFrameObserver: NSObjectProtocol?
|
||||
private var inputHeight: CGFloat = 0.0
|
||||
|
||||
private let environment: Environment<EnvironmentType>
|
||||
private var componentView: ComponentHostView<(NavigationLayout, EnvironmentType)>
|
||||
|
||||
private var scheduledTransition: Transition?
|
||||
|
||||
public init(
|
||||
content: AnyComponent<(NavigationLayout, EnvironmentType)>,
|
||||
@EnvironmentBuilder environment: () -> Environment<EnvironmentType>
|
||||
) {
|
||||
self.content = content
|
||||
|
||||
self.environment = Environment<EnvironmentType>()
|
||||
self.componentView = ComponentHostView<(NavigationLayout, EnvironmentType)>()
|
||||
|
||||
EnvironmentBuilder._environment = self.environment
|
||||
let _ = environment()
|
||||
EnvironmentBuilder._environment = nil
|
||||
|
||||
super.init(nibName: nil, bundle: nil)
|
||||
|
||||
NotificationCenter.default.addObserver(forName: UIApplication.keyboardWillChangeFrameNotification, object: nil, queue: nil, using: { [weak self] notification in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
guard let keyboardFrame = notification.userInfo?[UIApplication.keyboardFrameEndUserInfoKey] as? CGRect else {
|
||||
return
|
||||
}
|
||||
|
||||
var duration: Double = (notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0.0
|
||||
if duration > Double.ulpOfOne {
|
||||
duration = 0.5
|
||||
}
|
||||
let curve: UInt = (notification.userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber)?.uintValue ?? 7
|
||||
|
||||
let transition: Transition
|
||||
if curve == 7 {
|
||||
transition = Transition(animation: .curve(duration: duration, curve: .spring))
|
||||
} else {
|
||||
transition = Transition(animation: .curve(duration: duration, curve: .easeInOut))
|
||||
}
|
||||
|
||||
strongSelf.updateKeyboardLayout(keyboardFrame: keyboardFrame, transition: transition)
|
||||
})
|
||||
}
|
||||
|
||||
required public init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.keyboardWillChangeFrameObserver.flatMap(NotificationCenter.default.removeObserver)
|
||||
}
|
||||
|
||||
private func updateKeyboardLayout(keyboardFrame: CGRect, transition: Transition) {
|
||||
self.inputHeight = max(0.0, self.view.bounds.height - keyboardFrame.minY)
|
||||
if self.componentView.isUpdating || true {
|
||||
if let _ = self.scheduledTransition {
|
||||
if case .curve = transition.animation {
|
||||
self.scheduledTransition = transition
|
||||
}
|
||||
} else {
|
||||
self.scheduledTransition = transition
|
||||
}
|
||||
self.view.setNeedsLayout()
|
||||
} else {
|
||||
self.updateComponent(size: self.view.bounds.size, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
private func updateComponent(size: CGSize, transition: Transition) {
|
||||
self.environment._isUpdated = false
|
||||
|
||||
transition.setFrame(view: self.componentView, frame: CGRect(origin: CGPoint(), size: size))
|
||||
let _ = self.componentView.update(
|
||||
transition: transition,
|
||||
component: self.content,
|
||||
environment: {
|
||||
NavigationLayout(
|
||||
statusBarHeight: size.width > size.height ? 0.0 : 40.0,
|
||||
inputHeight: self.inputHeight,
|
||||
bottomNavigationHeight: 22.0
|
||||
)
|
||||
self.environment[EnvironmentType.self]
|
||||
},
|
||||
containerSize: size
|
||||
)
|
||||
}
|
||||
|
||||
public func updateEnvironment(@EnvironmentBuilder environment: () -> Environment<EnvironmentType>) {
|
||||
EnvironmentBuilder._environment = self.environment
|
||||
let _ = environment()
|
||||
EnvironmentBuilder._environment = nil
|
||||
|
||||
if self.environment.calculateIsUpdated() {
|
||||
if !self.view.bounds.size.width.isZero {
|
||||
self.updateComponent(size: self.view.bounds.size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override public func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
self.view.addSubview(self.componentView)
|
||||
|
||||
if !self.view.bounds.size.width.isZero {
|
||||
self.updateComponent(size: self.view.bounds.size, transition: .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
override public func viewDidLayoutSubviews() {
|
||||
super.viewDidLayoutSubviews()
|
||||
|
||||
if let scheduledTransition = self.scheduledTransition {
|
||||
self.scheduledTransition = nil
|
||||
self.updateComponent(size: self.view.bounds.size, transition: scheduledTransition)
|
||||
}
|
||||
}
|
||||
|
||||
override public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
||||
super.viewWillTransition(to: size, with: coordinator)
|
||||
|
||||
self.updateComponent(size: size, transition: coordinator.isAnimated ? .easeInOut(duration: 0.3) : .immediate)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user