mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-02 00:17:02 +00:00
Added recent stickers clearing Added sending logs via email Added forward recipient change on forward acccessory panel tap Tweaked undo panel design Various UI fixes
169 lines
8.8 KiB
Swift
169 lines
8.8 KiB
Swift
import Foundation
|
|
import AsyncDisplayKit
|
|
import Display
|
|
import SwiftSignalKit
|
|
|
|
final class UndoOverlayControllerNode: ViewControllerTracingNode {
|
|
private let statusNode: RadialStatusNode
|
|
private let timerTextNode: ImmediateTextNode
|
|
private let textNode: ImmediateTextNode
|
|
private let buttonTextNode: ImmediateTextNode
|
|
private let buttonNode: HighlightTrackingButtonNode
|
|
private let panelNode: ASDisplayNode
|
|
private let panelWrapperNode: ASDisplayNode
|
|
private let action: (Bool) -> Void
|
|
private let dismiss: () -> Void
|
|
|
|
private let effectView: UIVisualEffectView
|
|
|
|
private var remainingSeconds = 5
|
|
private var timer: SwiftSignalKit.Timer?
|
|
|
|
private var validLayout: ContainerViewLayout?
|
|
|
|
init(presentationData: PresentationData, text: String, action: @escaping (Bool) -> Void, dismiss: @escaping () -> Void) {
|
|
self.action = action
|
|
self.dismiss = dismiss
|
|
|
|
self.statusNode = RadialStatusNode(backgroundNodeColor: .clear)
|
|
|
|
self.timerTextNode = ImmediateTextNode()
|
|
self.timerTextNode.displaysAsynchronously = false
|
|
|
|
self.textNode = ImmediateTextNode()
|
|
self.textNode.displaysAsynchronously = false
|
|
|
|
self.textNode.attributedText = NSAttributedString(string: text, font: Font.regular(15.0), textColor: .white)
|
|
|
|
self.buttonTextNode = ImmediateTextNode()
|
|
self.buttonTextNode.displaysAsynchronously = false
|
|
self.buttonTextNode.attributedText = NSAttributedString(string: presentationData.strings.Undo_Undo, font: Font.regular(17.0), textColor: UIColor(rgb: 0x5ac8fa))
|
|
|
|
self.buttonNode = HighlightTrackingButtonNode()
|
|
|
|
self.panelNode = ASDisplayNode()
|
|
self.panelNode.backgroundColor = .clear
|
|
self.panelNode.clipsToBounds = true
|
|
self.panelNode.cornerRadius = 9.0
|
|
|
|
self.panelWrapperNode = ASDisplayNode()
|
|
|
|
self.effectView = UIVisualEffectView(effect: UIBlurEffect(style: .dark))
|
|
|
|
super.init()
|
|
|
|
self.panelWrapperNode.addSubnode(self.timerTextNode)
|
|
self.panelWrapperNode.addSubnode(self.statusNode)
|
|
self.panelWrapperNode.addSubnode(self.textNode)
|
|
self.panelWrapperNode.addSubnode(self.buttonTextNode)
|
|
self.panelWrapperNode.addSubnode(self.buttonNode)
|
|
self.addSubnode(self.panelNode)
|
|
self.addSubnode(self.panelWrapperNode)
|
|
|
|
self.buttonNode.highligthedChanged = { [weak self] highlighted in
|
|
if let strongSelf = self {
|
|
if highlighted {
|
|
strongSelf.buttonTextNode.layer.removeAnimation(forKey: "opacity")
|
|
strongSelf.buttonTextNode.alpha = 0.4
|
|
} else {
|
|
strongSelf.buttonTextNode.alpha = 1.0
|
|
strongSelf.buttonTextNode.layer.animateAlpha(from: 0.4, to: 1.0, duration: 0.2)
|
|
}
|
|
}
|
|
}
|
|
self.buttonNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside)
|
|
|
|
self.checkTimer()
|
|
}
|
|
|
|
override func didLoad() {
|
|
super.didLoad()
|
|
self.panelNode.view.addSubview(self.effectView)
|
|
}
|
|
|
|
@objc private func buttonPressed() {
|
|
self.action(false)
|
|
self.dismiss()
|
|
}
|
|
|
|
private func checkTimer() {
|
|
if self.timer != nil {
|
|
self.remainingSeconds -= 1
|
|
}
|
|
if self.remainingSeconds == 0 {
|
|
self.action(true)
|
|
self.dismiss()
|
|
} else {
|
|
if !self.timerTextNode.bounds.size.width.isZero, let snapshot = self.timerTextNode.view.snapshotContentTree() {
|
|
self.panelNode.view.insertSubview(snapshot, aboveSubview: self.timerTextNode.view)
|
|
snapshot.frame = self.timerTextNode.frame
|
|
self.timerTextNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.12)
|
|
self.timerTextNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -10.0), to: CGPoint(), duration: 0.12, removeOnCompletion: false, additive: true)
|
|
snapshot.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.12, removeOnCompletion: false)
|
|
snapshot.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: 10.0), duration: 0.12, removeOnCompletion: false, additive: true, completion: { [weak snapshot] _ in
|
|
snapshot?.removeFromSuperview()
|
|
})
|
|
}
|
|
self.timerTextNode.attributedText = NSAttributedString(string: "\(self.remainingSeconds)", font: Font.regular(16.0), textColor: .white)
|
|
if let validLayout = self.validLayout {
|
|
self.containerLayoutUpdated(layout: validLayout, transition: .immediate)
|
|
}
|
|
let timer = SwiftSignalKit.Timer(timeout: 1.0, repeat: false, completion: { [weak self] in
|
|
self?.checkTimer()
|
|
}, queue: .mainQueue())
|
|
self.timer = timer
|
|
timer.start()
|
|
}
|
|
}
|
|
|
|
func containerLayoutUpdated(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {
|
|
let firstLayout = self.validLayout == nil
|
|
self.validLayout = layout
|
|
|
|
let leftInset: CGFloat = 50.0
|
|
let rightInset: CGFloat = 16.0
|
|
let contentHeight: CGFloat = 49.0
|
|
let margin: CGFloat = 16.0
|
|
|
|
let panelFrame = CGRect(origin: CGPoint(x: margin, y: layout.size.height - contentHeight - layout.intrinsicInsets.bottom - margin - 49.0), size: CGSize(width: layout.size.width - margin * 2.0, height: contentHeight))
|
|
let panelWrapperFrame = CGRect(origin: CGPoint(x: margin, y: layout.size.height - contentHeight - layout.intrinsicInsets.bottom - margin - 49.0), size: CGSize(width: layout.size.width - margin * 2.0 + margin, height: contentHeight))
|
|
transition.updateFrame(node: self.panelNode, frame: panelFrame)
|
|
transition.updateFrame(node: self.panelWrapperNode, frame: panelWrapperFrame)
|
|
self.effectView.frame = CGRect(x: 0.0, y: 0.0, width: layout.size.width - margin * 2.0, height: contentHeight)
|
|
|
|
let buttonTextSize = self.buttonTextNode.updateLayout(CGSize(width: 200.0, height: .greatestFiniteMagnitude))
|
|
let buttonTextFrame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - rightInset - buttonTextSize.width - margin * 2.0, y: floor((contentHeight - buttonTextSize.height) / 2.0)), size: buttonTextSize)
|
|
transition.updateFrame(node: self.buttonTextNode, frame: buttonTextFrame)
|
|
self.buttonNode.frame = CGRect(origin: CGPoint(x: layout.size.width - layout.safeInsets.right - rightInset - buttonTextSize.width - 8.0 - margin, y: 0.0), size: CGSize(width: layout.safeInsets.right + rightInset + buttonTextSize.width + 8.0 + margin, height: contentHeight))
|
|
|
|
let textSize = self.textNode.updateLayout(CGSize(width: buttonTextFrame.minX - 8.0 - leftInset - layout.safeInsets.left - layout.safeInsets.right - margin * 2.0, height: .greatestFiniteMagnitude))
|
|
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + leftInset, y: floor((contentHeight - textSize.height) / 2.0)), size: textSize))
|
|
|
|
let timerTextSize = self.timerTextNode.updateLayout(CGSize(width: 100.0, height: 100.0))
|
|
transition.updateFrame(node: self.timerTextNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((leftInset - timerTextSize.width) / 2.0), y: floor((contentHeight - timerTextSize.height) / 2.0)), size: timerTextSize))
|
|
let statusSize: CGFloat = 30.0
|
|
transition.updateFrame(node: self.statusNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + floor((leftInset - statusSize) / 2.0), y: floor((contentHeight - statusSize) / 2.0)), size: CGSize(width: statusSize, height: statusSize)))
|
|
if firstLayout {
|
|
self.statusNode.transitionToState(.secretTimeout(color: .white, icon: nil, beginTime: CFAbsoluteTimeGetCurrent() + NSTimeIntervalSince1970, timeout: Double(self.remainingSeconds), sparks: false), completion: {})
|
|
}
|
|
}
|
|
|
|
func animateIn() {
|
|
self.panelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
|
}
|
|
|
|
func animateOut(completion: @escaping () -> Void) {
|
|
self.panelNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, delay: 0.0, timingFunction: kCAMediaTimingFunctionEaseOut, removeOnCompletion: false, completion: { _ in })
|
|
self.panelWrapperNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, delay: 0.0, timingFunction: kCAMediaTimingFunctionEaseOut, removeOnCompletion: false) { _ in
|
|
completion()
|
|
}
|
|
}
|
|
|
|
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
|
if !self.panelNode.frame.contains(point) {
|
|
return nil
|
|
}
|
|
return super.hitTest(point, with: event)
|
|
}
|
|
}
|