mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-09-05 04:10:16 +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:^
|
[UIView animateWithDuration:0.3 delay:0.0 options:7 << 16 animations:^
|
||||||
{
|
{
|
||||||
_innerIconView.transform = CGAffineTransformIdentity;
|
_innerIconView.transform = CGAffineTransformIdentity;
|
||||||
_decoration.transform = CGAffineTransformIdentity;
|
|
||||||
snapshotView.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
|
snapshotView.transform = CGAffineTransformMakeScale(0.001f, 0.001f);
|
||||||
} completion:^(__unused BOOL finished) {
|
} completion:^(__unused BOOL finished) {
|
||||||
[snapshotView removeFromSuperview];
|
[snapshotView removeFromSuperview];
|
||||||
@ -837,11 +836,13 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius
|
|||||||
_innerCircleView.image = nil;
|
_innerCircleView.image = nil;
|
||||||
}
|
}
|
||||||
NSTimeInterval t = CACurrentMediaTime();
|
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) {
|
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);
|
CGFloat outerScale = outerCircleMinScale + _currentLevel * (1.0f - outerCircleMinScale);
|
||||||
CGAffineTransform translation = CGAffineTransformMakeTranslation(0, _currentTranslation);
|
CGAffineTransform translation = CGAffineTransformMakeTranslation(0, _currentTranslation);
|
||||||
CGAffineTransform transform = CGAffineTransformScale(translation, outerScale, outerScale);
|
CGAffineTransform transform = CGAffineTransformScale(translation, outerScale, outerScale);
|
||||||
@ -857,8 +858,6 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius
|
|||||||
_innerCircleView.transform = transform;
|
_innerCircleView.transform = transform;
|
||||||
_innerIconWrapperView.transform = transform;
|
_innerIconWrapperView.transform = transform;
|
||||||
_decoration.transform = transform;
|
_decoration.transform = transform;
|
||||||
|
|
||||||
[_decoration tick:_currentLevel];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDecoration
|
|||||||
minScale: 0.55,
|
minScale: 0.55,
|
||||||
maxScale: 0.9,
|
maxScale: 0.9,
|
||||||
scaleSpeed: 0.2,
|
scaleSpeed: 0.2,
|
||||||
isCircle: true
|
isCircle: false
|
||||||
)
|
)
|
||||||
private let bigBlob = BlobView(
|
private let bigBlob = BlobView(
|
||||||
pointsCount: 8,
|
pointsCount: 8,
|
||||||
@ -41,7 +41,7 @@ final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDecoration
|
|||||||
minScale: 0.55,
|
minScale: 0.55,
|
||||||
maxScale: 1,
|
maxScale: 1,
|
||||||
scaleSpeed: 0.2,
|
scaleSpeed: 0.2,
|
||||||
isCircle: true
|
isCircle: false
|
||||||
)
|
)
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
@ -65,13 +65,19 @@ final class VoiceBlobView: UIView, TGModernConversationInputMicButtonDecoration
|
|||||||
func updateLevel(_ level: CGFloat) {
|
func updateLevel(_ level: CGFloat) {
|
||||||
let normalizedLevel = min(1, max(level / Constants.maxLevel, 0))
|
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
|
smallBlob.level = normalizedLevel
|
||||||
mediumBlob.level = normalizedLevel
|
mediumBlob.level = normalizedLevel
|
||||||
bigBlob.level = normalizedLevel
|
bigBlob.level = normalizedLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
func tick(_ level: CGFloat) { }
|
|
||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
|
|
||||||
@ -104,17 +110,18 @@ final class BlobView: UIView {
|
|||||||
let maxScale: CGFloat
|
let maxScale: CGFloat
|
||||||
let scaleSpeed: CGFloat
|
let scaleSpeed: CGFloat
|
||||||
|
|
||||||
|
var scaleLevelsToBalance = [CGFloat]()
|
||||||
|
|
||||||
// If true ignores randomness and pointsCount
|
// If true ignores randomness and pointsCount
|
||||||
let isCircle: Bool
|
let isCircle: Bool
|
||||||
|
|
||||||
var level: CGFloat = 0 {
|
var level: CGFloat = 0 {
|
||||||
didSet {
|
didSet {
|
||||||
speedLevel = max(level, speedLevel)
|
CATransaction.begin()
|
||||||
scaleLevel = max(level, scaleLevel)
|
CATransaction.setDisableActions(true)
|
||||||
|
let lv = minScale + (maxScale - minScale) * level
|
||||||
if abs(scaleLevel - lastScaleLevel) > 0.4 {
|
shapeLayer.transform = CATransform3DMakeScale(lv, lv, 1)
|
||||||
animateToNewScale()
|
CATransaction.commit()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,18 +197,27 @@ final class BlobView: UIView {
|
|||||||
shapeLayer.fillColor = color.cgColor
|
shapeLayer.fillColor = color.cgColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func updateSpeedLevel(to newSpeedLevel: CGFloat) {
|
||||||
|
speedLevel = max(speedLevel, newSpeedLevel)
|
||||||
|
}
|
||||||
|
|
||||||
func startAnimating() {
|
func startAnimating() {
|
||||||
animateToNewShape()
|
animateToNewShape()
|
||||||
animateToNewScale()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateToNewScale() {
|
func animateToNewScale() {
|
||||||
let isDownscale = lastScaleLevel > scaleLevel
|
let scaleLevelForAnimation: CGFloat = {
|
||||||
lastScaleLevel = scaleLevel
|
if scaleLevelsToBalance.isEmpty {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return scaleLevelsToBalance.reduce(0, +) / CGFloat(scaleLevelsToBalance.count)
|
||||||
|
}()
|
||||||
|
let isDownscale = lastScaleLevel > scaleLevelForAnimation
|
||||||
|
lastScaleLevel = scaleLevelForAnimation
|
||||||
|
|
||||||
shapeLayer.pop_removeAnimation(forKey: "scale")
|
shapeLayer.pop_removeAnimation(forKey: "scale")
|
||||||
|
|
||||||
let currentScale = minScale + (maxScale - minScale) * scaleLevel
|
let currentScale = minScale + (maxScale - minScale) * scaleLevelForAnimation
|
||||||
let scaleAnimation = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)!
|
let scaleAnimation = POPBasicAnimation(propertyNamed: kPOPLayerScaleXY)!
|
||||||
scaleAnimation.toValue = CGPoint(x: currentScale, y: currentScale)
|
scaleAnimation.toValue = CGPoint(x: currentScale, y: currentScale)
|
||||||
scaleAnimation.duration = isDownscale ? 0.45 : CFTimeInterval(scaleSpeed)
|
scaleAnimation.duration = isDownscale ? 0.45 : CFTimeInterval(scaleSpeed)
|
||||||
@ -213,6 +229,7 @@ final class BlobView: UIView {
|
|||||||
shapeLayer.pop_add(scaleAnimation, forKey: "scale")
|
shapeLayer.pop_add(scaleAnimation, forKey: "scale")
|
||||||
|
|
||||||
scaleLevel = 0
|
scaleLevel = 0
|
||||||
|
scaleLevelsToBalance.removeAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
func animateToNewShape() {
|
func animateToNewShape() {
|
||||||
|
@ -321,6 +321,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
private let peekData: ChatPeekTimeout?
|
private let peekData: ChatPeekTimeout?
|
||||||
private let peekTimerDisposable = MetaDisposable()
|
private let peekTimerDisposable = MetaDisposable()
|
||||||
|
|
||||||
|
private var shouldDisplayDownButton = false
|
||||||
|
|
||||||
private var hasEmbeddedTitleContent = false
|
private var hasEmbeddedTitleContent = false
|
||||||
private var isEmbeddedTitleContentHidden = false
|
private var isEmbeddedTitleContentHidden = false
|
||||||
|
|
||||||
@ -2544,6 +2546,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
} else {
|
} else {
|
||||||
strongSelf.audioRecorderStatusDisposable = nil
|
strongSelf.audioRecorderStatusDisposable = nil
|
||||||
}
|
}
|
||||||
|
strongSelf.updateDownButtonVisibility()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -2592,6 +2595,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
videoRecorder.lockVideo()
|
videoRecorder.lockVideo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
strongSelf.updateDownButtonVisibility()
|
||||||
|
|
||||||
if let previousVideoRecorderValue = previousVideoRecorderValue {
|
if let previousVideoRecorderValue = previousVideoRecorderValue {
|
||||||
previousVideoRecorderValue.dismissVideo()
|
previousVideoRecorderValue.dismissVideo()
|
||||||
@ -3091,32 +3095,33 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.chatDisplayNode.historyNode.contentPositionChanged = { [weak self] offset in
|
self.chatDisplayNode.historyNode.contentPositionChanged = { [weak self] offset in
|
||||||
if let strongSelf = self {
|
guard let strongSelf = self else { return }
|
||||||
let offsetAlpha: CGFloat
|
|
||||||
let plainInputSeparatorAlpha: CGFloat
|
let offsetAlpha: CGFloat
|
||||||
switch offset {
|
let plainInputSeparatorAlpha: CGFloat
|
||||||
case let .known(offset):
|
switch offset {
|
||||||
if offset < 40.0 {
|
case let .known(offset):
|
||||||
offsetAlpha = 0.0
|
if offset < 40.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:
|
|
||||||
offsetAlpha = 0.0
|
offsetAlpha = 0.0
|
||||||
|
} else {
|
||||||
|
offsetAlpha = 1.0
|
||||||
|
}
|
||||||
|
if offset < 4.0 {
|
||||||
plainInputSeparatorAlpha = 0.0
|
plainInputSeparatorAlpha = 0.0
|
||||||
}
|
} else {
|
||||||
|
plainInputSeparatorAlpha = 1.0
|
||||||
strongSelf.chatDisplayNode.navigateButtons.displayDownButton = !offsetAlpha.isZero
|
}
|
||||||
strongSelf.chatDisplayNode.updatePlainInputSeparatorAlpha(plainInputSeparatorAlpha, transition: .animated(duration: 0.2, curve: .easeInOut))
|
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
|
self.chatDisplayNode.historyNode.scrolledToIndex = { [weak self] toIndex in
|
||||||
@ -7636,6 +7641,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
self.chatDisplayNode.historyNode.scrollToEndOfHistory()
|
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) {
|
func updateTextInputState(_ textInputState: ChatTextInputState) {
|
||||||
self.updateChatPresentationInterfaceState(interactive: false, { state in
|
self.updateChatPresentationInterfaceState(interactive: false, { state in
|
||||||
state.updatedInterfaceState({ 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))
|
audioRecordingDotNode.frame = CGRect(origin: CGPoint(x: leftInset + 2.0 - UIScreenPixel, y: panelHeight - 44 + 1), size: CGSize(width: 40.0, height: 40))
|
||||||
if animateDotAppearing {
|
if animateDotAppearing {
|
||||||
audioRecordingDotNode.layer.animateScale(from: 0.3, to: 1, duration: 0.15, delay: 0, removeOnCompletion: false)
|
let dotStartScale: CGFloat = (audioRecordingDotNode.layer.presentation()?.value(forKeyPath: "transform.scale.x") as? CGFloat) ?? 1
|
||||||
audioRecordingDotNode.layer.animateAlpha(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 1, duration: 0.15, delay: 0, completion: { [weak audioRecordingDotNode] finished in
|
audioRecordingDotNode.layer.animateScale(from: dotStartScale, to: 1, duration: 0.15, delay: 0, removeOnCompletion: false)
|
||||||
if finished {
|
if audioRecordingDotNode.layer.animation(forKey: "recording") == nil {
|
||||||
let animation = CAKeyframeAnimation(keyPath: "opacity")
|
audioRecordingDotNode.layer.animateAlpha(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 1, duration: 0.15, delay: 0, completion: { [weak audioRecordingDotNode] finished in
|
||||||
animation.values = [1.0 as NSNumber, 1.0 as NSNumber, 0.0 as NSNumber]
|
if finished {
|
||||||
animation.keyTimes = [0.0 as NSNumber, 0.4546 as NSNumber, 0.9091 as NSNumber, 1 as NSNumber]
|
let animation = CAKeyframeAnimation(keyPath: "opacity")
|
||||||
animation.duration = 0.5
|
animation.values = [1.0 as NSNumber, 1.0 as NSNumber, 0.0 as NSNumber]
|
||||||
animation.autoreverses = true
|
animation.keyTimes = [0.0 as NSNumber, 0.4546 as NSNumber, 0.9091 as NSNumber, 1 as NSNumber]
|
||||||
animation.repeatCount = Float.infinity
|
animation.duration = 0.5
|
||||||
|
animation.autoreverses = true
|
||||||
audioRecordingDotNode?.layer.add(animation, forKey: "recording")
|
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.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)
|
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
|
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.animateScale(from: 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.animateAlpha(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 0.0, duration: 0.15, delay: 0, removeOnCompletion: false) { [weak audioRecordingDotNode] _ in
|
||||||
audioRecordingDotNode?.removeFromSupernode()
|
audioRecordingDotNode?.removeFromSupernode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user