mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-11-07 17:30:12 +00:00
ipad fixes
This commit is contained in:
parent
bb94bd7e88
commit
10e3733a88
@ -10,21 +10,38 @@ import DisplayPrivate
|
|||||||
public final class NavigationControllerTheme {
|
public final class NavigationControllerTheme {
|
||||||
public let navigationBar: NavigationBarTheme
|
public let navigationBar: NavigationBarTheme
|
||||||
public let emptyAreaColor: UIColor
|
public let emptyAreaColor: UIColor
|
||||||
public let emptyDetailIcon: UIImage?
|
|
||||||
|
|
||||||
public init(navigationBar: NavigationBarTheme, emptyAreaColor: UIColor, emptyDetailIcon: UIImage?) {
|
public init(navigationBar: NavigationBarTheme, emptyAreaColor: UIColor) {
|
||||||
self.navigationBar = navigationBar
|
self.navigationBar = navigationBar
|
||||||
self.emptyAreaColor = emptyAreaColor
|
self.emptyAreaColor = emptyAreaColor
|
||||||
self.emptyDetailIcon = emptyDetailIcon
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public struct NavigationAnimationOptions : OptionSet {
|
||||||
|
public let rawValue: Int
|
||||||
|
|
||||||
|
public init(rawValue: Int) {
|
||||||
|
self.rawValue = rawValue
|
||||||
|
}
|
||||||
|
|
||||||
|
public init() {
|
||||||
|
self.rawValue = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
public static let removeOnMasterDetails = NavigationAnimationOptions(rawValue: 1 << 0)
|
||||||
|
}
|
||||||
|
|
||||||
private final class NavigationControllerContainerView: UIView {
|
private final class NavigationControllerContainerView: UIView {
|
||||||
override class var layerClass: AnyClass {
|
override class var layerClass: AnyClass {
|
||||||
return CATracingLayer.self
|
return CATracingLayer.self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum NavigationEmptyDetailsBackgoundMode {
|
||||||
|
case image(UIImage)
|
||||||
|
case wallpaper(UIImage)
|
||||||
|
}
|
||||||
|
|
||||||
private final class NavigationControllerView: UITracingLayerView {
|
private final class NavigationControllerView: UITracingLayerView {
|
||||||
var inTransition = false
|
var inTransition = false
|
||||||
|
|
||||||
@ -34,7 +51,8 @@ private final class NavigationControllerView: UITracingLayerView {
|
|||||||
var navigationBackgroundView: UIView?
|
var navigationBackgroundView: UIView?
|
||||||
var navigationSeparatorView: UIView?
|
var navigationSeparatorView: UIView?
|
||||||
var emptyDetailView: UIImageView?
|
var emptyDetailView: UIImageView?
|
||||||
|
var detailsBackground: WallpaperbackgroundNode?
|
||||||
|
var masterDetailsBlackout: ASDisplayNode?
|
||||||
var topControllerNode: ASDisplayNode?
|
var topControllerNode: ASDisplayNode?
|
||||||
|
|
||||||
/*override var accessibilityElements: [Any]? {
|
/*override var accessibilityElements: [Any]? {
|
||||||
@ -98,12 +116,20 @@ public enum NavigationControllerMode {
|
|||||||
case automaticMasterDetail
|
case automaticMasterDetail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum MasterDetailLayoutBlackout : Equatable {
|
||||||
|
case master
|
||||||
|
case details
|
||||||
|
}
|
||||||
|
|
||||||
open class NavigationController: UINavigationController, ContainableController, UIGestureRecognizerDelegate {
|
open class NavigationController: UINavigationController, ContainableController, UIGestureRecognizerDelegate {
|
||||||
public var isOpaqueWhenInOverlay: Bool = true
|
public var isOpaqueWhenInOverlay: Bool = true
|
||||||
public var blocksBackgroundWhenInOverlay: Bool = true
|
public var blocksBackgroundWhenInOverlay: Bool = true
|
||||||
|
|
||||||
public var ready: Promise<Bool> = Promise(true)
|
public var ready: Promise<Bool> = Promise(true)
|
||||||
|
|
||||||
|
private var masterDetailsBlackout: MasterDetailLayoutBlackout?
|
||||||
|
private var backgroundDetailsMode: NavigationEmptyDetailsBackgoundMode?
|
||||||
|
|
||||||
public var lockOrientation: Bool = false
|
public var lockOrientation: Bool = false
|
||||||
|
|
||||||
public var deferScreenEdgeGestures: UIRectEdge = UIRectEdge()
|
public var deferScreenEdgeGestures: UIRectEdge = UIRectEdge()
|
||||||
@ -150,10 +176,23 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
return self._displayNode!
|
return self._displayNode!
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(mode: NavigationControllerMode, theme: NavigationControllerTheme) {
|
public func updateMasterDetailsBlackout(_ blackout: MasterDetailLayoutBlackout?, transition: ContainedViewLayoutTransition) {
|
||||||
|
self.masterDetailsBlackout = blackout
|
||||||
|
if isViewLoaded {
|
||||||
|
self.view.endEditing(true)
|
||||||
|
}
|
||||||
|
self.requestLayout(transition: transition)
|
||||||
|
}
|
||||||
|
public func updateBackgroundDetailsMode(_ mode: NavigationEmptyDetailsBackgoundMode?, transition: ContainedViewLayoutTransition) {
|
||||||
|
self.backgroundDetailsMode = mode
|
||||||
|
self.requestLayout(transition: transition)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public init(mode: NavigationControllerMode, theme: NavigationControllerTheme, backgroundDetailsMode: NavigationEmptyDetailsBackgoundMode? = nil) {
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
|
self.backgroundDetailsMode = backgroundDetailsMode
|
||||||
super.init(nibName: nil, bundle: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,12 +234,12 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
self.controllerView.separatorView.backgroundColor = theme.navigationBar.separatorColor
|
self.controllerView.separatorView.backgroundColor = theme.navigationBar.separatorColor
|
||||||
self.controllerView.navigationBackgroundView?.backgroundColor = theme.navigationBar.backgroundColor
|
self.controllerView.navigationBackgroundView?.backgroundColor = theme.navigationBar.backgroundColor
|
||||||
self.controllerView.navigationSeparatorView?.backgroundColor = theme.navigationBar.separatorColor
|
self.controllerView.navigationSeparatorView?.backgroundColor = theme.navigationBar.separatorColor
|
||||||
if let emptyDetailView = self.controllerView.emptyDetailView {
|
// if let emptyDetailView = self.controllerView.emptyDetailView {
|
||||||
emptyDetailView.image = theme.emptyDetailIcon
|
// emptyDetailView.image = theme.emptyDetailIcon
|
||||||
if let image = theme.emptyDetailIcon {
|
// if let image = theme.emptyDetailIcon {
|
||||||
emptyDetailView.frame = CGRect(origin: CGPoint(x: floor(emptyDetailView.center.x - image.size.width / 2.0), y: floor(emptyDetailView.center.y - image.size.height / 2.0)), size: image.size)
|
// emptyDetailView.frame = CGRect(origin: CGPoint(x: floor(emptyDetailView.center.x - image.size.width / 2.0), y: floor(emptyDetailView.center.y - image.size.height / 2.0)), size: image.size)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,43 +293,139 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
self.controllerView.addSubview(self.controllerView.separatorView)
|
self.controllerView.addSubview(self.controllerView.separatorView)
|
||||||
}
|
}
|
||||||
|
|
||||||
let navigationBackgroundFrame = CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: CGSize(width: lastControllerFrameAndLayout.0.width, height: (layout.statusBarHeight ?? 0.0) + 44.0))
|
let navigationBackgroundFrame = CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: CGSize(width: lastControllerFrameAndLayout.0.width, height: (layout.statusBarHeight ?? 0.0) + 44.0))
|
||||||
|
|
||||||
if let navigationBackgroundView = self.controllerView.navigationBackgroundView, let navigationSeparatorView = self.controllerView.navigationSeparatorView, let emptyDetailView = self.controllerView.emptyDetailView {
|
if let backgroundDetailsMode = self.backgroundDetailsMode {
|
||||||
transition.updateFrame(view: navigationBackgroundView, frame: navigationBackgroundFrame)
|
|
||||||
transition.updateFrame(view: navigationSeparatorView, frame: CGRect(origin: CGPoint(x: navigationBackgroundFrame.minX, y: navigationBackgroundFrame.maxY), size: CGSize(width: navigationBackgroundFrame.width, height: UIScreenPixel)))
|
|
||||||
if let image = emptyDetailView.image {
|
|
||||||
transition.updateFrame(view: emptyDetailView, frame: CGRect(origin: CGPoint(x: masterData.0.maxX + floor((lastControllerFrameAndLayout.0.size.width - image.size.width) / 2.0), y: floor((lastControllerFrameAndLayout.0.size.height - image.size.height) / 2.0)), size: image.size))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let navigationBackgroundView = UIView()
|
|
||||||
navigationBackgroundView.backgroundColor = self.theme.navigationBar.backgroundColor
|
|
||||||
let navigationSeparatorView = UIView()
|
|
||||||
navigationSeparatorView.backgroundColor = self.theme.navigationBar.separatorColor
|
|
||||||
let emptyDetailView = UIImageView()
|
|
||||||
emptyDetailView.image = self.theme.emptyDetailIcon
|
|
||||||
emptyDetailView.alpha = 0.0
|
|
||||||
|
|
||||||
self.controllerView.navigationBackgroundView = navigationBackgroundView
|
switch backgroundDetailsMode {
|
||||||
self.controllerView.navigationSeparatorView = navigationSeparatorView
|
case let .image(image):
|
||||||
self.controllerView.emptyDetailView = emptyDetailView
|
if let detailsBackground = self.controllerView.detailsBackground {
|
||||||
|
self.controllerView.detailsBackground = nil
|
||||||
|
transition.updateAlpha(node: detailsBackground, alpha: 0.0, completion: { [weak detailsBackground] _ in
|
||||||
|
detailsBackground?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let emptyDetailView: UIImageView
|
||||||
|
if let emptyView = self.controllerView.emptyDetailView {
|
||||||
|
emptyDetailView = emptyView
|
||||||
|
} else {
|
||||||
|
emptyDetailView = UIImageView()
|
||||||
|
emptyDetailView.alpha = 0.0
|
||||||
|
self.controllerView.emptyDetailView = emptyDetailView
|
||||||
|
}
|
||||||
|
emptyDetailView.image = image
|
||||||
|
if emptyDetailView.superview == nil {
|
||||||
|
self.controllerView.insertSubview(emptyDetailView, at: 0)
|
||||||
|
}
|
||||||
|
transition.updateAlpha(layer: emptyDetailView.layer, alpha: 1.0)
|
||||||
|
|
||||||
self.controllerView.insertSubview(navigationBackgroundView, at: 0)
|
|
||||||
self.controllerView.insertSubview(navigationSeparatorView, at: 1)
|
|
||||||
self.controllerView.insertSubview(emptyDetailView, at: 2)
|
|
||||||
|
|
||||||
navigationBackgroundView.frame = navigationBackgroundFrame
|
|
||||||
navigationSeparatorView.frame = CGRect(origin: CGPoint(x: navigationBackgroundFrame.minX, y: navigationBackgroundFrame.maxY), size: CGSize(width: navigationBackgroundFrame.width, height: UIScreenPixel))
|
|
||||||
|
|
||||||
transition.animatePositionAdditive(layer: navigationBackgroundView.layer, offset: CGPoint(x: navigationBackgroundFrame.width, y: 0.0))
|
|
||||||
transition.animatePositionAdditive(layer: navigationSeparatorView.layer, offset: CGPoint(x: navigationBackgroundFrame.width, y: 0.0))
|
|
||||||
|
|
||||||
if let image = emptyDetailView.image {
|
|
||||||
emptyDetailView.frame = CGRect(origin: CGPoint(x: masterData.0.maxX + floor((lastControllerFrameAndLayout.0.size.width - image.size.width) / 2.0), y: floor((lastControllerFrameAndLayout.0.size.height - image.size.height) / 2.0)), size: image.size)
|
emptyDetailView.frame = CGRect(origin: CGPoint(x: masterData.0.maxX + floor((lastControllerFrameAndLayout.0.size.width - image.size.width) / 2.0), y: floor((lastControllerFrameAndLayout.0.size.height - image.size.height) / 2.0)), size: image.size)
|
||||||
|
|
||||||
|
|
||||||
|
case let .wallpaper(image):
|
||||||
|
if let emptyDetailView = self.controllerView.emptyDetailView {
|
||||||
|
self.controllerView.emptyDetailView = nil
|
||||||
|
transition.updateAlpha(layer: emptyDetailView.layer, alpha: 0.0, completion: { [weak emptyDetailView] _ in
|
||||||
|
emptyDetailView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let detailsBackground: WallpaperbackgroundNode
|
||||||
|
if let background = self.controllerView.detailsBackground {
|
||||||
|
detailsBackground = background
|
||||||
|
} else {
|
||||||
|
detailsBackground = WallpaperbackgroundNode()
|
||||||
|
detailsBackground.alpha = 0.0
|
||||||
|
self.controllerView.detailsBackground = detailsBackground
|
||||||
|
}
|
||||||
|
detailsBackground.image = image
|
||||||
|
if detailsBackground.supernode == nil {
|
||||||
|
self.controllerView.insertSubview(detailsBackground.view, at: 0)
|
||||||
|
}
|
||||||
|
transition.updateAlpha(node: detailsBackground, alpha: 1.0)
|
||||||
|
detailsBackground.frame = CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: lastControllerFrameAndLayout.0.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
transition.updateAlpha(layer: emptyDetailView.layer, alpha: 1.0)
|
} else {
|
||||||
|
if let emptyDetailView = self.controllerView.emptyDetailView {
|
||||||
|
self.controllerView.emptyDetailView = nil
|
||||||
|
transition.updateAlpha(layer: emptyDetailView.layer, alpha: 0.0, completion: { [weak emptyDetailView] _ in
|
||||||
|
emptyDetailView?.removeFromSuperview()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if let detailsBackground = self.controllerView.detailsBackground {
|
||||||
|
self.controllerView.detailsBackground = nil
|
||||||
|
transition.updateAlpha(node: detailsBackground, alpha: 0.0, completion: { [weak detailsBackground] _ in
|
||||||
|
detailsBackground?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let emptyDetailView = self.controllerView.emptyDetailView {
|
||||||
|
// transition.updateFrame(view: navigationBackgroundView, frame: navigationBackgroundFrame)
|
||||||
|
// transition.updateFrame(view: navigationSeparatorView, frame: CGRect(origin: CGPoint(x: navigationBackgroundFrame.minX, y: navigationBackgroundFrame.maxY), size: CGSize(width: navigationBackgroundFrame.width, height: UIScreenPixel)))
|
||||||
|
// if let image = emptyDetailView.image {
|
||||||
|
// transition.updateFrame(view: emptyDetailView, frame: CGRect(origin: CGPoint(x: masterData.0.maxX + floor((lastControllerFrameAndLayout.0.size.width - image.size.width) / 2.0), y: floor((lastControllerFrameAndLayout.0.size.height - image.size.height) / 2.0)), size: image.size))
|
||||||
|
// }
|
||||||
|
} else {
|
||||||
|
// let navigationBackgroundView = UIView()
|
||||||
|
// navigationBackgroundView.backgroundColor = self.theme.navigationBar.c
|
||||||
|
// let navigationSeparatorView = UIView()
|
||||||
|
// navigationSeparatorView.backgroundColor = self.theme.navigationBar.separatorColor
|
||||||
|
// let emptyDetailView = UIImageView()
|
||||||
|
// emptyDetailView.image = self.theme.emptyDetailIcon
|
||||||
|
// emptyDetailView.alpha = 0.0
|
||||||
|
//
|
||||||
|
// self.controllerView.navigationBackgroundView = navigationBackgroundView
|
||||||
|
// self.controllerView.navigationSeparatorView = navigationSeparatorView
|
||||||
|
// self.controllerView.emptyDetailView = emptyDetailView
|
||||||
|
//
|
||||||
|
// self.controllerView.insertSubview(navigationBackgroundView, at: 0)
|
||||||
|
// self.controllerView.insertSubview(navigationSeparatorView, at: 1)
|
||||||
|
// self.controllerView.insertSubview(emptyDetailView, at: 0)
|
||||||
|
|
||||||
|
// navigationBackgroundView.frame = navigationBackgroundFrame
|
||||||
|
// navigationSeparatorView.frame = CGRect(origin: CGPoint(x: navigationBackgroundFrame.minX, y: navigationBackgroundFrame.maxY), size: CGSize(width: navigationBackgroundFrame.width, height: UIScreenPixel))
|
||||||
|
//
|
||||||
|
// transition.animatePositionAdditive(layer: navigationBackgroundView.layer, offset: CGPoint(x: navigationBackgroundFrame.width, y: 0.0))
|
||||||
|
// transition.animatePositionAdditive(layer: navigationSeparatorView.layer, offset: CGPoint(x: navigationBackgroundFrame.width, y: 0.0))
|
||||||
|
|
||||||
|
// if let image = emptyDetailView.image {
|
||||||
|
// emptyDetailView.frame = CGRect(origin: CGPoint(x: masterData.0.maxX + floor((lastControllerFrameAndLayout.0.size.width - image.size.width) / 2.0), y: floor((lastControllerFrameAndLayout.0.size.height - image.size.height) / 2.0)), size: image.size)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// transition.updateAlpha(layer: emptyDetailView.layer, alpha: 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let blackout = self.masterDetailsBlackout {
|
||||||
|
|
||||||
|
let blackoutFrame: CGRect
|
||||||
|
switch blackout {
|
||||||
|
case .details:
|
||||||
|
blackoutFrame = CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: lastControllerFrameAndLayout.0.size)
|
||||||
|
case .master:
|
||||||
|
blackoutFrame = masterData.0
|
||||||
|
}
|
||||||
|
if self.controllerView.masterDetailsBlackout == nil {
|
||||||
|
self.controllerView.masterDetailsBlackout = ASDisplayNode()
|
||||||
|
self.controllerView.masterDetailsBlackout?.backgroundColor = UIColor.black
|
||||||
|
self.controllerView.masterDetailsBlackout?.alpha = 0
|
||||||
|
self.controllerView.masterDetailsBlackout?.frame = blackoutFrame
|
||||||
|
}
|
||||||
|
let blackoutNode = self.controllerView.masterDetailsBlackout!
|
||||||
|
if blackoutNode.supernode == nil {
|
||||||
|
self.controllerView.addSubnode(blackoutNode)
|
||||||
|
}
|
||||||
|
transition.updateFrame(node: blackoutNode, frame: blackoutFrame)
|
||||||
|
transition.updateAlpha(node: blackoutNode, alpha: 0.2)
|
||||||
|
} else {
|
||||||
|
if let blackout = self.controllerView.masterDetailsBlackout {
|
||||||
|
self.controllerView.masterDetailsBlackout = nil
|
||||||
|
transition.updateAlpha(node: blackout, alpha: 0.0, completion: { [weak blackout] _ in
|
||||||
|
blackout?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
transition.updateFrame(view: self.controllerView.separatorView, frame: CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: CGSize(width: UIScreenPixel, height: layout.size.height)))
|
transition.updateFrame(view: self.controllerView.separatorView, frame: CGRect(origin: CGPoint(x: masterData.0.maxX, y: 0.0), size: CGSize(width: UIScreenPixel, height: layout.size.height)))
|
||||||
case .single:
|
case .single:
|
||||||
self.viewControllers.first?.view.clipsToBounds = false
|
self.viewControllers.first?.view.clipsToBounds = false
|
||||||
@ -310,6 +445,12 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
emptyDetailView?.removeFromSuperview()
|
emptyDetailView?.removeFromSuperview()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if let blackout = self.controllerView.masterDetailsBlackout {
|
||||||
|
self.controllerView.masterDetailsBlackout = nil
|
||||||
|
transition.updateAlpha(node: blackout, alpha: 0.0, completion: { [weak blackout] _ in
|
||||||
|
blackout?.removeFromSupernode()
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.controllerView.containerView.clipsToBounds = false
|
self.controllerView.containerView.clipsToBounds = false
|
||||||
lastControllerFrameAndLayout = layoutDataForConfiguration(layoutConfiguration, layout: layout, index: 1)
|
lastControllerFrameAndLayout = layoutDataForConfiguration(layoutConfiguration, layout: layout, index: 1)
|
||||||
@ -348,6 +489,11 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
} else {
|
} else {
|
||||||
controller.navigationBar?.previousItem = .item(viewControllers[i - 1].navigationItem)
|
controller.navigationBar?.previousItem = .item(viewControllers[i - 1].navigationItem)
|
||||||
}
|
}
|
||||||
|
if i < self._viewControllers.count - 1 {
|
||||||
|
controller.navigationCustomData = (viewControllers[i + 1] as? ViewController)?.customData
|
||||||
|
} else {
|
||||||
|
controller.navigationCustomData = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
viewControllers[i].navigation_setNavigationController(self)
|
viewControllers[i].navigation_setNavigationController(self)
|
||||||
|
|
||||||
@ -872,15 +1018,26 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceControllersAndPush(controllers: [UIViewController], controller: ViewController, animated: Bool, ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
|
public func replaceControllersAndPush(controllers: [UIViewController], controller: ViewController, animated: Bool, options: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
|
||||||
self.view.endEditing(true)
|
self.view.endEditing(true)
|
||||||
|
var animated = animated
|
||||||
|
|
||||||
self.scheduleAfterLayout { [weak self] in
|
self.scheduleAfterLayout { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let validLayout = strongSelf.validLayout {
|
if let validLayout = strongSelf.validLayout {
|
||||||
var (_, controllerLayout) = strongSelf.layoutDataForConfiguration(strongSelf.layoutConfiguration(for: validLayout), layout: validLayout, index: strongSelf.viewControllers.count)
|
let configuration = strongSelf.layoutConfiguration(for: validLayout)
|
||||||
|
var (_, controllerLayout) = strongSelf.layoutDataForConfiguration(configuration, layout: validLayout, index: strongSelf.viewControllers.count)
|
||||||
controllerLayout.inputHeight = nil
|
controllerLayout.inputHeight = nil
|
||||||
|
if options.contains(.removeOnMasterDetails) {
|
||||||
|
switch configuration {
|
||||||
|
case .masterDetail:
|
||||||
|
animated = false
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
controller.containerLayoutUpdated(controllerLayout, transition: .immediate)
|
controller.containerLayoutUpdated(controllerLayout, transition: .immediate)
|
||||||
}
|
}
|
||||||
strongSelf.currentPushDisposable.set((controller.ready.get()
|
strongSelf.currentPushDisposable.set((controller.ready.get()
|
||||||
@ -898,16 +1055,26 @@ open class NavigationController: UINavigationController, ContainableController,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public func replaceAllButRootController(_ controller: ViewController, animated: Bool, ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
|
public func replaceAllButRootController(_ controller: ViewController, animated: Bool, animationOptions: NavigationAnimationOptions = [], ready: ValuePromise<Bool>? = nil, completion: @escaping () -> Void = {}) {
|
||||||
self.view.endEditing(true)
|
self.view.endEditing(true)
|
||||||
self.scheduleAfterLayout { [weak self] in
|
self.scheduleAfterLayout { [weak self] in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
var animated = animated
|
||||||
if let validLayout = strongSelf.validLayout {
|
if let validLayout = strongSelf.validLayout {
|
||||||
var (_, controllerLayout) = strongSelf.layoutDataForConfiguration(strongSelf.layoutConfiguration(for: validLayout), layout: validLayout, index: strongSelf.viewControllers.count)
|
let configuration = strongSelf.layoutConfiguration(for: validLayout)
|
||||||
|
var (_, controllerLayout) = strongSelf.layoutDataForConfiguration(configuration, layout: validLayout, index: strongSelf.viewControllers.count)
|
||||||
controllerLayout.inputHeight = nil
|
controllerLayout.inputHeight = nil
|
||||||
controller.containerLayoutUpdated(controllerLayout, transition: .immediate)
|
controller.containerLayoutUpdated(controllerLayout, transition: .immediate)
|
||||||
|
switch configuration {
|
||||||
|
case .masterDetail:
|
||||||
|
if animationOptions.contains(.removeOnMasterDetails) {
|
||||||
|
animated = false
|
||||||
|
}
|
||||||
|
case .single:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
strongSelf.currentPushDisposable.set((controller.ready.get()
|
strongSelf.currentPushDisposable.set((controller.ready.get()
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
|
|||||||
@ -73,6 +73,14 @@ open class TabBarController: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open override var navigationCustomData: Any? {
|
||||||
|
didSet {
|
||||||
|
for controller in controllers {
|
||||||
|
controller.navigationCustomData = navigationCustomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public private(set) var controllers: [ViewController] = []
|
public private(set) var controllers: [ViewController] = []
|
||||||
|
|
||||||
private let _ready = Promise<Bool>()
|
private let _ready = Promise<Bool>()
|
||||||
|
|||||||
@ -206,6 +206,13 @@ open class ViewControllerPresentationArguments {
|
|||||||
public var scrollToTopWithTabBar: (() -> Void)?
|
public var scrollToTopWithTabBar: (() -> Void)?
|
||||||
public var longTapWithTabBar: (() -> Void)?
|
public var longTapWithTabBar: (() -> Void)?
|
||||||
|
|
||||||
|
open var navigationCustomData: Any?
|
||||||
|
open var customData: Any? {
|
||||||
|
get {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public var attemptNavigation: (@escaping () -> Void) -> Bool = { _ in
|
public var attemptNavigation: (@escaping () -> Void) -> Bool = { _ in
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
73
submodules/Display/Display/WallpaperBackgroundNode.swift
Normal file
73
submodules/Display/Display/WallpaperBackgroundNode.swift
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// WallpaperBackgroundNode.swift
|
||||||
|
// Display
|
||||||
|
//
|
||||||
|
// Created by Mikhail Filimonov on 13/06/2019.
|
||||||
|
// Copyright © 2019 Telegram. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
private let motionAmount: CGFloat = 32.0
|
||||||
|
|
||||||
|
public final class WallpaperbackgroundNode: ASDisplayNode {
|
||||||
|
let contentNode: ASDisplayNode
|
||||||
|
|
||||||
|
public var motionEnabled: Bool = false {
|
||||||
|
didSet {
|
||||||
|
if oldValue != self.motionEnabled {
|
||||||
|
if self.motionEnabled {
|
||||||
|
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
||||||
|
horizontal.minimumRelativeValue = motionAmount
|
||||||
|
horizontal.maximumRelativeValue = -motionAmount
|
||||||
|
|
||||||
|
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
|
||||||
|
vertical.minimumRelativeValue = motionAmount
|
||||||
|
vertical.maximumRelativeValue = -motionAmount
|
||||||
|
|
||||||
|
let group = UIMotionEffectGroup()
|
||||||
|
group.motionEffects = [horizontal, vertical]
|
||||||
|
self.contentNode.view.addMotionEffect(group)
|
||||||
|
} else {
|
||||||
|
for effect in self.contentNode.view.motionEffects {
|
||||||
|
self.contentNode.view.removeMotionEffect(effect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.updateScale()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var image: UIImage? {
|
||||||
|
didSet {
|
||||||
|
self.contentNode.contents = self.image?.cgImage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateScale() {
|
||||||
|
if self.motionEnabled {
|
||||||
|
let scale = (self.frame.width + motionAmount * 2.0) / self.frame.width
|
||||||
|
self.contentNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
|
||||||
|
} else {
|
||||||
|
self.contentNode.transform = CATransform3DIdentity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override init() {
|
||||||
|
self.contentNode = ASDisplayNode()
|
||||||
|
self.contentNode.contentMode = .scaleAspectFill
|
||||||
|
|
||||||
|
super.init()
|
||||||
|
|
||||||
|
self.clipsToBounds = true
|
||||||
|
self.contentNode.frame = self.bounds
|
||||||
|
self.addSubnode(self.contentNode)
|
||||||
|
}
|
||||||
|
|
||||||
|
override public func layout() {
|
||||||
|
super.layout()
|
||||||
|
self.contentNode.bounds = self.bounds
|
||||||
|
self.contentNode.position = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
|
||||||
|
self.updateScale()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -23,6 +23,7 @@
|
|||||||
D015F7581D1B467200E269B5 /* ActionSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015F7571D1B467200E269B5 /* ActionSheetController.swift */; };
|
D015F7581D1B467200E269B5 /* ActionSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015F7571D1B467200E269B5 /* ActionSheetController.swift */; };
|
||||||
D015F75A1D1B46B600E269B5 /* ActionSheetControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015F7591D1B46B600E269B5 /* ActionSheetControllerNode.swift */; };
|
D015F75A1D1B46B600E269B5 /* ActionSheetControllerNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D015F7591D1B46B600E269B5 /* ActionSheetControllerNode.swift */; };
|
||||||
D01847661FFA72E000075256 /* ContainedViewLayoutTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01847651FFA72E000075256 /* ContainedViewLayoutTransition.swift */; };
|
D01847661FFA72E000075256 /* ContainedViewLayoutTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01847651FFA72E000075256 /* ContainedViewLayoutTransition.swift */; };
|
||||||
|
D01E1F0222B28D9400AD6DAE /* WallpaperBackgroundNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01E1F0122B28D9400AD6DAE /* WallpaperBackgroundNode.swift */; };
|
||||||
D01E2BDE1D9049620066BF65 /* GridNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01E2BDD1D9049620066BF65 /* GridNode.swift */; };
|
D01E2BDE1D9049620066BF65 /* GridNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01E2BDD1D9049620066BF65 /* GridNode.swift */; };
|
||||||
D01E2BE01D90498E0066BF65 /* GridNodeScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01E2BDF1D90498E0066BF65 /* GridNodeScroller.swift */; };
|
D01E2BE01D90498E0066BF65 /* GridNodeScroller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01E2BDF1D90498E0066BF65 /* GridNodeScroller.swift */; };
|
||||||
D01E2BE21D9049F60066BF65 /* GridItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01E2BE11D9049F60066BF65 /* GridItemNode.swift */; };
|
D01E2BE21D9049F60066BF65 /* GridItemNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01E2BE11D9049F60066BF65 /* GridItemNode.swift */; };
|
||||||
@ -195,6 +196,7 @@
|
|||||||
D015F7591D1B46B600E269B5 /* ActionSheetControllerNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionSheetControllerNode.swift; sourceTree = "<group>"; };
|
D015F7591D1B46B600E269B5 /* ActionSheetControllerNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionSheetControllerNode.swift; sourceTree = "<group>"; };
|
||||||
D01847651FFA72E000075256 /* ContainedViewLayoutTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainedViewLayoutTransition.swift; sourceTree = "<group>"; };
|
D01847651FFA72E000075256 /* ContainedViewLayoutTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainedViewLayoutTransition.swift; sourceTree = "<group>"; };
|
||||||
D01C06C61FC2558F001561AB /* SwiftSignalKitMac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwiftSignalKitMac.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
D01C06C61FC2558F001561AB /* SwiftSignalKitMac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwiftSignalKitMac.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
D01E1F0122B28D9400AD6DAE /* WallpaperBackgroundNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WallpaperBackgroundNode.swift; sourceTree = "<group>"; };
|
||||||
D01E2BDD1D9049620066BF65 /* GridNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridNode.swift; sourceTree = "<group>"; };
|
D01E2BDD1D9049620066BF65 /* GridNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridNode.swift; sourceTree = "<group>"; };
|
||||||
D01E2BDF1D90498E0066BF65 /* GridNodeScroller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridNodeScroller.swift; sourceTree = "<group>"; };
|
D01E2BDF1D90498E0066BF65 /* GridNodeScroller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridNodeScroller.swift; sourceTree = "<group>"; };
|
||||||
D01E2BE11D9049F60066BF65 /* GridItemNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridItemNode.swift; sourceTree = "<group>"; };
|
D01E2BE11D9049F60066BF65 /* GridItemNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GridItemNode.swift; sourceTree = "<group>"; };
|
||||||
@ -462,6 +464,7 @@
|
|||||||
D0CA3F892073F7650042D2B6 /* LinkHighlightingNode.swift */,
|
D0CA3F892073F7650042D2B6 /* LinkHighlightingNode.swift */,
|
||||||
D04554A921BDB93E007A6DD9 /* CollectionIndexNode.swift */,
|
D04554A921BDB93E007A6DD9 /* CollectionIndexNode.swift */,
|
||||||
09DD88EA21BCA5E0000766BC /* EditableTextNode.swift */,
|
09DD88EA21BCA5E0000766BC /* EditableTextNode.swift */,
|
||||||
|
D01E1F0122B28D9400AD6DAE /* WallpaperBackgroundNode.swift */,
|
||||||
);
|
);
|
||||||
name = Nodes;
|
name = Nodes;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -939,6 +942,7 @@
|
|||||||
D033874E223D3E86007A2CE4 /* AccessibilityAreaNode.swift in Sources */,
|
D033874E223D3E86007A2CE4 /* AccessibilityAreaNode.swift in Sources */,
|
||||||
D015F75A1D1B46B600E269B5 /* ActionSheetControllerNode.swift in Sources */,
|
D015F75A1D1B46B600E269B5 /* ActionSheetControllerNode.swift in Sources */,
|
||||||
D01847661FFA72E000075256 /* ContainedViewLayoutTransition.swift in Sources */,
|
D01847661FFA72E000075256 /* ContainedViewLayoutTransition.swift in Sources */,
|
||||||
|
D01E1F0222B28D9400AD6DAE /* WallpaperBackgroundNode.swift in Sources */,
|
||||||
D03725C11D6DF594007FC290 /* ContextMenuNode.swift in Sources */,
|
D03725C11D6DF594007FC290 /* ContextMenuNode.swift in Sources */,
|
||||||
D03AA4DB202DA6D60056C405 /* PeekControllerContent.swift in Sources */,
|
D03AA4DB202DA6D60056C405 /* PeekControllerContent.swift in Sources */,
|
||||||
D053CB611D22B4F200DD41DF /* CATracingLayer.m in Sources */,
|
D053CB611D22B4F200DD41DF /* CATracingLayer.m in Sources */,
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"filename" : "DetailLogoBlank@2x.png",
|
"filename" : "EmptyChat@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.6 KiB |
BIN
submodules/TelegramUI/Images.xcassets/Chat List/EmptyMasterDetailIcon.imageset/EmptyChat@2x.png
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat List/EmptyMasterDetailIcon.imageset/EmptyChat@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
@ -47,7 +47,7 @@ public final class AuthorizationSequenceController: NavigationController, MFMail
|
|||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.openUrl = openUrl
|
self.openUrl = openUrl
|
||||||
|
|
||||||
super.init(mode: .single, theme: NavigationControllerTheme(navigationBar: AuthorizationSequenceController.navigationBarTheme(theme), emptyAreaColor: .black, emptyDetailIcon: nil))
|
super.init(mode: .single, theme: NavigationControllerTheme(navigationBar: AuthorizationSequenceController.navigationBarTheme(theme), emptyAreaColor: .black))
|
||||||
|
|
||||||
self.stateDisposable = (account.postbox.stateView()
|
self.stateDisposable = (account.postbox.stateView()
|
||||||
|> map { view -> InnerState in
|
|> map { view -> InnerState in
|
||||||
|
|||||||
@ -227,6 +227,10 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||||||
|
|
||||||
var purposefulAction: (() -> Void)?
|
var purposefulAction: (() -> Void)?
|
||||||
|
|
||||||
|
public override var customData: Any? {
|
||||||
|
return self.chatLocation
|
||||||
|
}
|
||||||
|
|
||||||
public init(context: AccountContext, chatLocation: ChatLocation, messageId: MessageId? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false)) {
|
public init(context: AccountContext, chatLocation: ChatLocation, messageId: MessageId? = nil, botStart: ChatControllerInitialBotStart? = nil, mode: ChatControllerPresentationMode = .standard(previewing: false)) {
|
||||||
let _ = ChatControllerCount.modify { value in
|
let _ = ChatControllerCount.modify { value in
|
||||||
return value + 1
|
return value + 1
|
||||||
@ -4164,6 +4168,7 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||||||
if updatedChatPresentationInterfaceState.interfaceState.selectionState != controllerInteraction.selectionState {
|
if updatedChatPresentationInterfaceState.interfaceState.selectionState != controllerInteraction.selectionState {
|
||||||
controllerInteraction.selectionState = updatedChatPresentationInterfaceState.interfaceState.selectionState
|
controllerInteraction.selectionState = updatedChatPresentationInterfaceState.interfaceState.selectionState
|
||||||
self.updateItemNodesSelectionStates(animated: transition.isAnimated)
|
self.updateItemNodesSelectionStates(animated: transition.isAnimated)
|
||||||
|
(self.navigationController as? NavigationController)?.updateMasterDetailsBlackout(controllerInteraction.selectionState != nil ? .master : nil, transition: transition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5369,6 +5374,8 @@ public final class ChatController: TelegramController, GalleryHiddenMediaTarget,
|
|||||||
self.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
self.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public func navigateToMessage(messageLocation: NavigateToMessageLocation, animated: Bool, forceInCurrentChat: Bool = false, completion: (() -> Void)? = nil, customPresentProgress: ((ViewController, Any?) -> Void)? = nil) {
|
public func navigateToMessage(messageLocation: NavigateToMessageLocation, animated: Bool, forceInCurrentChat: Bool = false, completion: (() -> Void)? = nil, customPresentProgress: ((ViewController, Any?) -> Void)? = nil) {
|
||||||
self.navigateToMessage(from: nil, to: messageLocation, rememberInStack: false, forceInCurrentChat: forceInCurrentChat, animated: animated, completion: completion, customPresentProgress: customPresentProgress)
|
self.navigateToMessage(from: nil, to: messageLocation, rememberInStack: false, forceInCurrentChat: forceInCurrentChat, animated: animated, completion: completion, customPresentProgress: customPresentProgress)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,69 +6,6 @@ import Display
|
|||||||
import SwiftSignalKit
|
import SwiftSignalKit
|
||||||
import Postbox
|
import Postbox
|
||||||
|
|
||||||
private let motionAmount: CGFloat = 32.0
|
|
||||||
|
|
||||||
final class ChatBackgroundNode: ASDisplayNode {
|
|
||||||
let contentNode: ASDisplayNode
|
|
||||||
|
|
||||||
var motionEnabled: Bool = false {
|
|
||||||
didSet {
|
|
||||||
if oldValue != self.motionEnabled {
|
|
||||||
if self.motionEnabled {
|
|
||||||
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
|
|
||||||
horizontal.minimumRelativeValue = motionAmount
|
|
||||||
horizontal.maximumRelativeValue = -motionAmount
|
|
||||||
|
|
||||||
let vertical = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
|
|
||||||
vertical.minimumRelativeValue = motionAmount
|
|
||||||
vertical.maximumRelativeValue = -motionAmount
|
|
||||||
|
|
||||||
let group = UIMotionEffectGroup()
|
|
||||||
group.motionEffects = [horizontal, vertical]
|
|
||||||
self.contentNode.view.addMotionEffect(group)
|
|
||||||
} else {
|
|
||||||
for effect in self.contentNode.view.motionEffects {
|
|
||||||
self.contentNode.view.removeMotionEffect(effect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.updateScale()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var image: UIImage? {
|
|
||||||
didSet {
|
|
||||||
self.contentNode.contents = self.image?.cgImage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateScale() {
|
|
||||||
if self.motionEnabled {
|
|
||||||
let scale = (self.frame.width + motionAmount * 2.0) / self.frame.width
|
|
||||||
self.contentNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
|
|
||||||
} else {
|
|
||||||
self.contentNode.transform = CATransform3DIdentity
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override init() {
|
|
||||||
self.contentNode = ASDisplayNode()
|
|
||||||
self.contentNode.contentMode = .scaleAspectFill
|
|
||||||
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
self.clipsToBounds = true
|
|
||||||
self.contentNode.frame = self.bounds
|
|
||||||
self.addSubnode(self.contentNode)
|
|
||||||
}
|
|
||||||
|
|
||||||
override func layout() {
|
|
||||||
super.layout()
|
|
||||||
self.contentNode.bounds = self.bounds
|
|
||||||
self.contentNode.position = CGPoint(x: self.bounds.midX, y: self.bounds.midY)
|
|
||||||
self.updateScale()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var backgroundImageForWallpaper: (TelegramWallpaper, Bool, UIImage)?
|
private var backgroundImageForWallpaper: (TelegramWallpaper, Bool, UIImage)?
|
||||||
private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)?
|
private var serviceBackgroundColorForWallpaper: (TelegramWallpaper, UIColor)?
|
||||||
|
|||||||
@ -69,7 +69,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let backgroundNode: ChatBackgroundNode
|
let backgroundNode: WallpaperbackgroundNode
|
||||||
let historyNode: ChatHistoryListNode
|
let historyNode: ChatHistoryListNode
|
||||||
let historyNodeContainer: ASDisplayNode
|
let historyNodeContainer: ASDisplayNode
|
||||||
let loadingNode: ChatLoadingNode
|
let loadingNode: ChatLoadingNode
|
||||||
@ -191,7 +191,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
|||||||
self.navigationBar = navigationBar
|
self.navigationBar = navigationBar
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
|
|
||||||
self.backgroundNode = ChatBackgroundNode()
|
self.backgroundNode = WallpaperbackgroundNode()
|
||||||
self.backgroundNode.displaysAsynchronously = false
|
self.backgroundNode.displaysAsynchronously = false
|
||||||
|
|
||||||
self.titleAccessoryPanelContainer = ChatControllerTitlePanelNodeContainer()
|
self.titleAccessoryPanelContainer = ChatControllerTitlePanelNodeContainer()
|
||||||
|
|||||||
@ -94,6 +94,12 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
|||||||
|
|
||||||
private var searchContentNode: NavigationBarSearchContentNode?
|
private var searchContentNode: NavigationBarSearchContentNode?
|
||||||
|
|
||||||
|
public override var navigationCustomData: Any? {
|
||||||
|
didSet {
|
||||||
|
self.chatListDisplayNode.chatListNode.updateSelectedChatLocation(self.navigationCustomData as? ChatLocation, progress: 1, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false) {
|
public init(context: AccountContext, groupId: PeerGroupId, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool = false) {
|
||||||
self.context = context
|
self.context = context
|
||||||
self.controlsHistoryPreload = controlsHistoryPreload
|
self.controlsHistoryPreload = controlsHistoryPreload
|
||||||
@ -684,9 +690,7 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
|||||||
scrollToEndIfExists = true
|
scrollToEndIfExists = true
|
||||||
}
|
}
|
||||||
|
|
||||||
let animated: Bool = !scrollToEndIfExists || strongSelf.groupId != PeerGroupId.root
|
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [], parentGroupId: strongSelf.groupId, completion: { [weak self] in
|
||||||
|
|
||||||
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peerId), scrollToEndIfExists: animated, animated: animated, parentGroupId: strongSelf.groupId, completion: { [weak self] in
|
|
||||||
self?.chatListDisplayNode.chatListNode.clearHighlightAnimated(true)
|
self?.chatListDisplayNode.chatListNode.clearHighlightAnimated(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -726,9 +730,16 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
|||||||
|> deliverOnMainQueue).start(next: { [weak strongSelf] actualPeerId in
|
|> deliverOnMainQueue).start(next: { [weak strongSelf] actualPeerId in
|
||||||
if let strongSelf = strongSelf {
|
if let strongSelf = strongSelf {
|
||||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||||
|
|
||||||
|
var scrollToEndIfExists = false
|
||||||
|
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
|
||||||
|
scrollToEndIfExists = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), messageId: messageId, purposefulAction: {
|
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(actualPeerId), messageId: messageId, purposefulAction: {
|
||||||
self?.deactivateSearch(animated: false)
|
self?.deactivateSearch(animated: false)
|
||||||
})
|
}, scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [])
|
||||||
strongSelf.chatListDisplayNode.chatListNode.clearHighlightAnimated(true)
|
strongSelf.chatListDisplayNode.chatListNode.clearHighlightAnimated(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -748,12 +759,18 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
|||||||
strongSelf.openMessageFromSearchDisposable.set((storedPeer |> deliverOnMainQueue).start(completed: { [weak strongSelf] in
|
strongSelf.openMessageFromSearchDisposable.set((storedPeer |> deliverOnMainQueue).start(completed: { [weak strongSelf] in
|
||||||
if let strongSelf = strongSelf {
|
if let strongSelf = strongSelf {
|
||||||
if dismissSearch {
|
if dismissSearch {
|
||||||
strongSelf.dismissSearchOnDisappear = true
|
strongSelf.deactivateSearch(animated: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var scrollToEndIfExists = false
|
||||||
|
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
|
||||||
|
scrollToEndIfExists = true
|
||||||
|
}
|
||||||
|
|
||||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||||
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), purposefulAction: { [weak self] in
|
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), purposefulAction: { [weak self] in
|
||||||
self?.deactivateSearch(animated: false)
|
self?.deactivateSearch(animated: false)
|
||||||
})
|
}, scrollToEndIfExists: scrollToEndIfExists, options: strongSelf.groupId == PeerGroupId.root ? [.removeOnMasterDetails] : [])
|
||||||
strongSelf.chatListDisplayNode.chatListNode.clearHighlightAnimated(true)
|
strongSelf.chatListDisplayNode.chatListNode.clearHighlightAnimated(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1095,10 +1112,6 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
|||||||
|
|
||||||
override public func navigationStackConfigurationUpdated(next: [ViewController]) {
|
override public func navigationStackConfigurationUpdated(next: [ViewController]) {
|
||||||
super.navigationStackConfigurationUpdated(next: next)
|
super.navigationStackConfigurationUpdated(next: next)
|
||||||
|
|
||||||
let chatLocation = (next.first as? ChatController)?.chatLocation
|
|
||||||
|
|
||||||
self.chatListDisplayNode.chatListNode.updateSelectedChatLocation(chatLocation, progress: 1.0, transition: .immediate)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func editPressed() {
|
@objc func editPressed() {
|
||||||
@ -1110,6 +1123,7 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
|||||||
self.navigationItem.rightBarButtonItem = editItem
|
self.navigationItem.rightBarButtonItem = editItem
|
||||||
}
|
}
|
||||||
self.searchContentNode?.setIsEnabled(false, animated: true)
|
self.searchContentNode?.setIsEnabled(false, animated: true)
|
||||||
|
(self.navigationController as? NavigationController)?.updateMasterDetailsBlackout(.details, transition: .animated(duration: 0.5, curve: .spring))
|
||||||
self.chatListDisplayNode.chatListNode.updateState { state in
|
self.chatListDisplayNode.chatListNode.updateState { state in
|
||||||
var state = state
|
var state = state
|
||||||
state.editing = true
|
state.editing = true
|
||||||
@ -1126,6 +1140,7 @@ public class ChatListController: TelegramController, UIViewControllerPreviewingD
|
|||||||
} else {
|
} else {
|
||||||
self.navigationItem.rightBarButtonItem = editItem
|
self.navigationItem.rightBarButtonItem = editItem
|
||||||
}
|
}
|
||||||
|
(self.navigationController as? NavigationController)?.updateMasterDetailsBlackout(nil, transition: .animated(duration: 0.4, curve: .spring))
|
||||||
self.searchContentNode?.setIsEnabled(true, animated: true)
|
self.searchContentNode?.setIsEnabled(true, animated: true)
|
||||||
self.chatListDisplayNode.chatListNode.updateState { state in
|
self.chatListDisplayNode.chatListNode.updateState { state in
|
||||||
var state = state
|
var state = state
|
||||||
|
|||||||
@ -504,7 +504,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
self.updateIsHighlighted(transition: (animated && !highlighted) ? .animated(duration: 0.3, curve: .easeInOut) : .immediate)
|
self.updateIsHighlighted(transition: (animated && !highlighted) ? .animated(duration: 0.3, curve: .easeInOut) : .immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateIsHighlighted(transition: ContainedViewLayoutTransition) {
|
var reallyHighlighted: Bool {
|
||||||
var reallyHighlighted = self.isHighlighted
|
var reallyHighlighted = self.isHighlighted
|
||||||
if let item = self.item {
|
if let item = self.item {
|
||||||
if let itemChatLocation = item.content.chatLocation {
|
if let itemChatLocation = item.content.chatLocation {
|
||||||
@ -513,6 +513,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return reallyHighlighted
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateIsHighlighted(transition: ContainedViewLayoutTransition) {
|
||||||
|
|
||||||
|
|
||||||
if reallyHighlighted {
|
if reallyHighlighted {
|
||||||
if self.highlightedBackgroundNode.supernode == nil {
|
if self.highlightedBackgroundNode.supernode == nil {
|
||||||
@ -1193,7 +1198,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
transition.updateFrame(node: strongSelf.onlineNode, frame: onlineFrame)
|
transition.updateFrame(node: strongSelf.onlineNode, frame: onlineFrame)
|
||||||
|
|
||||||
let onlineIcon: UIImage?
|
let onlineIcon: UIImage?
|
||||||
if strongSelf.isHighlighted {
|
if strongSelf.reallyHighlighted {
|
||||||
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .highlighted)
|
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .highlighted)
|
||||||
} else if item.index.pinningIndex != nil {
|
} else if item.index.pinningIndex != nil {
|
||||||
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned)
|
onlineIcon = PresentationResourcesChatList.recentStatusOnlineIcon(item.presentationData.theme, state: .pinned)
|
||||||
|
|||||||
@ -57,6 +57,6 @@ extension PeekControllerTheme {
|
|||||||
|
|
||||||
public extension NavigationControllerTheme {
|
public extension NavigationControllerTheme {
|
||||||
convenience init(presentationTheme: PresentationTheme) {
|
convenience init(presentationTheme: PresentationTheme) {
|
||||||
self.init(navigationBar: NavigationBarTheme(rootControllerTheme: presentationTheme), emptyAreaColor: presentationTheme.chatList.backgroundColor, emptyDetailIcon: generateTintedImage(image: UIImage(bundleImageName: "Chat List/EmptyMasterDetailIcon"), color: presentationTheme.chatList.messageTextColor.withAlphaComponent(0.2)))
|
self.init(navigationBar: NavigationBarTheme(rootControllerTheme: presentationTheme), emptyAreaColor: presentationTheme.chatList.backgroundColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -94,12 +94,21 @@ private enum ContactListNodeEntryId: Hashable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final class ContactItemHighlighting {
|
||||||
|
var chatLocation: ChatLocation?
|
||||||
|
init(chatLocation: ChatLocation? = nil) {
|
||||||
|
self.chatLocation = chatLocation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final class ContactListNodeInteraction {
|
private final class ContactListNodeInteraction {
|
||||||
let activateSearch: () -> Void
|
fileprivate let activateSearch: () -> Void
|
||||||
let openSortMenu: () -> Void
|
fileprivate let openSortMenu: () -> Void
|
||||||
let authorize: () -> Void
|
fileprivate let authorize: () -> Void
|
||||||
let suppressWarning: () -> Void
|
fileprivate let suppressWarning: () -> Void
|
||||||
let openPeer: (ContactListPeer) -> Void
|
fileprivate let openPeer: (ContactListPeer) -> Void
|
||||||
|
|
||||||
|
let itemHighlighting = ContactItemHighlighting()
|
||||||
|
|
||||||
init(activateSearch: @escaping () -> Void, openSortMenu: @escaping () -> Void, authorize: @escaping () -> Void, suppressWarning: @escaping () -> Void, openPeer: @escaping (ContactListPeer) -> Void) {
|
init(activateSearch: @escaping () -> Void, openSortMenu: @escaping () -> Void, authorize: @escaping () -> Void, suppressWarning: @escaping () -> Void, openPeer: @escaping (ContactListPeer) -> Void) {
|
||||||
self.activateSearch = activateSearch
|
self.activateSearch = activateSearch
|
||||||
@ -191,6 +200,8 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
func item(account: Account, interaction: ContactListNodeInteraction) -> ListViewItem {
|
func item(account: Account, interaction: ContactListNodeInteraction) -> ListViewItem {
|
||||||
switch self {
|
switch self {
|
||||||
case let .search(theme, strings):
|
case let .search(theme, strings):
|
||||||
@ -245,7 +256,7 @@ private enum ContactListNodeEntry: Comparable, Identifiable {
|
|||||||
}
|
}
|
||||||
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: itemPeer, status: status, enabled: enabled, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
return ContactsPeerItem(theme: theme, strings: strings, sortOrder: nameSortOrder, displayOrder: nameDisplayOrder, account: account, peerMode: .peer, peer: itemPeer, status: status, enabled: enabled, selection: selection, editing: ContactsPeerItemEditing(editable: false, editing: false, revealed: false), index: nil, header: header, action: { _ in
|
||||||
interaction.openPeer(peer)
|
interaction.openPeer(peer)
|
||||||
})
|
}, itemHighlighting: interaction.itemHighlighting)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -775,6 +786,7 @@ final class ContactListNode: ASDisplayNode {
|
|||||||
var selectionState: ContactListNodeGroupSelectionState? {
|
var selectionState: ContactListNodeGroupSelectionState? {
|
||||||
return self.selectionStateValue
|
return self.selectionStateValue
|
||||||
}
|
}
|
||||||
|
private var interaction: ContactListNodeInteraction?
|
||||||
|
|
||||||
private var enableUpdatesValue = false
|
private var enableUpdatesValue = false
|
||||||
var enableUpdates: Bool {
|
var enableUpdates: Bool {
|
||||||
@ -929,6 +941,8 @@ final class ContactListNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.interaction = interaction
|
||||||
|
|
||||||
let context = self.context
|
let context = self.context
|
||||||
var firstTime: Int32 = 1
|
var firstTime: Int32 = 1
|
||||||
let selectionStateSignal = self.selectionStatePromise.get()
|
let selectionStateSignal = self.selectionStatePromise.get()
|
||||||
@ -1318,6 +1332,17 @@ final class ContactListNode: ASDisplayNode {
|
|||||||
self.enableUpdates = true
|
self.enableUpdates = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateSelectedChatLocation(_ chatLocation: ChatLocation?, progress: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||||
|
|
||||||
|
self.interaction?.itemHighlighting.chatLocation = chatLocation
|
||||||
|
|
||||||
|
self.listNode.forEachItemNode { itemNode in
|
||||||
|
if let itemNode = itemNode as? ContactsPeerItemNode {
|
||||||
|
itemNode.updateIsHighlighted(transition: transition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
self.disposable.dispose()
|
self.disposable.dispose()
|
||||||
self.presentationDataDisposable?.dispose()
|
self.presentationDataDisposable?.dispose()
|
||||||
|
|||||||
@ -56,6 +56,7 @@ public class ContactsController: ViewController {
|
|||||||
private var contactsNode: ContactsControllerNode {
|
private var contactsNode: ContactsControllerNode {
|
||||||
return self.displayNode as! ContactsControllerNode
|
return self.displayNode as! ContactsControllerNode
|
||||||
}
|
}
|
||||||
|
private var validLayout: ContainerViewLayout?
|
||||||
|
|
||||||
private let index: PeerNameIndex = .lastNameFirst
|
private let index: PeerNameIndex = .lastNameFirst
|
||||||
|
|
||||||
@ -73,6 +74,12 @@ public class ContactsController: ViewController {
|
|||||||
|
|
||||||
var switchToChatsController: (() -> Void)?
|
var switchToChatsController: (() -> Void)?
|
||||||
|
|
||||||
|
public override var navigationCustomData: Any? {
|
||||||
|
didSet {
|
||||||
|
self.contactsNode.contactListNode.updateSelectedChatLocation(self.navigationCustomData as? ChatLocation, progress: 1, transition: .immediate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public init(context: AccountContext) {
|
public init(context: AccountContext) {
|
||||||
self.context = context
|
self.context = context
|
||||||
|
|
||||||
@ -195,12 +202,19 @@ public class ContactsController: ViewController {
|
|||||||
switch peer {
|
switch peer {
|
||||||
case let .peer(peer, _, _):
|
case let .peer(peer, _, _):
|
||||||
if let navigationController = strongSelf.navigationController as? NavigationController {
|
if let navigationController = strongSelf.navigationController as? NavigationController {
|
||||||
|
|
||||||
|
var scrollToEndIfExists = false
|
||||||
|
if let layout = strongSelf.validLayout, case .regular = layout.metrics.widthClass {
|
||||||
|
scrollToEndIfExists = true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), purposefulAction: { [weak self] in
|
navigateToChatController(navigationController: navigationController, context: strongSelf.context, chatLocation: .peer(peer.id), purposefulAction: { [weak self] in
|
||||||
if fromSearch {
|
if fromSearch {
|
||||||
self?.deactivateSearch(animated: false)
|
self?.deactivateSearch(animated: false)
|
||||||
self?.switchToChatsController?()
|
self?.switchToChatsController?()
|
||||||
}
|
}
|
||||||
}, completion: { [weak self] in
|
}, scrollToEndIfExists: scrollToEndIfExists, options: [.removeOnMasterDetails], completion: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true)
|
strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,6 +125,7 @@ class ContactsPeerItem: ListViewItem {
|
|||||||
let action: (ContactsPeerItemPeer) -> Void
|
let action: (ContactsPeerItemPeer) -> Void
|
||||||
let setPeerIdWithRevealedOptions: ((PeerId?, PeerId?) -> Void)?
|
let setPeerIdWithRevealedOptions: ((PeerId?, PeerId?) -> Void)?
|
||||||
let deletePeer: ((PeerId) -> Void)?
|
let deletePeer: ((PeerId) -> Void)?
|
||||||
|
let itemHighlighting: ContactItemHighlighting?
|
||||||
|
|
||||||
let selectable: Bool
|
let selectable: Bool
|
||||||
|
|
||||||
@ -132,7 +133,7 @@ class ContactsPeerItem: ListViewItem {
|
|||||||
|
|
||||||
let header: ListViewItemHeader?
|
let header: ListViewItemHeader?
|
||||||
|
|
||||||
init(theme: PresentationTheme, strings: PresentationStrings, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, account: Account, peerMode: ContactsPeerItemPeerMode, peer: ContactsPeerItemPeer, status: ContactsPeerItemStatus, badge: ContactsPeerItemBadge? = nil, enabled: Bool, selection: ContactsPeerItemSelection, editing: ContactsPeerItemEditing, options: [ItemListPeerItemRevealOption] = [], actionIcon: ContactsPeerItemActionIcon = .none, index: PeerNameIndex?, header: ListViewItemHeader?, action: @escaping (ContactsPeerItemPeer) -> Void, setPeerIdWithRevealedOptions: ((PeerId?, PeerId?) -> Void)? = nil, deletePeer: ((PeerId) -> Void)? = nil) {
|
init(theme: PresentationTheme, strings: PresentationStrings, sortOrder: PresentationPersonNameOrder, displayOrder: PresentationPersonNameOrder, account: Account, peerMode: ContactsPeerItemPeerMode, peer: ContactsPeerItemPeer, status: ContactsPeerItemStatus, badge: ContactsPeerItemBadge? = nil, enabled: Bool, selection: ContactsPeerItemSelection, editing: ContactsPeerItemEditing, options: [ItemListPeerItemRevealOption] = [], actionIcon: ContactsPeerItemActionIcon = .none, index: PeerNameIndex?, header: ListViewItemHeader?, action: @escaping (ContactsPeerItemPeer) -> Void, setPeerIdWithRevealedOptions: ((PeerId?, PeerId?) -> Void)? = nil, deletePeer: ((PeerId) -> Void)? = nil, itemHighlighting: ContactItemHighlighting? = nil) {
|
||||||
self.theme = theme
|
self.theme = theme
|
||||||
self.strings = strings
|
self.strings = strings
|
||||||
self.sortOrder = sortOrder
|
self.sortOrder = sortOrder
|
||||||
@ -151,7 +152,7 @@ class ContactsPeerItem: ListViewItem {
|
|||||||
self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions
|
self.setPeerIdWithRevealedOptions = setPeerIdWithRevealedOptions
|
||||||
self.deletePeer = deletePeer
|
self.deletePeer = deletePeer
|
||||||
self.header = header
|
self.header = header
|
||||||
|
self.itemHighlighting = itemHighlighting
|
||||||
self.selectable = self.enabled
|
self.selectable = self.enabled
|
||||||
|
|
||||||
if let index = index {
|
if let index = index {
|
||||||
@ -298,6 +299,9 @@ class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
private var avatarState: (Account, Peer?)?
|
private var avatarState: (Account, Peer?)?
|
||||||
|
|
||||||
|
private var isHighlighted: Bool = false
|
||||||
|
|
||||||
|
|
||||||
private var peerPresenceManager: PeerPresenceStatusManager?
|
private var peerPresenceManager: PeerPresenceStatusManager?
|
||||||
private var layoutParams: (ContactsPeerItem, ListViewItemLayoutParams, Bool, Bool, Bool)?
|
private var layoutParams: (ContactsPeerItem, ListViewItemLayoutParams, Bool, Bool, Bool)?
|
||||||
var chatPeer: Peer? {
|
var chatPeer: Peer? {
|
||||||
@ -365,25 +369,65 @@ class ContactsPeerItemNode: ItemListRevealOptionsItemNode {
|
|||||||
override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) {
|
override func setHighlighted(_ highlighted: Bool, at point: CGPoint, animated: Bool) {
|
||||||
super.setHighlighted(highlighted, at: point, animated: animated)
|
super.setHighlighted(highlighted, at: point, animated: animated)
|
||||||
|
|
||||||
if highlighted && self.selectionNode == nil {
|
self.isHighlighted = highlighted
|
||||||
self.highlightedBackgroundNode.alpha = 1.0
|
|
||||||
|
self.updateIsHighlighted(transition: (animated && !highlighted) ? .animated(duration: 0.3, curve: .easeInOut) : .immediate)
|
||||||
|
|
||||||
|
// if highlighted && self.selectionNode == nil {
|
||||||
|
// self.highlightedBackgroundNode.alpha = 1.0
|
||||||
|
// if self.highlightedBackgroundNode.supernode == nil {
|
||||||
|
// self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: self.separatorNode)
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if self.highlightedBackgroundNode.supernode != nil {
|
||||||
|
// if animated {
|
||||||
|
// self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in
|
||||||
|
// if let strongSelf = self {
|
||||||
|
// if completed {
|
||||||
|
// strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// self.highlightedBackgroundNode.alpha = 0.0
|
||||||
|
// } else {
|
||||||
|
// self.highlightedBackgroundNode.removeFromSupernode()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func updateIsHighlighted(transition: ContainedViewLayoutTransition) {
|
||||||
|
var reallyHighlighted = self.isHighlighted
|
||||||
|
if let item = self.item {
|
||||||
|
switch item.peer {
|
||||||
|
case let .peer(_, chatPeer):
|
||||||
|
if let peer = chatPeer {
|
||||||
|
if ChatLocation.peer(peer.id) == item.itemHighlighting?.chatLocation {
|
||||||
|
reallyHighlighted = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if reallyHighlighted {
|
||||||
if self.highlightedBackgroundNode.supernode == nil {
|
if self.highlightedBackgroundNode.supernode == nil {
|
||||||
self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: self.separatorNode)
|
self.insertSubnode(self.highlightedBackgroundNode, aboveSubnode: self.separatorNode)
|
||||||
|
self.highlightedBackgroundNode.alpha = 0.0
|
||||||
}
|
}
|
||||||
|
self.highlightedBackgroundNode.layer.removeAllAnimations()
|
||||||
|
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: 1.0)
|
||||||
} else {
|
} else {
|
||||||
if self.highlightedBackgroundNode.supernode != nil {
|
if self.highlightedBackgroundNode.supernode != nil {
|
||||||
if animated {
|
transition.updateAlpha(layer: self.highlightedBackgroundNode.layer, alpha: 0.0, completion: { [weak self] completed in
|
||||||
self.highlightedBackgroundNode.layer.animateAlpha(from: self.highlightedBackgroundNode.alpha, to: 0.0, duration: 0.4, completion: { [weak self] completed in
|
if let strongSelf = self {
|
||||||
if let strongSelf = self {
|
if completed {
|
||||||
if completed {
|
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
||||||
strongSelf.highlightedBackgroundNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
self.highlightedBackgroundNode.alpha = 0.0
|
})
|
||||||
} else {
|
|
||||||
self.highlightedBackgroundNode.removeFromSupernode()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ public enum NavigateToChatKeepStack {
|
|||||||
case never
|
case never
|
||||||
}
|
}
|
||||||
|
|
||||||
public func navigateToChatController(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, messageId: MessageId? = nil, botStart: ChatControllerInitialBotStart? = nil, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, animated: Bool = true, parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) {
|
public func navigateToChatController(navigationController: NavigationController, chatController: ChatController? = nil, context: AccountContext, chatLocation: ChatLocation, messageId: MessageId? = nil, botStart: ChatControllerInitialBotStart? = nil, keepStack: NavigateToChatKeepStack = .default, purposefulAction: (() -> Void)? = nil, scrollToEndIfExists: Bool = false, animated: Bool = true, options: NavigationAnimationOptions = [], parentGroupId: PeerGroupId? = nil, completion: @escaping () -> Void = {}) {
|
||||||
var found = false
|
var found = false
|
||||||
var isFirst = true
|
var isFirst = true
|
||||||
for controller in navigationController.viewControllers.reversed() {
|
for controller in navigationController.viewControllers.reversed() {
|
||||||
@ -72,9 +72,9 @@ public func navigateToChatController(navigationController: NavigationController,
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
if viewControllers.isEmpty {
|
if viewControllers.isEmpty {
|
||||||
navigationController.replaceAllButRootController(controller, animated: animated, completion: completion)
|
navigationController.replaceAllButRootController(controller, animated: animated, animationOptions: options, completion: completion)
|
||||||
} else {
|
} else {
|
||||||
navigationController.replaceControllersAndPush(controllers: viewControllers, controller: controller, animated: animated, completion: completion)
|
navigationController.replaceControllersAndPush(controllers: viewControllers, controller: controller, animated: animated, options: options, completion: completion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1243,7 +1243,7 @@ public func settingsController(context: AccountContext, accountManager: AccountM
|
|||||||
|
|
||||||
let controller = SettingsControllerImpl(currentContext: context, contextValue: contextValue, state: signal, tabBarItem: tabBarItem, accountsAndPeers: accountsAndPeers.get())
|
let controller = SettingsControllerImpl(currentContext: context, contextValue: contextValue, state: signal, tabBarItem: tabBarItem, accountsAndPeers: accountsAndPeers.get())
|
||||||
pushControllerImpl = { [weak controller] value in
|
pushControllerImpl = { [weak controller] value in
|
||||||
(controller?.navigationController as? NavigationController)?.replaceAllButRootController(value, animated: true)
|
(controller?.navigationController as? NavigationController)?.replaceAllButRootController(value, animated: true, animationOptions: [.removeOnMasterDetails])
|
||||||
}
|
}
|
||||||
presentControllerImpl = { [weak controller] value, arguments in
|
presentControllerImpl = { [weak controller] value, arguments in
|
||||||
controller?.present(value, in: .window(.root), with: arguments ?? ViewControllerPresentationArguments(presentationAnimation: .modalSheet), blockInteraction: true)
|
controller?.present(value, in: .window(.root), with: arguments ?? ViewControllerPresentationArguments(presentationAnimation: .modalSheet), blockInteraction: true)
|
||||||
|
|||||||
@ -26,16 +26,44 @@ public final class TelegramRootController: NavigationController {
|
|||||||
|
|
||||||
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
self.presentationData = context.sharedContext.currentPresentationData.with { $0 }
|
||||||
|
|
||||||
super.init(mode: .automaticMasterDetail, theme: NavigationControllerTheme(presentationTheme: self.presentationData.theme))
|
let navigationDetailsBackgroundMode: NavigationEmptyDetailsBackgoundMode?
|
||||||
|
switch presentationData.chatWallpaper {
|
||||||
|
case .color:
|
||||||
|
let image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/EmptyMasterDetailIcon"), color: presentationData.theme.chatList.messageTextColor.withAlphaComponent(0.2))
|
||||||
|
navigationDetailsBackgroundMode = image != nil ? .image(image!) : nil
|
||||||
|
default:
|
||||||
|
let image = chatControllerBackgroundImage(wallpaper: presentationData.chatWallpaper, mediaBox: context.account.postbox.mediaBox)
|
||||||
|
navigationDetailsBackgroundMode = image != nil ? .wallpaper(image!) : nil
|
||||||
|
}
|
||||||
|
|
||||||
|
super.init(mode: .automaticMasterDetail, theme: NavigationControllerTheme(presentationTheme: self.presentationData.theme), backgroundDetailsMode: navigationDetailsBackgroundMode)
|
||||||
|
|
||||||
self.presentationDataDisposable = (context.sharedContext.presentationData
|
self.presentationDataDisposable = (context.sharedContext.presentationData
|
||||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
|
|
||||||
|
if presentationData.chatWallpaper != strongSelf.presentationData.chatWallpaper {
|
||||||
|
let navigationDetailsBackgroundMode: NavigationEmptyDetailsBackgoundMode?
|
||||||
|
switch presentationData.chatWallpaper {
|
||||||
|
case .color:
|
||||||
|
let image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/EmptyMasterDetailIcon"), color: presentationData.theme.chatList.messageTextColor.withAlphaComponent(0.2))
|
||||||
|
navigationDetailsBackgroundMode = image != nil ? .image(image!) : nil
|
||||||
|
default:
|
||||||
|
let image = chatControllerBackgroundImage(wallpaper: presentationData.chatWallpaper, mediaBox: strongSelf.context.account.postbox.mediaBox)
|
||||||
|
navigationDetailsBackgroundMode = image != nil ? .wallpaper(image!) : nil
|
||||||
|
}
|
||||||
|
strongSelf.updateBackgroundDetailsMode(navigationDetailsBackgroundMode, transition: .immediate)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let previousTheme = strongSelf.presentationData.theme
|
let previousTheme = strongSelf.presentationData.theme
|
||||||
strongSelf.presentationData = presentationData
|
strongSelf.presentationData = presentationData
|
||||||
if previousTheme !== presentationData.theme {
|
if previousTheme !== presentationData.theme {
|
||||||
strongSelf.rootTabController?.updateTheme(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData), theme: TabBarControllerTheme(rootControllerTheme: presentationData.theme))
|
strongSelf.rootTabController?.updateTheme(navigationBarPresentationData: NavigationBarPresentationData(presentationData: presentationData), theme: TabBarControllerTheme(rootControllerTheme: presentationData.theme))
|
||||||
strongSelf.rootTabController?.statusBar.statusBarStyle = presentationData.theme.rootController.statusBar.style.style
|
strongSelf.rootTabController?.statusBar.statusBarStyle = presentationData.theme.rootController.statusBar.style.style
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user