From 28283923fba027e1146ec5224e277798f570d319 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 4 Jul 2020 19:10:24 +0400 Subject: [PATCH] Apply patch --- .../TGModernConversationInputMicButton.m | 13 ++--- submodules/TelegramUI/Sources/BlobView.swift | 45 ++++++++++----- .../TelegramUI/Sources/ChatController.swift | 56 +++++++++++-------- .../Sources/ChatTextInputPanelNode.swift | 34 +++++------ 4 files changed, 88 insertions(+), 60 deletions(-) diff --git a/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m b/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m index b47a97ccb1..3b24ac7c61 100644 --- a/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m +++ b/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m @@ -575,7 +575,6 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius [UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:^ { _innerIconView.transform = CGAffineTransformIdentity; - _decoration.transform = CGAffineTransformIdentity; snapshotView.transform = CGAffineTransformMakeScale(0.001f, 0.001f); } completion:^(__unused BOOL finished) { [snapshotView removeFromSuperview]; @@ -837,11 +836,13 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius _innerCircleView.image = nil; } NSTimeInterval t = CACurrentMediaTime(); + + _currentLevel = _currentLevel * 0.9f + _inputLevel * 0.1f; + [_decoration tick:_currentLevel]; + + _currentTranslation = MIN(0.0, _currentTranslation * 0.7f + _targetTranslation * 0.3f); + if (t > _animationStartTime) { - _currentLevel = _currentLevel * 0.8f + _inputLevel * 0.2f; - - _currentTranslation = MIN(0.0, _currentTranslation * 0.7f + _targetTranslation * 0.3f); - CGFloat outerScale = outerCircleMinScale + _currentLevel * (1.0f - outerCircleMinScale); CGAffineTransform translation = CGAffineTransformMakeTranslation(0, _currentTranslation); CGAffineTransform transform = CGAffineTransformScale(translation, outerScale, outerScale); @@ -857,8 +858,6 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius _innerCircleView.transform = transform; _innerIconWrapperView.transform = transform; _decoration.transform = transform; - - [_decoration tick:_currentLevel]; } } diff --git a/submodules/TelegramUI/Sources/BlobView.swift b/submodules/TelegramUI/Sources/BlobView.swift index 3f3d6e1613..4b6c2470cd 100644 --- a/submodules/TelegramUI/Sources/BlobView.swift +++ b/submodules/TelegramUI/Sources/BlobView.swift @@ -30,7 +30,7 @@ final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDecoration minScale: 0.55, maxScale: 0.9, scaleSpeed: 0.2, - isCircle: true + isCircle: false ) private let bigBlob = BlobView( pointsCount: 8, @@ -41,7 +41,7 @@ final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDecoration minScale: 0.55, maxScale: 1, scaleSpeed: 0.2, - isCircle: true + isCircle: false ) override init(frame: CGRect) { @@ -65,13 +65,19 @@ final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDecoration func updateLevel(_ level: CGFloat) { let normalizedLevel = min(1, max(level / Constants.maxLevel, 0)) + smallBlob.updateSpeedLevel(to: normalizedLevel) + mediumBlob.updateSpeedLevel(to: normalizedLevel) + bigBlob.updateSpeedLevel(to: normalizedLevel) + } + + func tick(_ level: CGFloat) { + let normalizedLevel = min(1, max(level / Constants.maxLevel, 0)) + smallBlob.level = normalizedLevel mediumBlob.level = normalizedLevel bigBlob.level = normalizedLevel } - func tick(_ level: CGFloat) { } - override func layoutSubviews() { super.layoutSubviews() @@ -104,17 +110,18 @@ final class BlobView: UIView { let maxScale: CGFloat let scaleSpeed: CGFloat + var scaleLevelsToBalance = [CGFloat]() + // If true ignores randomness and pointsCount let isCircle: Bool var level: CGFloat = 0 { didSet { - speedLevel = max(level, speedLevel) - scaleLevel = max(level, scaleLevel) - - if abs(scaleLevel - lastScaleLevel) > 0.4 { - animateToNewScale() - } + CATransaction.begin() + CATransaction.setDisableActions(true) + let lv = minScale + (maxScale - minScale) * level + shapeLayer.transform = CATransform3DMakeScale(lv, lv, 1) + CATransaction.commit() } } @@ -190,18 +197,27 @@ final class BlobView: UIView { shapeLayer.fillColor = color.cgColor } + func updateSpeedLevel(to newSpeedLevel: CGFloat) { + speedLevel = max(speedLevel, newSpeedLevel) + } + func startAnimating() { animateToNewShape() - animateToNewScale() } func animateToNewScale() { - let isDownscale = lastScaleLevel > scaleLevel - lastScaleLevel = scaleLevel + let scaleLevelForAnimation: CGFloat = { + if scaleLevelsToBalance.isEmpty { + return 0 + } + return scaleLevelsToBalance.reduce(0, +) / CGFloat(scaleLevelsToBalance.count) + }() + let isDownscale = lastScaleLevel > scaleLevelForAnimation + lastScaleLevel = scaleLevelForAnimation shapeLayer.pop_removeAnimation(forKey: "scale") - let currentScale = minScale + (maxScale - minScale) * scaleLevel + let currentScale = minScale + (maxScale - minScale) * scaleLevelForAnimation let scaleAnimation = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)! scaleAnimation.toValue = CGPoint(x: currentScale, y: currentScale) scaleAnimation.duration = isDownscale ? 0.45 : CFTimeInterval(scaleSpeed) @@ -213,6 +229,7 @@ final class BlobView: UIView { shapeLayer.pop_add(scaleAnimation, forKey: "scale") scaleLevel = 0 + scaleLevelsToBalance.removeAll() } func animateToNewShape() { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 1225d33f19..3a922606bd 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -321,6 +321,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G private let peekData: ChatPeekTimeout? private let peekTimerDisposable = MetaDisposable() + private var shouldDisplayDownButton = false + private var hasEmbeddedTitleContent = false private var isEmbeddedTitleContentHidden = false @@ -2544,6 +2546,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } else { strongSelf.audioRecorderStatusDisposable = nil } + strongSelf.updateDownButtonVisibility() } } }) @@ -2592,6 +2595,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G videoRecorder.lockVideo() } } + strongSelf.updateDownButtonVisibility() if let previousVideoRecorderValue = previousVideoRecorderValue { previousVideoRecorderValue.dismissVideo() @@ -3091,32 +3095,33 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } self.chatDisplayNode.historyNode.contentPositionChanged = { [weak self] offset in - if let strongSelf = self { - let offsetAlpha: CGFloat - let plainInputSeparatorAlpha: CGFloat - switch offset { - case let .known(offset): - if offset < 40.0 { - offsetAlpha = 0.0 - } else { - offsetAlpha = 1.0 - } - if offset < 4.0 { - plainInputSeparatorAlpha = 0.0 - } else { - plainInputSeparatorAlpha = 1.0 - } - case .unknown: - offsetAlpha = 1.0 - plainInputSeparatorAlpha = 1.0 - case .none: + guard let strongSelf = self else { return } + + let offsetAlpha: CGFloat + let plainInputSeparatorAlpha: CGFloat + switch offset { + case let .known(offset): + if offset < 40.0 { offsetAlpha = 0.0 + } else { + offsetAlpha = 1.0 + } + if offset < 4.0 { plainInputSeparatorAlpha = 0.0 - } - - strongSelf.chatDisplayNode.navigateButtons.displayDownButton = !offsetAlpha.isZero - strongSelf.chatDisplayNode.updatePlainInputSeparatorAlpha(plainInputSeparatorAlpha, transition: .animated(duration: 0.2, curve: .easeInOut)) + } else { + plainInputSeparatorAlpha = 1.0 + } + case .unknown: + offsetAlpha = 1.0 + plainInputSeparatorAlpha = 1.0 + case .none: + offsetAlpha = 0.0 + plainInputSeparatorAlpha = 0.0 } + + strongSelf.shouldDisplayDownButton = !offsetAlpha.isZero + strongSelf.updateDownButtonVisibility() + strongSelf.chatDisplayNode.updatePlainInputSeparatorAlpha(plainInputSeparatorAlpha, transition: .animated(duration: 0.2, curve: .easeInOut)) } self.chatDisplayNode.historyNode.scrolledToIndex = { [weak self] toIndex in @@ -7636,6 +7641,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.chatDisplayNode.historyNode.scrollToEndOfHistory() } + func updateDownButtonVisibility() { + let recordingMediaMessage = self.audioRecorderValue != nil || self.videoRecorderValue != nil + self.chatDisplayNode.navigateButtons.displayDownButton = self.shouldDisplayDownButton && !recordingMediaMessage + } + func updateTextInputState(_ textInputState: ChatTextInputState) { self.updateChatPresentationInterfaceState(interactive: false, { state in state.updatedInterfaceState({ state in diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index c4642c1ef6..1d3cf7f30f 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -1055,20 +1055,22 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { audioRecordingDotNode.frame = CGRect(origin: CGPoint(x: leftInset + 2.0 - UIScreenPixel, y: panelHeight - 44 + 1), size: CGSize(width: 40.0, height: 40)) if animateDotAppearing { - audioRecordingDotNode.layer.animateScale(from: 0.3, to: 1, duration: 0.15, delay: 0, removeOnCompletion: false) - audioRecordingDotNode.layer.animateAlpha(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 1, duration: 0.15, delay: 0, completion: { [weak audioRecordingDotNode] finished in - if finished { - let animation = CAKeyframeAnimation(keyPath: "opacity") - animation.values = [1.0 as NSNumber, 1.0 as NSNumber, 0.0 as NSNumber] - animation.keyTimes = [0.0 as NSNumber, 0.4546 as NSNumber, 0.9091 as NSNumber, 1 as NSNumber] - animation.duration = 0.5 - animation.autoreverses = true - animation.repeatCount = Float.infinity - - audioRecordingDotNode?.layer.add(animation, forKey: "recording") - } - }) - + let dotStartScale: CGFloat = (audioRecordingDotNode.layer.presentation()?.value(forKeyPath: "transform.scale.x") as? CGFloat) ?? 1 + audioRecordingDotNode.layer.animateScale(from: dotStartScale, to: 1, duration: 0.15, delay: 0, removeOnCompletion: false) + if audioRecordingDotNode.layer.animation(forKey: "recording") == nil { + audioRecordingDotNode.layer.animateAlpha(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 1, duration: 0.15, delay: 0, completion: { [weak audioRecordingDotNode] finished in + if finished { + let animation = CAKeyframeAnimation(keyPath: "opacity") + animation.values = [1.0 as NSNumber, 1.0 as NSNumber, 0.0 as NSNumber] + animation.keyTimes = [0.0 as NSNumber, 0.4546 as NSNumber, 0.9091 as NSNumber, 1 as NSNumber] + animation.duration = 0.5 + animation.autoreverses = true + animation.repeatCount = Float.infinity + + audioRecordingDotNode?.layer.add(animation, forKey: "recording") + } + }) + } self.attachmentButton.layer.animateAlpha(from: CGFloat(self.attachmentButton.layer.presentation()?.opacity ?? 1), to: 0, duration: 0.15, delay: 0, removeOnCompletion: false) self.attachmentButton.layer.animateScale(from: 1, to: 0.3, duration: 0.15, delay: 0, removeOnCompletion: false) } @@ -1103,8 +1105,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self?.audioRecordingDotNode = nil - audioRecordingDotNode.layer.animateScale(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 0.3, duration: 0.15, delay: 0, removeOnCompletion: false) - audioRecordingDotNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, delay: 0, removeOnCompletion: false) { [weak audioRecordingDotNode] _ in + audioRecordingDotNode.layer.animateScale(from: 1, to: 0.3, duration: 0.15, delay: 0, removeOnCompletion: false) + audioRecordingDotNode.layer.animateAlpha(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 0.0, duration: 0.15, delay: 0, removeOnCompletion: false) { [weak audioRecordingDotNode] _ in audioRecordingDotNode?.removeFromSupernode() }