mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 06:35:51 +00:00
Temp
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import Display
|
||||
import AsyncDisplayKit
|
||||
import AppBundle
|
||||
|
||||
private let innerCircleDiameter: CGFloat = 110.0
|
||||
private let outerCircleDiameter = innerCircleDiameter + 50.0
|
||||
private let outerCircleMinScale = innerCircleDiameter / outerCircleDiameter
|
||||
private let innerCircleImage = generateFilledCircleImage(diameter: innerCircleDiameter, color: UIColor(rgb: 0x007ee5))
|
||||
private let outerCircleImage = generateFilledCircleImage(diameter: outerCircleDiameter, color: UIColor(rgb: 0x007ee5, alpha: 0.2))
|
||||
private let micIcon = generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Text/IconMicrophone"), color: .white)!
|
||||
|
||||
private final class ChatTextInputAudioRecordingOverlayDisplayLinkTarget: NSObject {
|
||||
private let f: () -> Void
|
||||
|
||||
init(_ f: @escaping () -> Void) {
|
||||
self.f = f
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
@objc func displayLinkEvent() {
|
||||
self.f()
|
||||
}
|
||||
}
|
||||
|
||||
final class ChatTextInputAudioRecordingOverlay {
|
||||
private weak var anchorView: UIView?
|
||||
|
||||
private let containerNode: ASDisplayNode
|
||||
private let circleContainerNode: ASDisplayNode
|
||||
private let innerCircleNode: ASImageNode
|
||||
private let outerCircleNode: ASImageNode
|
||||
private let iconNode: ASImageNode
|
||||
|
||||
var animationStartTime: Double?
|
||||
var displayLink: CADisplayLink?
|
||||
var currentLevel: CGFloat = 0.0
|
||||
var inputLevel: CGFloat = 0.0
|
||||
var animatedIn = false
|
||||
|
||||
var dismissFactor: CGFloat = 1.0 {
|
||||
didSet {
|
||||
let scale = max(0.3, min(self.dismissFactor, 1.0))
|
||||
self.circleContainerNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
init(anchorView: UIView) {
|
||||
self.anchorView = anchorView
|
||||
|
||||
self.containerNode = ASDisplayNode()
|
||||
self.containerNode.isLayerBacked = true
|
||||
|
||||
self.circleContainerNode = ASDisplayNode()
|
||||
self.circleContainerNode.isLayerBacked = true
|
||||
|
||||
self.outerCircleNode = ASImageNode()
|
||||
self.outerCircleNode.displayWithoutProcessing = true
|
||||
self.outerCircleNode.displaysAsynchronously = false
|
||||
self.outerCircleNode.isLayerBacked = true
|
||||
self.outerCircleNode.image = outerCircleImage
|
||||
self.outerCircleNode.frame = CGRect(origin: CGPoint(x: -outerCircleDiameter / 2.0, y: -outerCircleDiameter / 2.0), size: CGSize(width: outerCircleDiameter, height: outerCircleDiameter))
|
||||
|
||||
self.innerCircleNode = ASImageNode()
|
||||
self.innerCircleNode.displayWithoutProcessing = true
|
||||
self.innerCircleNode.displaysAsynchronously = false
|
||||
self.innerCircleNode.isLayerBacked = true
|
||||
self.innerCircleNode.image = innerCircleImage
|
||||
self.innerCircleNode.frame = CGRect(origin: CGPoint(x: -innerCircleDiameter / 2.0, y: -innerCircleDiameter / 2.0), size: CGSize(width: innerCircleDiameter, height: innerCircleDiameter))
|
||||
|
||||
self.iconNode = ASImageNode()
|
||||
self.iconNode.displayWithoutProcessing = true
|
||||
self.iconNode.displaysAsynchronously = false
|
||||
self.iconNode.isLayerBacked = true
|
||||
self.iconNode.image = micIcon
|
||||
self.iconNode.frame = CGRect(origin: CGPoint(x: -micIcon.size.width / 2.0, y: -micIcon.size.height / 2.0), size: micIcon.size)
|
||||
|
||||
self.circleContainerNode.addSubnode(self.outerCircleNode)
|
||||
self.circleContainerNode.addSubnode(self.innerCircleNode)
|
||||
self.containerNode.addSubnode(self.circleContainerNode)
|
||||
self.containerNode.addSubnode(self.iconNode)
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.displayLink?.invalidate()
|
||||
}
|
||||
|
||||
func present(in window: UIWindow) {
|
||||
if let anchorView = self.anchorView, let anchorSuperview = anchorView.superview {
|
||||
if let displayLink = self.displayLink {
|
||||
displayLink.invalidate()
|
||||
}
|
||||
self.displayLink = CADisplayLink(target: ChatTextInputAudioRecordingOverlayDisplayLinkTarget({ [weak self] in
|
||||
self?.displayLinkEvent()
|
||||
}), selector: #selector(ChatTextInputAudioRecordingOverlayDisplayLinkTarget.displayLinkEvent))
|
||||
|
||||
let convertedCenter = anchorSuperview.convert(anchorView.center, to: window)
|
||||
self.containerNode.position = CGPoint(x: convertedCenter.x, y: convertedCenter.y)
|
||||
window.addSubnode(self.containerNode)
|
||||
|
||||
self.innerCircleNode.layer.animateSpring(from: 0.2 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5)
|
||||
self.outerCircleNode.layer.transform = CATransform3DMakeScale(outerCircleMinScale, outerCircleMinScale, 1.0)
|
||||
self.outerCircleNode.layer.animateSpring(from: 0.2 as NSNumber, to: outerCircleMinScale as NSNumber, keyPath: "transform.scale", duration: 0.5)
|
||||
self.innerCircleNode.layer.animateAlpha(from: 0.2, to: 1.0, duration: 0.15)
|
||||
self.outerCircleNode.layer.animateAlpha(from: 0.2, to: 1.0, duration: 0.15)
|
||||
self.iconNode.layer.animateAlpha(from: 0.2, to: 1.0, duration: 0.15)
|
||||
|
||||
self.animatedIn = true
|
||||
self.animationStartTime = CACurrentMediaTime()
|
||||
self.displayLink?.add(to: RunLoop.main, forMode: .common)
|
||||
self.displayLink?.isPaused = false
|
||||
}
|
||||
}
|
||||
|
||||
func dismiss() {
|
||||
self.displayLink?.invalidate()
|
||||
self.displayLink = nil
|
||||
|
||||
var innerCompleted = false
|
||||
var outerCompleted = false
|
||||
var iconCompleted = false
|
||||
|
||||
var containerNodeRef: ASDisplayNode? = self.containerNode
|
||||
|
||||
var completion: () -> Void = {
|
||||
if let containerNode = containerNodeRef, innerCompleted, outerCompleted, iconCompleted {
|
||||
containerNode.removeFromSupernode()
|
||||
containerNodeRef = nil
|
||||
}
|
||||
}
|
||||
|
||||
self.innerCircleNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false)
|
||||
self.innerCircleNode.layer.animateScale(from: 1.0, to: 0.2, duration: 0.18, removeOnCompletion: false, completion: { _ in
|
||||
innerCompleted = true
|
||||
completion()
|
||||
})
|
||||
|
||||
var currentScaleValue: CGFloat = outerCircleMinScale
|
||||
if let currentScale = self.outerCircleNode.layer.value(forKeyPath: "transform.scale") as? AnyObject, currentScale.responds(to: Selector("floatValue")) {
|
||||
currentScaleValue = CGFloat(currentScale.floatValue)
|
||||
}
|
||||
|
||||
self.outerCircleNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false)
|
||||
self.outerCircleNode.layer.animateScale(from: currentScaleValue, to: 0.2, duration: 0.18, removeOnCompletion: false, completion: { _ in
|
||||
outerCompleted = true
|
||||
completion()
|
||||
})
|
||||
|
||||
self.iconNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.18, removeOnCompletion: false, completion: { _ in
|
||||
iconCompleted = true
|
||||
completion()
|
||||
})
|
||||
}
|
||||
|
||||
private func displayLinkEvent() {
|
||||
let t = CACurrentMediaTime()
|
||||
if let animationStartTime = self.animationStartTime {
|
||||
if t > animationStartTime + 0.5 {
|
||||
self.currentLevel = self.currentLevel * 0.8 + self.inputLevel * 0.2
|
||||
|
||||
let scale = outerCircleMinScale + self.currentLevel * (1.0 - outerCircleMinScale)
|
||||
self.outerCircleNode.transform = CATransform3DMakeScale(scale, scale, 1.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addImmediateMicLevel(_ level: CGFloat) {
|
||||
self.inputLevel = level
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user