diff --git a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGModernConversationInputMicButton.h b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGModernConversationInputMicButton.h index ed78e3cbef..94e5eff7d9 100644 --- a/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGModernConversationInputMicButton.h +++ b/submodules/LegacyComponents/PublicHeaders/LegacyComponents/TGModernConversationInputMicButton.h @@ -87,6 +87,8 @@ - (void)_commitLocked; +- (void)lockImmediately; + - (void)setHidesPanelOnLock; - (UIView *)createLockPanelView; diff --git a/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m b/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m index e388791013..9e570cdd40 100644 --- a/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m +++ b/submodules/LegacyComponents/Sources/TGModernConversationInputMicButton.m @@ -473,7 +473,7 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius _outerCircleView.alpha = 0.2f; _decoration.alpha = 0.2; - _lockPanelWrapperView.transform = CGAffineTransformMakeTranslation(0.0f, 100.0f); + _lockPanelWrapperView.transform = CGAffineTransformMakeTranslation(0.0f, _locked ? 36.0 : 100.0f); _lockPanelWrapperView.alpha = 0.0f; _lock.transform = CGAffineTransformIdentity; @@ -598,6 +598,32 @@ static const CGFloat outerCircleMinScale = innerCircleRadius / outerCircleRadius return iconImage; } +- (void)lockImmediately { + _lockView.lockness = 1.0; + [_lock updateLockness:1.0]; + + UIImage *icon = TGComponentsImageNamed(@"RecordSendIcon"); + [self setIcon:TGTintedImage(icon, _pallete != nil && !_hidesPanelOnLock ? _pallete.iconColor : [UIColor whiteColor])]; + + _currentScale = 1; + _cancelTargetTranslation = 0; + + id delegate = _delegate; + if ([delegate respondsToSelector:@selector(micButtonInteractionUpdateCancelTranslation:)]) + [delegate micButtonInteractionUpdateCancelTranslation:-_cancelTargetTranslation]; + + _lockPanelView.frame = CGRectMake(_lockPanelView.frame.origin.x, 40.0f, _lockPanelView.frame.size.width, 72.0f - 32.0f); + _lockView.transform = CGAffineTransformMakeTranslation(0.0f, -11.0f); + _lock.transform = CGAffineTransformMakeTranslation(0.0f, -16.0f); + _lockArrowView.transform = CGAffineTransformMakeTranslation(0.0f, -39.0f); + _lockArrowView.alpha = 0.0f; + + _stopButton.userInteractionEnabled = true; + [UIView animateWithDuration:0.25 delay:0.56 options:kNilOptions animations:^ + { + _stopButton.alpha = 1.0f; + } completion:nil]; +} - (void)animateLock { if (!_animatedIn) { diff --git a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift index 822eacf1e8..83337ed8d5 100644 --- a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift @@ -252,7 +252,6 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM if let audioRecorder = self.audioRecorder { self.micLevelDisposable?.set(audioRecorder.micLevel.start(next: { [weak self] level in Queue.mainQueue().async { - //self?.recordingOverlay?.addImmediateMicLevel(CGFloat(level)) self?.addMicLevel(CGFloat(level)) } })) @@ -275,7 +274,6 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM if let videoRecordingStatus = self.videoRecordingStatus { self.micLevelDisposable?.set(videoRecordingStatus.micLevel.start(next: { [weak self] level in Queue.mainQueue().async { - //self?.recordingOverlay?.addImmediateMicLevel(CGFloat(level)) self?.addMicLevel(CGFloat(level)) } })) @@ -411,7 +409,7 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM animationName = "anim_micToVideo" } - let _ = animationView.update( + let _ = self.animationView.update( transition: .immediate, component: AnyComponent(LottieComponent( content: LottieComponent.AppBundleContent(name: animationName), @@ -421,7 +419,7 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM containerSize: animationFrame.size ) - if let view = animationView.view as? LottieComponent.View { + if let view = self.animationView.view as? LottieComponent.View { view.isUserInteractionEnabled = false if view.superview == nil { self.insertSubview(view, at: 0) @@ -537,6 +535,10 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM micButtonInteractionStopped() } + public func lock() { + super._commitLocked() + } + override public func animateIn() { super.animateIn() diff --git a/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift index 44a8142f0d..c06841f2a1 100644 --- a/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecordingPreviewInputPanelNode.swift @@ -346,6 +346,9 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode { prevTextInputPanelNode.viewOnceButton.update(isSelected: false, animated: false) }) + self.recordMoreButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) + self.recordMoreButton.layer.animateScale(from: 0.1, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring) + if let audioRecordingDotNode = prevTextInputPanelNode.audioRecordingDotNode { let startAlpha = CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1.0) audioRecordingDotNode.layer.removeAllAnimations() @@ -388,6 +391,8 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode { ) { [weak self, weak prevTextInputPanelNode] finished in if prevTextInputPanelNode?.supernode === self { prevTextInputPanelNode?.removeFromSupernode() + prevTextInputPanelNode?.finishedTransitionToPreview = true + prevTextInputPanelNode?.requestLayout() } } } diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 7d23052d53..40c20b121e 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -769,6 +769,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch private var spoilersRevealed = false + private var animatingTransition = false + var finishedTransitionToPreview: Bool? + private var touchDownGestureRecognizer: TouchDownGestureRecognizer? var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? @@ -1292,7 +1295,6 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch return minimalHeight } - private var animatingTransition = false private func animateBotButtonInFromMenu(transition: ContainedViewLayoutTransition) { guard !self.animatingTransition else { return @@ -1412,6 +1414,13 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch } } + func requestLayout() { + guard let presentationInterfaceState = self.presentationInterfaceState, let (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) = self.validLayout else { + return + } + let _ = self.updateLayout(width: width, leftInset: leftInset, rightInset: rightInset, bottomInset: bottomInset, additionalSideInsets: additionalSideInsets, maxHeight: maxHeight, isSecondary: isSecondary, transition: .immediate, interfaceState: presentationInterfaceState, metrics: metrics, isMediaInputExpanded: isMediaInputExpanded) + } + override func updateLayout(width: CGFloat, leftInset: CGFloat, rightInset: CGFloat, bottomInset: CGFloat, additionalSideInsets: UIEdgeInsets, maxHeight: CGFloat, isSecondary: Bool, transition: ContainedViewLayoutTransition, interfaceState: ChatPresentationInterfaceState, metrics: LayoutMetrics, isMediaInputExpanded: Bool) -> CGFloat { let previousAdditionalSideInsets = self.validLayout?.4 self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) @@ -1986,7 +1995,11 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch var hideMicButton = false var audioRecordingItemsAlpha: CGFloat = 1 - if mediaRecordingState != nil || interfaceState.recordedMediaPreview != nil { + if mediaRecordingState != nil || (interfaceState.recordedMediaPreview != nil && self.finishedTransitionToPreview != true) { + if interfaceState.recordedMediaPreview != nil { + self.finishedTransitionToPreview = false + } + audioRecordingItemsAlpha = 0 let audioRecordingInfoContainerNode: ASDisplayNode @@ -2033,7 +2046,11 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch if let mediaRecordingState = mediaRecordingState { switch mediaRecordingState { - case let .audio(recorder, _): + case let .audio(recorder, isLocked): + let hadAudioRecorder = self.actionButtons.micButton.audioRecorder != nil + if !hadAudioRecorder, isLocked { + self.actionButtons.micButton.lock() + } self.actionButtons.micButton.audioRecorder = recorder audioRecordingTimeNode.audioRecorder = recorder case let .video(status, _): @@ -2176,6 +2193,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch audioRecordingCancelIndicator.layer.animateAlpha(from: CGFloat(audioRecordingCancelIndicator.layer.presentation()?.opacity ?? 1), to: 0, duration: 0.15, delay: 0, removeOnCompletion: false) } } else { + self.finishedTransitionToPreview = nil + var update = self.actionButtons.micButton.audioRecorder != nil || self.actionButtons.micButton.videoRecordingStatus != nil self.actionButtons.micButton.audioRecorder = nil self.actionButtons.micButton.videoRecordingStatus = nil @@ -2200,13 +2219,13 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate, Ch self?.audioRecordingDotNode = nil - 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.layer.animateScale(from: 1.0, to: 0.3, duration: 0.15, delay: 0.0, removeOnCompletion: false) + audioRecordingDotNode.layer.animateAlpha(from: CGFloat(audioRecordingDotNode.layer.presentation()?.opacity ?? 1), to: 0.0, duration: 0.15, delay: 0.0, removeOnCompletion: false) { [weak audioRecordingDotNode] _ in audioRecordingDotNode?.removeFromSupernode() } - self?.attachmentButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: 0, removeOnCompletion: false) - self?.attachmentButton.layer.animateScale(from: 0.3, to: 1.0, duration: 0.15, delay: 0, removeOnCompletion: false) + self?.attachmentButton.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, delay: 0.0, removeOnCompletion: false) + self?.attachmentButton.layer.animateScale(from: 0.3, to: 1.0, duration: 0.15, delay: 0.0, removeOnCompletion: false) } if update && !self.audioRecordingDotNodeDismissed { diff --git a/submodules/TelegramUI/Sources/ManagedAudioRecorder.swift b/submodules/TelegramUI/Sources/ManagedAudioRecorder.swift index 24053992e1..a78fc96e3f 100644 --- a/submodules/TelegramUI/Sources/ManagedAudioRecorder.swift +++ b/submodules/TelegramUI/Sources/ManagedAudioRecorder.swift @@ -500,7 +500,7 @@ final class ManagedAudioRecorderContext { free(buffer.mData) } - if !self.processSamples && !self.paused { + if !self.processSamples || self.paused { return }