mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2026-01-28 14:59:44 +00:00
AlertControllerNode: use blurred effect view for background
TextAlertController: exposed TextAlertContentActionNode
This commit is contained in:
@@ -3,9 +3,15 @@ import UIKit
|
||||
import AsyncDisplayKit
|
||||
|
||||
final class AlertControllerNode: ASDisplayNode {
|
||||
private let dimmingNode: ASDisplayNode
|
||||
private let centerDimView: UIImageView
|
||||
private let topDimView: UIView
|
||||
private let bottomDimView: UIView
|
||||
private let leftDimView: UIView
|
||||
private let rightDimView: UIView
|
||||
|
||||
private let containerNode: ASDisplayNode
|
||||
private let effectNode: ASDisplayNode
|
||||
private let backgroundNode: ASDisplayNode
|
||||
private let contentNode: AlertContentNode
|
||||
private let allowInputInset: Bool
|
||||
|
||||
@@ -15,14 +21,35 @@ final class AlertControllerNode: ASDisplayNode {
|
||||
|
||||
init(contentNode: AlertContentNode, theme: AlertControllerTheme, allowInputInset: Bool) {
|
||||
self.allowInputInset = allowInputInset
|
||||
self.dimmingNode = ASDisplayNode()
|
||||
self.dimmingNode.backgroundColor = UIColor(white: 0.0, alpha: 0.5)
|
||||
|
||||
let dimColor = UIColor(white: 0.0, alpha: 0.5)
|
||||
|
||||
self.centerDimView = UIImageView()
|
||||
self.centerDimView.image = generateStretchableFilledCircleImage(radius: 16.0, color: nil, backgroundColor: dimColor)
|
||||
|
||||
self.topDimView = UIView()
|
||||
self.topDimView.backgroundColor = dimColor
|
||||
self.topDimView.isUserInteractionEnabled = false
|
||||
|
||||
self.bottomDimView = UIView()
|
||||
self.bottomDimView.backgroundColor = dimColor
|
||||
self.bottomDimView.isUserInteractionEnabled = false
|
||||
|
||||
self.leftDimView = UIView()
|
||||
self.leftDimView.backgroundColor = dimColor
|
||||
self.leftDimView.isUserInteractionEnabled = false
|
||||
|
||||
self.rightDimView = UIView()
|
||||
self.rightDimView.backgroundColor = dimColor
|
||||
self.rightDimView.isUserInteractionEnabled = false
|
||||
|
||||
self.containerNode = ASDisplayNode()
|
||||
self.containerNode.backgroundColor = theme.backgroundColor
|
||||
self.containerNode.layer.cornerRadius = 14.0
|
||||
self.containerNode.layer.masksToBounds = true
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.backgroundColor = theme.backgroundColor
|
||||
|
||||
self.effectNode = ASDisplayNode(viewBlock: {
|
||||
return UIVisualEffectView(effect: UIBlurEffect(style: theme.backgroundType == .light ? .light : .dark))
|
||||
})
|
||||
@@ -31,10 +58,14 @@ final class AlertControllerNode: ASDisplayNode {
|
||||
|
||||
super.init()
|
||||
|
||||
self.addSubnode(self.dimmingNode)
|
||||
|
||||
self.addSubnode(self.effectNode)
|
||||
self.view.addSubview(self.centerDimView)
|
||||
self.view.addSubview(self.topDimView)
|
||||
self.view.addSubview(self.bottomDimView)
|
||||
self.view.addSubview(self.leftDimView)
|
||||
self.view.addSubview(self.rightDimView)
|
||||
|
||||
self.containerNode.addSubnode(self.effectNode)
|
||||
self.containerNode.addSubnode(self.backgroundNode)
|
||||
self.containerNode.addSubnode(self.contentNode)
|
||||
self.addSubnode(self.containerNode)
|
||||
|
||||
@@ -48,7 +79,8 @@ final class AlertControllerNode: ASDisplayNode {
|
||||
override func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.dimmingNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimmingNodeTapGesture(_:))))
|
||||
self.topDimView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimmingNodeTapGesture(_:))))
|
||||
self.bottomDimView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.dimmingNodeTapGesture(_:))))
|
||||
}
|
||||
|
||||
func updateTheme(_ theme: AlertControllerTheme) {
|
||||
@@ -60,13 +92,21 @@ final class AlertControllerNode: ASDisplayNode {
|
||||
}
|
||||
|
||||
func animateIn() {
|
||||
self.dimmingNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.centerDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.topDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.bottomDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.leftDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.rightDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
self.containerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
|
||||
self.containerNode.layer.animateSpring(from: 0.8 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5, initialVelocity: 0.0, removeOnCompletion: true, additive: false, completion: nil)
|
||||
}
|
||||
|
||||
func animateOut(completion: @escaping () -> Void) {
|
||||
self.dimmingNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.centerDimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.topDimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.bottomDimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.leftDimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.rightDimView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.containerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false)
|
||||
self.containerNode.layer.animateScale(from: 1.0, to: 0.8, duration: 0.4, removeOnCompletion: false, completion: { _ in
|
||||
completion()
|
||||
@@ -76,8 +116,6 @@ final class AlertControllerNode: ASDisplayNode {
|
||||
func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
||||
self.containerLayout = layout
|
||||
|
||||
transition.updateFrame(node: self.dimmingNode, frame: CGRect(origin: CGPoint(), size: layout.size))
|
||||
|
||||
var insetOptions: ContainerViewLayoutInsetOptions = [.statusBar]
|
||||
if self.allowInputInset {
|
||||
insetOptions.insert(.input)
|
||||
@@ -91,8 +129,15 @@ final class AlertControllerNode: ASDisplayNode {
|
||||
let containerSize = CGSize(width: contentSize.width, height: contentSize.height)
|
||||
let containerFrame = CGRect(origin: CGPoint(x: floor((layout.size.width - containerSize.width) / 2.0), y: contentAvailableFrame.minY + floor((contentAvailableFrame.size.height - containerSize.height) / 2.0)), size: containerSize)
|
||||
|
||||
transition.updateFrame(view: self.centerDimView, frame: containerFrame)
|
||||
transition.updateFrame(view: self.topDimView, frame: CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: containerFrame.minY)))
|
||||
transition.updateFrame(view: self.bottomDimView, frame: CGRect(origin: CGPoint(x: 0.0, y: containerFrame.maxY), size: CGSize(width: layout.size.width, height: layout.size.height - containerFrame.maxY)))
|
||||
transition.updateFrame(view: self.leftDimView, frame: CGRect(origin: CGPoint(x: 0.0, y: containerFrame.minY), size: CGSize(width: containerFrame.minX, height: containerFrame.height)))
|
||||
transition.updateFrame(view: self.rightDimView, frame: CGRect(origin: CGPoint(x: containerFrame.maxX, y: containerFrame.minY), size: CGSize(width: layout.size.width - containerFrame.maxX, height: containerFrame.height)))
|
||||
|
||||
transition.updateFrame(node: self.containerNode, frame: containerFrame)
|
||||
transition.updateFrame(node: self.effectNode, frame: containerFrame)
|
||||
transition.updateFrame(node: self.effectNode, frame: CGRect(origin: CGPoint(), size: containerFrame.size))
|
||||
transition.updateFrame(node: self.backgroundNode, frame: CGRect(origin: CGPoint(), size: containerFrame.size))
|
||||
transition.updateFrame(node: self.contentNode, frame: CGRect(origin: CGPoint(), size: containerFrame.size))
|
||||
}
|
||||
|
||||
|
||||
@@ -22,18 +22,20 @@ public struct TextAlertAction {
|
||||
}
|
||||
}
|
||||
|
||||
private final class TextAlertContentActionNode: HighlightableButtonNode {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
|
||||
public final class TextAlertContentActionNode: HighlightableButtonNode {
|
||||
private var theme: AlertControllerTheme
|
||||
let action: TextAlertAction
|
||||
|
||||
init(theme: AlertControllerTheme, action: TextAlertAction) {
|
||||
private let backgroundNode: ASDisplayNode
|
||||
|
||||
public init(theme: AlertControllerTheme, action: TextAlertAction) {
|
||||
self.theme = theme
|
||||
self.action = action
|
||||
|
||||
self.backgroundNode = ASDisplayNode()
|
||||
self.backgroundNode.isLayerBacked = true
|
||||
self.backgroundNode.alpha = 0.0
|
||||
|
||||
self.action = action
|
||||
|
||||
super.init()
|
||||
|
||||
self.titleNode.maximumNumberOfLines = 2
|
||||
@@ -56,16 +58,27 @@ private final class TextAlertContentActionNode: HighlightableButtonNode {
|
||||
self.updateTheme(theme)
|
||||
}
|
||||
|
||||
func updateTheme(_ theme: AlertControllerTheme) {
|
||||
public var actionEnabled: Bool = true {
|
||||
didSet {
|
||||
self.isUserInteractionEnabled = self.actionEnabled
|
||||
self.updateTitle()
|
||||
}
|
||||
}
|
||||
|
||||
public func updateTheme(_ theme: AlertControllerTheme) {
|
||||
self.theme = theme
|
||||
self.backgroundNode.backgroundColor = theme.highlightedItemColor
|
||||
|
||||
self.updateTitle()
|
||||
}
|
||||
|
||||
private func updateTitle() {
|
||||
var font = Font.regular(17.0)
|
||||
var color = theme.accentColor
|
||||
var color: UIColor
|
||||
switch self.action.type {
|
||||
case .defaultAction, .genericAction:
|
||||
break
|
||||
color = self.actionEnabled ? self.theme.accentColor : self.theme.disabledColor
|
||||
case .destructiveAction:
|
||||
color = theme.destructiveColor
|
||||
color = self.actionEnabled ? self.theme.destructiveColor : self.theme.disabledColor
|
||||
}
|
||||
switch self.action.type {
|
||||
case .defaultAction:
|
||||
@@ -76,7 +89,7 @@ private final class TextAlertContentActionNode: HighlightableButtonNode {
|
||||
self.setAttributedTitle(NSAttributedString(string: self.action.title, font: font, textColor: color, paragraphAlignment: .center), for: [])
|
||||
}
|
||||
|
||||
override func didLoad() {
|
||||
override public func didLoad() {
|
||||
super.didLoad()
|
||||
|
||||
self.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside)
|
||||
@@ -86,7 +99,7 @@ private final class TextAlertContentActionNode: HighlightableButtonNode {
|
||||
self.action.action()
|
||||
}
|
||||
|
||||
override func layout() {
|
||||
override public func layout() {
|
||||
super.layout()
|
||||
|
||||
self.backgroundNode.frame = self.bounds
|
||||
@@ -203,16 +216,17 @@ public final class TextAlertContentNode: AlertContentNode {
|
||||
override public func updateTheme(_ theme: AlertControllerTheme) {
|
||||
self.theme = theme
|
||||
|
||||
let textFont: UIFont
|
||||
if let titleNode = self.titleNode {
|
||||
titleNode.attributedText = NSAttributedString(string: titleNode.attributedText?.string ?? "", font: Font.medium(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
textFont = Font.regular(13.0)
|
||||
} else {
|
||||
textFont = Font.semibold(17.0)
|
||||
if let titleNode = self.titleNode, let attributedText = titleNode.attributedText {
|
||||
let updatedText = NSMutableAttributedString(attributedString: attributedText)
|
||||
updatedText.addAttribute(NSAttributedStringKey.foregroundColor, value: theme.primaryColor, range: NSRange(location: 0, length: updatedText.length))
|
||||
titleNode.attributedText = updatedText
|
||||
}
|
||||
|
||||
self.textNode.attributedText = NSAttributedString(string: self.textNode.attributedText?.string ?? "", font: textFont, textColor: theme.primaryColor, paragraphAlignment: .center)
|
||||
|
||||
if let attributedText = self.textNode.attributedText {
|
||||
let updatedText = NSMutableAttributedString(attributedString: attributedText)
|
||||
updatedText.addAttribute(NSAttributedStringKey.foregroundColor, value: theme.primaryColor, range: NSRange(location: 0, length: updatedText.length))
|
||||
self.textNode.attributedText = updatedText
|
||||
}
|
||||
|
||||
self.actionNodesSeparator.backgroundColor = theme.separatorColor
|
||||
for actionNode in self.actionNodes {
|
||||
actionNode.updateTheme(theme)
|
||||
|
||||
Reference in New Issue
Block a user