mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-03 11:21:06 +00:00
Apply patch
This commit is contained in:
parent
2bb0293fb4
commit
28283923fb
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user