Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios

This commit is contained in:
overtake 2021-04-08 18:17:09 +04:00
commit c6b5b23f2a
9 changed files with 1802 additions and 1750 deletions

View File

@ -5774,6 +5774,8 @@ Sorry for the inconvenience.";
"VoiceChat.CreateNewVoiceChatText" = "Voice chat ended. Start a new one?"; "VoiceChat.CreateNewVoiceChatText" = "Voice chat ended. Start a new one?";
"VoiceChat.CreateNewVoiceChatStart" = "Start"; "VoiceChat.CreateNewVoiceChatStart" = "Start";
"VoiceChat.CreateNewVoiceChatStartNow" = "Start Now";
"VoiceChat.CreateNewVoiceChatSchedule" = "Schedule";
"PUSH_CHAT_VOICECHAT_START" = "%2$@|%1$@ started a voice chat"; "PUSH_CHAT_VOICECHAT_START" = "%2$@|%1$@ started a voice chat";
"PUSH_CHAT_VOICECHAT_INVITE" = "%2$@|%1$@ invited %3$@ to the voice chat"; "PUSH_CHAT_VOICECHAT_INVITE" = "%2$@|%1$@ invited %3$@ to the voice chat";

View File

@ -300,8 +300,8 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
private func updateJoinButton() { private func updateJoinButton() {
if self.isScheduled { if self.isScheduled {
let purple = UIColor(rgb: 0x3252ef) let purple = UIColor(rgb: 0x5d4ed1)
let pink = UIColor(rgb: 0xef436c) let pink = UIColor(rgb: 0xea436f)
self.joinButtonBackgroundNode.image = generateGradientImage(size: CGSize(width: 100.0, height: 1.0), colors: [purple, pink], locations: [0.0, 1.0], direction: .horizontal) self.joinButtonBackgroundNode.image = generateGradientImage(size: CGSize(width: 100.0, height: 1.0), colors: [purple, pink], locations: [0.0, 1.0], direction: .horizontal)
self.joinButtonBackgroundNode.backgroundColor = nil self.joinButtonBackgroundNode.backgroundColor = nil
} else { } else {

View File

@ -61,7 +61,7 @@ final class VoiceChatActionButton: HighlightTrackingButtonNode {
private let containerNode: ASDisplayNode private let containerNode: ASDisplayNode
private let backgroundNode: VoiceChatActionButtonBackgroundNode private let backgroundNode: VoiceChatActionButtonBackgroundNode
private let iconNode: VoiceChatActionButtonIconNode private let iconNode: VoiceChatActionButtonIconNode
private let titleLabel: ImmediateTextNode let titleLabel: ImmediateTextNode
private let subtitleLabel: ImmediateTextNode private let subtitleLabel: ImmediateTextNode
private let buttonTitleLabel: ImmediateTextNode private let buttonTitleLabel: ImmediateTextNode
@ -1005,14 +1005,17 @@ private final class VoiceChatActionButtonBackgroundNode: ASDisplayNode {
self.maskCircleLayer.path = largerCirclePath self.maskCircleLayer.path = largerCirclePath
self.maskIsCircle = true self.maskIsCircle = true
self.maskCircleLayer.animateSpring(from: previousPath as AnyObject, to: largerCirclePath as AnyObject, keyPath: "path", duration: 0.42, initialVelocity: 0.0, damping: 104.0) self.maskCircleLayer.animateSpring(from: previousPath as AnyObject, to: largerCirclePath as AnyObject, keyPath: "path", duration: 0.6, initialVelocity: 0.0, damping: 100.0)
self.maskBlobView.isHidden = false self.maskBlobView.isHidden = false
self.maskBlobView.startAnimating() self.maskBlobView.startAnimating()
self.maskBlobView.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.45) self.maskBlobView.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.6, damping: 100.0)
let initialScale: CGFloat = ((self.maskGradientLayer.value(forKeyPath: "presentationLayer.transform.scale.x") as? NSNumber)?.floatValue).flatMap({ CGFloat($0) }) ?? (((self.maskGradientLayer.value(forKeyPath: "transform.scale.x") as? NSNumber)?.floatValue).flatMap({ CGFloat($0) }) ?? 0.8) self.disableGlowAnimations = true
self.maskGradientLayer.animateSpring(from: initialScale as NSNumber, to: 0.85 as NSNumber, keyPath: "transform.scale", duration: 0.45) self.maskGradientLayer.removeAllAnimations()
self.maskGradientLayer.animateSpring(from: 0.3 as NSNumber, to: 0.85 as NSNumber, keyPath: "transform.scale", duration: 0.45, completion: { [weak self] _ in
self?.disableGlowAnimations = false
})
} }
var isActive = false var isActive = false

View File

@ -2311,42 +2311,47 @@ public final class VoiceChatController: ViewController {
} }
private func transitionToScheduled() { private func transitionToScheduled() {
let springDuration: Double = 0.6
let springDamping: CGFloat = 100.0
self.optionsButton.alpha = 1.0 self.optionsButton.alpha = 1.0
self.optionsButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.optionsButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.optionsButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.42, damping: 104.0) self.optionsButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, damping: springDamping)
self.optionsButton.isUserInteractionEnabled = true self.optionsButton.isUserInteractionEnabled = true
self.closeButton.alpha = 1.0 self.closeButton.alpha = 1.0
self.closeButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.closeButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.closeButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.42, damping: 104.0) self.closeButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, damping: springDamping)
self.closeButton.isUserInteractionEnabled = true self.closeButton.isUserInteractionEnabled = true
self.audioButton.alpha = 1.0 self.audioButton.alpha = 1.0
self.audioButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.audioButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.audioButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.42, damping: 104.0) self.audioButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, damping: springDamping)
self.audioButton.isUserInteractionEnabled = true self.audioButton.isUserInteractionEnabled = true
self.leaveButton.alpha = 1.0 self.leaveButton.alpha = 1.0
self.leaveButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.leaveButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.leaveButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.42, damping: 104.0) self.leaveButton.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: springDuration, damping: springDamping)
self.leaveButton.isUserInteractionEnabled = true self.leaveButton.isUserInteractionEnabled = true
self.scheduleCancelButton.alpha = 0.0 self.scheduleCancelButton.alpha = 0.0
self.scheduleCancelButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2) self.scheduleCancelButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15)
self.scheduleCancelButton.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: 26.0), duration: 0.2, removeOnCompletion: false, additive: true) self.scheduleCancelButton.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: 26.0), duration: 0.2, removeOnCompletion: false, additive: true)
self.actionButton.titleLabel.layer.animatePosition(from: CGPoint(x: 0.0, y: -26.0), to: CGPoint(), duration: 0.2, additive: true)
if let pickerView = self.pickerView { if let pickerView = self.pickerView {
pickerView.alpha = 0.0 pickerView.alpha = 0.0
pickerView.layer.animateScale(from: 1.0, to: 0.1, duration: 0.2) pickerView.layer.animateScale(from: 1.0, to: 0.25, duration: 0.15, removeOnCompletion: false)
pickerView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
pickerView.isUserInteractionEnabled = false pickerView.isUserInteractionEnabled = false
} }
self.timerNode.alpha = 1.0 self.timerNode.alpha = 1.0
self.timerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.timerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25)
self.timerNode.layer.animateSpring(from: 0.4 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.3, damping: 104.0)
self.timerNode.animateIn() self.timerNode.animateIn()
self.updateTitle(transition: .animated(duration: 0.2, curve: .easeInOut)) self.updateTitle(slide: true, transition: .animated(duration: 0.2, curve: .easeInOut))
} }
private func transitionToCall() { private func transitionToCall() {
@ -2354,6 +2359,7 @@ public final class VoiceChatController: ViewController {
self.listNode.alpha = 1.0 self.listNode.alpha = 1.0
self.listNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.listNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
self.listNode.isUserInteractionEnabled = true
self.timerNode.alpha = 0.0 self.timerNode.alpha = 0.0
self.timerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2) self.timerNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2)
@ -2939,7 +2945,7 @@ public final class VoiceChatController: ViewController {
self.updateTitle(transition: transition) self.updateTitle(transition: transition)
} }
private func updateTitle(transition: ContainedViewLayoutTransition) { private func updateTitle(slide: Bool = false, transition: ContainedViewLayoutTransition) {
guard let (layout, _) = self.validLayout else { guard let (layout, _) = self.validLayout else {
return return
} }
@ -2976,7 +2982,7 @@ public final class VoiceChatController: ViewController {
size.width = floor(min(size.width, size.height) * 0.5) size.width = floor(min(size.width, size.height) * 0.5)
} }
self.titleNode.update(size: CGSize(width: size.width, height: 44.0), title: title, subtitle: subtitle, transition: transition) self.titleNode.update(size: CGSize(width: size.width, height: 44.0), title: title, subtitle: subtitle, slide: slide, transition: transition)
} }
private func updateButtons(animated: Bool) { private func updateButtons(animated: Bool) {
@ -3393,6 +3399,7 @@ public final class VoiceChatController: ViewController {
if self.callState?.scheduleTimestamp != nil && self.listNode.alpha > 0.0 { if self.callState?.scheduleTimestamp != nil && self.listNode.alpha > 0.0 {
self.listNode.alpha = 0.0 self.listNode.alpha = 0.0
self.listNode.isUserInteractionEnabled = false
self.backgroundNode.backgroundColor = panelBackgroundColor self.backgroundNode.backgroundColor = panelBackgroundColor
self.updateIsFullscreen(false) self.updateIsFullscreen(false)
} }

View File

@ -26,10 +26,18 @@ final class VoiceChatTimerNode: ASDisplayNode {
private var updateTimer: SwiftSignalKit.Timer? private var updateTimer: SwiftSignalKit.Timer?
private let hierarchyTrackingNode: HierarchyTrackingNode
private var isCurrentlyInHierarchy = false
init(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) { init(strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat) {
self.strings = strings self.strings = strings
self.dateTimeFormat = dateTimeFormat self.dateTimeFormat = dateTimeFormat
var updateInHierarchy: ((Bool) -> Void)?
self.hierarchyTrackingNode = HierarchyTrackingNode({ value in
updateInHierarchy?(value)
})
self.titleNode = ImmediateTextNode() self.titleNode = ImmediateTextNode()
self.subtitleNode = ImmediateTextNode() self.subtitleNode = ImmediateTextNode()
@ -37,7 +45,10 @@ final class VoiceChatTimerNode: ASDisplayNode {
super.init() super.init()
self.addSubnode(self.hierarchyTrackingNode)
self.allowsGroupOpacity = true self.allowsGroupOpacity = true
self.isUserInteractionEnabled = false
self.foregroundGradientLayer.type = .radial self.foregroundGradientLayer.type = .radial
self.foregroundGradientLayer.colors = [pink.cgColor, purple.cgColor, purple.cgColor] self.foregroundGradientLayer.colors = [pink.cgColor, purple.cgColor, purple.cgColor]
@ -53,6 +64,13 @@ final class VoiceChatTimerNode: ASDisplayNode {
self.addSubnode(self.subtitleNode) self.addSubnode(self.subtitleNode)
self.maskView.addSubnode(self.timerNode) self.maskView.addSubnode(self.timerNode)
updateInHierarchy = { [weak self] value in
if let strongSelf = self {
strongSelf.isCurrentlyInHierarchy = value
strongSelf.updateAnimations()
}
}
} }
deinit { deinit {
@ -60,7 +78,15 @@ final class VoiceChatTimerNode: ASDisplayNode {
} }
func animateIn() { func animateIn() {
self.foregroundView.layer.animateSpring(from: 0.01 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.42, damping: 104.0) self.foregroundView.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.6, damping: 100.0)
}
private func updateAnimations() {
if self.isInHierarchy {
self.setupGradientAnimations()
} else {
self.foregroundGradientLayer.removeAllAnimations()
}
} }
private func setupGradientAnimations() { private func setupGradientAnimations() {
@ -78,9 +104,9 @@ final class VoiceChatTimerNode: ASDisplayNode {
animation.toValue = newValue animation.toValue = newValue
CATransaction.setCompletionBlock { [weak self] in CATransaction.setCompletionBlock { [weak self] in
// if let isCurrentlyInHierarchy = self?.isCurrentlyInHierarchy, isCurrentlyInHierarchy { if let isCurrentlyInHierarchy = self?.isCurrentlyInHierarchy, isCurrentlyInHierarchy {
self?.setupGradientAnimations() self?.setupGradientAnimations()
// } }
} }
self.foregroundGradientLayer.add(animation, forKey: "movement") self.foregroundGradientLayer.add(animation, forKey: "movement")
@ -90,7 +116,7 @@ final class VoiceChatTimerNode: ASDisplayNode {
func update(size: CGSize, scheduleTime: Int32?, transition: ContainedViewLayoutTransition) { func update(size: CGSize, scheduleTime: Int32?, transition: ContainedViewLayoutTransition) {
if self.validLayout == nil { if self.validLayout == nil {
self.setupGradientAnimations() self.updateAnimations()
} }
self.validLayout = size self.validLayout = size

View File

@ -65,7 +65,7 @@ final class VoiceChatTitleNode: ASDisplayNode {
self.tapped?() self.tapped?()
} }
func update(size: CGSize, title: String, subtitle: String, transition: ContainedViewLayoutTransition) { func update(size: CGSize, title: String, subtitle: String, slide: Bool, transition: ContainedViewLayoutTransition) {
var titleUpdated = false var titleUpdated = false
if let previousTitle = self.titleNode.attributedText?.string { if let previousTitle = self.titleNode.attributedText?.string {
titleUpdated = previousTitle != title titleUpdated = previousTitle != title
@ -80,6 +80,14 @@ final class VoiceChatTitleNode: ASDisplayNode {
}) })
self.titleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) self.titleNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
if slide {
self.infoNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
let offset: CGFloat = 16.0
snapshotView.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -offset), duration: 0.2, removeOnCompletion: false, additive: true)
self.titleNode.layer.animatePosition(from: CGPoint(x: 0.0, y: offset), to: CGPoint(), duration: 0.2, additive: true)
self.infoNode.layer.animatePosition(from: CGPoint(x: 0.0, y: offset), to: CGPoint(), duration: 0.2, additive: true)
}
} }
self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(17.0), textColor: UIColor(rgb: 0xffffff)) self.titleNode.attributedText = NSAttributedString(string: title, font: Font.medium(17.0), textColor: UIColor(rgb: 0xffffff))

View File

@ -553,7 +553,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
if canManageGroupCalls { if canManageGroupCalls {
strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatText, actions: [TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {}), TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatStart, action: { strongSelf.present(textAlertController(context: strongSelf.context, title: nil, text: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatText, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatStartNow, action: {
if let strongSelf = self { if let strongSelf = self {
var dismissStatus: (() -> Void)? var dismissStatus: (() -> Void)?
let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: { let statusController = OverlayStatusController(theme: strongSelf.presentationData.theme, type: .loading(cancelled: {
@ -589,7 +589,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
dismissStatus?() dismissStatus?()
})) }))
} }
})]), in: .window(.root)) }), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.VoiceChat_CreateNewVoiceChatSchedule, action: {
if let strongSelf = self {
strongSelf.context.scheduleGroupCall(peerId: message.id.peerId)
}
}), TextAlertAction(type: .genericAction, title: strongSelf.presentationData.strings.Common_Cancel, action: {})], actionLayout: .vertical), in: .window(.root))
} }
} }
return true return true