diff --git a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift index c3bcfc4331..ca1a6f386e 100644 --- a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/ChatTextInputMediaRecordingButton.swift @@ -178,6 +178,7 @@ private final class ChatTextInputMediaRecordingButtonPresenter : NSObject, TGMod public final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButton, TGModernConversationInputMicButtonDelegate { private let context: AccountContext private var theme: PresentationTheme + private let useDarkTheme: Bool private let strings: PresentationStrings public var mode: ChatTextInputMediaRecordingButtonMode = .audio @@ -293,16 +294,17 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM if let current = self.micLockValue { return current } else { - let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme, strings: self.strings) + let lockView = LockView(frame: CGRect(origin: CGPoint(), size: CGSize(width: 40.0, height: 60.0)), theme: self.theme, useDarkTheme: self.useDarkTheme, strings: self.strings) lockView.addTarget(self, action: #selector(handleStopTap), for: .touchUpInside) self.micLockValue = lockView return lockView } } - public init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) { + public init(context: AccountContext, theme: PresentationTheme, useDarkTheme: Bool = false, strings: PresentationStrings, presentController: @escaping (ViewController) -> Void) { self.context = context self.theme = theme + self.useDarkTheme = useDarkTheme self.strings = strings self.animationView = ComponentView() self.presentController = presentController @@ -382,7 +384,7 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM transition: .immediate, component: AnyComponent(LottieComponent( content: LottieComponent.AppBundleContent(name: animationName), - color: self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) + color: self.useDarkTheme ? .white : self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) )), environment: {}, containerSize: animationFrame.size @@ -407,7 +409,7 @@ public final class ChatTextInputMediaRecordingButton: TGModernConversationInputM self.updateAnimation(previousMode: self.mode) self.pallete = legacyInputMicPalette(from: theme) - self.micDecorationValue?.setColor(self.theme.chat.inputPanel.actionControlFillColor) + self.micDecorationValue?.setColor( self.theme.chat.inputPanel.actionControlFillColor) (self.micLockValue as? LockView)?.updateTheme(theme) } diff --git a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/LockView.swift b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/LockView.swift index 6d798f1f5c..6f0e822ad5 100644 --- a/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/LockView.swift +++ b/submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton/Sources/LockView.swift @@ -5,7 +5,7 @@ import Lottie import TelegramPresentationData final class LockView: UIButton, TGModernConversationInputMicButtonLock { - //private var colorCallbacks = [LOTValueDelegate]() + private let useDarkTheme: Bool private let idleView: AnimationView = { guard let url = getAppBundle().url(forResource: "LockWait", withExtension: "json"), let animation = Animation.filepath(url.path) @@ -28,7 +28,9 @@ final class LockView: UIButton, TGModernConversationInputMicButtonLock { return view }() - init(frame: CGRect, theme: PresentationTheme, strings: PresentationStrings) { + init(frame: CGRect, theme: PresentationTheme, useDarkTheme: Bool = false, strings: PresentationStrings) { + self.useDarkTheme = useDarkTheme + super.init(frame: frame) accessibilityLabel = strings.VoiceOver_Recording_StopAndPreview @@ -60,8 +62,6 @@ final class LockView: UIButton, TGModernConversationInputMicButtonLock { } func updateTheme(_ theme: PresentationTheme) { - //colorCallbacks.removeAll() - [ "Rectangle.Заливка 1": theme.chat.inputPanel.panelBackgroundColor, "Rectangle.Rectangle.Обводка 1": theme.chat.inputPanel.panelControlAccentColor, @@ -69,9 +69,6 @@ final class LockView: UIButton, TGModernConversationInputMicButtonLock { "Path 4.Path 4.Обводка 1": theme.chat.inputPanel.panelControlAccentColor ].forEach { key, value in idleView.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color")) - /*let colorCallback = LOTColorValueCallback(color: value.cgColor) - self.colorCallbacks.append(colorCallback) - idleView.setValueDelegate(colorCallback, for: LOTKeypath(string: "\(key).Color"))*/ } [ @@ -82,9 +79,6 @@ final class LockView: UIButton, TGModernConversationInputMicButtonLock { "Path 4.Path 4.Обводка 1": theme.chat.inputPanel.panelControlAccentColor ].forEach { key, value in lockingView.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color")) - /*let colorCallback = LOTColorValueCallback(color: value.cgColor) - self.colorCallbacks.append(colorCallback) - lockingView.setValueDelegate(colorCallback, for: LOTKeypath(string: "\(key).Color"))*/ } } diff --git a/submodules/TelegramUI/Components/LottieComponent/Sources/LottieComponent.swift b/submodules/TelegramUI/Components/LottieComponent/Sources/LottieComponent.swift index cac3700c51..d167e45295 100644 --- a/submodules/TelegramUI/Components/LottieComponent/Sources/LottieComponent.swift +++ b/submodules/TelegramUI/Components/LottieComponent/Sources/LottieComponent.swift @@ -55,16 +55,24 @@ public final class LottieComponent: Component { return EmptyDisposable } } + + public enum StartingPosition { + case begin + case end + } public let content: Content public let color: UIColor + public let startingPosition: StartingPosition public init( content: Content, - color: UIColor + color: UIColor, + startingPosition: StartingPosition = .end ) { self.content = content self.color = color + self.startingPosition = startingPosition } public static func ==(lhs: LottieComponent, rhs: LottieComponent) -> Bool { @@ -74,6 +82,9 @@ public final class LottieComponent: Component { if lhs.color != rhs.color { return false } + if lhs.startingPosition != rhs.startingPosition { + return false + } return true } @@ -82,6 +93,7 @@ public final class LottieComponent: Component { private var component: LottieComponent? private var scheduledPlayOnce: Bool = false + private var playOnceCompletion: (() -> Void)? private var animationInstance: LottieInstance? private var currentDisplaySize: CGSize? private var currentContentDisposable: Disposable? @@ -147,7 +159,9 @@ public final class LottieComponent: Component { } } - public func playOnce(delay: Double = 0.0) { + public func playOnce(delay: Double = 0.0, completion: (() -> Void)? = nil) { + self.playOnceCompletion = completion + guard let _ = self.animationInstance else { self.scheduledPlayOnce = true return @@ -194,13 +208,18 @@ public final class LottieComponent: Component { } } - private func loadAnimation(data: Data, cacheKey: String?) { + private func loadAnimation(data: Data, cacheKey: String?, startingPosition: StartingPosition) { self.animationInstance = LottieInstance(data: data, fitzModifier: .none, colorReplacements: nil, cacheKey: cacheKey ?? "") if self.scheduledPlayOnce { self.scheduledPlayOnce = false self.playOnce() } else if let animationInstance = self.animationInstance { - self.currentFrame = Int(animationInstance.frameCount - 1) + switch startingPosition { + case .begin: + self.currentFrame = 0 + case .end: + self.currentFrame = Int(animationInstance.frameCount - 1) + } self.updateImage() } } @@ -222,12 +241,21 @@ public final class LottieComponent: Component { let timestamp = CACurrentMediaTime() if currentFrameStartTime + timestamp >= secondsPerFrame * 0.9 { - self.currentFrame += 1 + var advanceFrameCount = 1 + if animationInstance.frameRate == 360 { + advanceFrameCount = 6 + } + self.currentFrame += advanceFrameCount if self.currentFrame >= Int(animationInstance.frameCount) - 1 { self.currentFrame = Int(animationInstance.frameCount) - 1 self.updateImage() self.displayLink?.invalidate() self.displayLink = nil + + if let playOnceCompletion = self.playOnceCompletion { + self.playOnceCompletion = nil + playOnceCompletion() + } } else { self.currentFrameStartTime = timestamp self.updateImage() @@ -271,10 +299,10 @@ public final class LottieComponent: Component { let content = component.content self.currentContentDisposable = component.content.load { [weak self, weak content] data, cacheKey in Queue.mainQueue().async { - guard let self, self.component?.content == content else { + guard let self, let component = self.component, component.content == content else { return } - self.loadAnimation(data: data, cacheKey: cacheKey) + self.loadAnimation(data: data, cacheKey: cacheKey, startingPosition: component.startingPosition) } } } else if redrawImage { diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD b/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD index 902a174f7d..cf686876b6 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/BUILD @@ -16,9 +16,11 @@ swift_library( "//submodules/TelegramUI/Components/TextFieldComponent", "//submodules/Components/BundleIconComponent", "//submodules/TelegramUI/Components/ChatTextInputMediaRecordingButton", + "//submodules/TelegramUI/Components/LottieComponent", "//submodules/AccountContext", "//submodules/TelegramPresentationData", "//submodules/SSignalKit/SwiftSignalKit", + "//submodules/Components/HierarchyTrackingLayer", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MediaRecordingPanelComponent.swift b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MediaRecordingPanelComponent.swift index d545593c17..a1ebef11fb 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MediaRecordingPanelComponent.swift +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MediaRecordingPanelComponent.swift @@ -9,6 +9,8 @@ import AccountContext import TelegramPresentationData import ChatPresentationInterfaceState import SwiftSignalKit +import LottieComponent +import HierarchyTrackingLayer public final class MediaRecordingPanelComponent: Component { public let audioRecorder: ManagedAudioRecorder? @@ -42,10 +44,15 @@ public final class MediaRecordingPanelComponent: Component { private var component: MediaRecordingPanelComponent? private weak var state: EmptyComponentState? - private let indicatorView: UIImageView + private let trackingLayer: HierarchyTrackingLayer + private let indicator = ComponentView() + + private let cancelContainerView: UIView private let cancelIconView: UIImageView private let cancelText = ComponentView() + + private let timerFont: UIFont private let timerText = ComponentView() private var timerTextDisposable: Disposable? @@ -53,13 +60,26 @@ public final class MediaRecordingPanelComponent: Component { private var timerTextValue: String = "0:00,00" override init(frame: CGRect) { - self.indicatorView = UIImageView() + self.trackingLayer = HierarchyTrackingLayer() self.cancelIconView = UIImageView() + self.timerFont = Font.with(size: 15.0, design: .camera, traits: .monospacedNumbers) + + self.cancelContainerView = UIView() + super.init(frame: frame) - self.addSubview(self.indicatorView) - self.addSubview(self.cancelIconView) + self.layer.addSublayer(self.trackingLayer) + + self.cancelContainerView.addSubview(self.cancelIconView) + self.addSubview(self.cancelContainerView) + + self.trackingLayer.didEnterHierarchy = { [weak self] in + guard let self else { + return + } + self.updateAnimations() + } } required init?(coder: NSCoder) { @@ -70,6 +90,72 @@ public final class MediaRecordingPanelComponent: Component { self.timerTextDisposable?.dispose() } + private func updateAnimations() { + if let indicatorView = self.indicator.view { + if indicatorView.layer.animation(forKey: "recording") == nil { + 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 + + indicatorView.layer.add(animation, forKey: "recording") + } + } + if self.cancelContainerView.layer.animation(forKey: "recording") == nil { + let animation = CAKeyframeAnimation(keyPath: "position.x") + animation.values = [-5.0 as NSNumber, 5.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 = 1.5 + animation.autoreverses = true + animation.isAdditive = true + animation.repeatCount = Float.infinity + + self.cancelContainerView.layer.add(animation, forKey: "recording") + } + } + + public func animateIn() { + if let indicatorView = self.indicator.view { + indicatorView.layer.animatePosition(from: CGPoint(x: -20.0, y: 0.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + } + if let timerTextView = self.timerText.view { + timerTextView.layer.animatePosition(from: CGPoint(x: -20.0, y: 0.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + } + self.cancelContainerView.layer.animatePosition(from: CGPoint(x: self.bounds.width, y: 0.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + } + + public func animateOut(dismissRecording: Bool, completion: @escaping () -> Void) { + if let indicatorView = self.indicator.view as? LottieComponent.View { + if let _ = indicatorView.layer.animation(forKey: "recording") { + let fromAlpha = indicatorView.layer.presentation()?.opacity ?? indicatorView.layer.opacity + indicatorView.layer.removeAnimation(forKey: "recording") + indicatorView.layer.animateAlpha(from: CGFloat(fromAlpha), to: 1.0, duration: 0.2) + + indicatorView.playOnce(completion: { [weak indicatorView] in + if let indicatorView { + let transition = Transition(animation: .curve(duration: 0.3, curve: .spring)) + transition.setScale(view: indicatorView, scale: 0.001) + } + + completion() + }) + } + } else { + completion() + } + + + let transition = Transition(animation: .curve(duration: 0.3, curve: .spring)) + if let timerTextView = self.timerText.view { + transition.setAlpha(view: timerTextView, alpha: 0.0) + transition.setScale(view: timerTextView, scale: 0.001) + } + + transition.setAlpha(view: self.cancelContainerView, alpha: 0.0) + } + func update(component: MediaRecordingPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { let previousComponent = self.component self.component = component @@ -134,26 +220,36 @@ public final class MediaRecordingPanelComponent: Component { } } - if self.indicatorView.image == nil { - self.indicatorView.image = generateFilledCircleImage(diameter: 10.0, color: UIColor(rgb: 0xFF3B30)) - } - if let image = self.indicatorView.image { - transition.setFrame(view: self.indicatorView, frame: CGRect(origin: CGPoint(x: 10.0, y: floor((availableSize.height - image.size.height) * 0.5)), size: image.size)) + let indicatorSize = self.indicator.update( + transition: .immediate, + component: AnyComponent(LottieComponent( + content: LottieComponent.AppBundleContent(name: "BinRed"), + color: UIColor(rgb: 0xFF3B30), + startingPosition: .begin + )), + environment: {}, + containerSize: CGSize(width: 40.0, height: 40.0) + ) + if let indicatorView = self.indicator.view { + if indicatorView.superview == nil { + self.addSubview(indicatorView) + } + transition.setFrame(view: indicatorView, frame: CGRect(origin: CGPoint(x: 3.0, y: floor((availableSize.height - indicatorSize.height) * 0.5)), size: indicatorSize)) } let timerTextSize = self.timerText.update( transition: .immediate, - component: AnyComponent(Text(text: self.timerTextValue, font: Font.regular(15.0), color: .white)), + component: AnyComponent(Text(text: self.timerTextValue, font: self.timerFont, color: .white)), environment: {}, containerSize: CGSize(width: 100.0, height: 100.0) ) if let timerTextView = self.timerText.view { if timerTextView.superview == nil { self.addSubview(timerTextView) - timerTextView.layer.anchorPoint = CGPoint() + timerTextView.layer.anchorPoint = CGPoint(x: 0.0, y: 0.5) } - let timerTextFrame = CGRect(origin: CGPoint(x: 28.0, y: floor((availableSize.height - timerTextSize.height) * 0.5)), size: timerTextSize) - transition.setPosition(view: timerTextView, position: timerTextFrame.origin) + let timerTextFrame = CGRect(origin: CGPoint(x: 38.0, y: floor((availableSize.height - timerTextSize.height) * 0.5)), size: timerTextSize) + transition.setPosition(view: timerTextView, position: CGPoint(x: timerTextFrame.minX, y: timerTextFrame.midY)) timerTextView.bounds = CGRect(origin: CGPoint(), size: timerTextFrame.size) } @@ -161,11 +257,11 @@ public final class MediaRecordingPanelComponent: Component { self.cancelIconView.image = UIImage(bundleImageName: "Chat/Input/Text/AudioRecordingCancelArrow")?.withRenderingMode(.alwaysTemplate) } - self.cancelIconView.tintColor = UIColor(white: 1.0, alpha: 0.3) + self.cancelIconView.tintColor = UIColor(white: 1.0, alpha: 0.4) let cancelTextSize = self.cancelText.update( transition: .immediate, - component: AnyComponent(Text(text: "Slide to cancel", font: Font.regular(15.0), color: UIColor(white: 1.0, alpha: 0.3))), + component: AnyComponent(Text(text: "Slide to cancel", font: Font.regular(15.0), color: UIColor(white: 1.0, alpha: 0.4))), environment: {}, containerSize: CGSize(width: max(30.0, availableSize.width - 100.0), height: 44.0) ) @@ -182,7 +278,7 @@ public final class MediaRecordingPanelComponent: Component { if let cancelTextView = self.cancelText.view { if cancelTextView.superview == nil { - self.addSubview(cancelTextView) + self.cancelContainerView.addSubview(cancelTextView) } transition.setFrame(view: cancelTextView, frame: textFrame) } @@ -190,6 +286,8 @@ public final class MediaRecordingPanelComponent: Component { transition.setFrame(view: self.cancelIconView, frame: CGRect(origin: CGPoint(x: textFrame.minX - 4.0 - image.size.width, y: textFrame.minY + floor((textFrame.height - image.size.height) * 0.5)), size: image.size)) } + self.updateAnimations() + return availableSize } } diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputActionButtonComponent.swift b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputActionButtonComponent.swift index 5027017e01..7b8a35c899 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputActionButtonComponent.swift +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputActionButtonComponent.swift @@ -141,6 +141,7 @@ public final class MessageInputActionButtonComponent: Component { let micButton = ChatTextInputMediaRecordingButton( context: component.context, theme: component.theme, + useDarkTheme: true, strings: component.strings, presentController: component.presentController ) diff --git a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift index 0503b22043..6c13d7c648 100644 --- a/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift +++ b/submodules/TelegramUI/Components/MessageInputPanelComponent/Sources/MessageInputPanelComponent.swift @@ -90,6 +90,7 @@ public final class MessageInputPanelComponent: Component { private let stickerIconView: UIImageView private var mediaRecordingPanel: ComponentView? + private weak var dismissingMediaRecordingPanel: UIView? private var currentMediaInputIsVoice: Bool = true private var mediaCancelFraction: CGFloat = 0.0 @@ -202,8 +203,6 @@ public final class MessageInputPanelComponent: Component { self.addSubview(attachmentButtonView) } transition.setFrame(view: attachmentButtonView, frame: CGRect(origin: CGPoint(x: floor((insets.left - attachmentButtonSize.width) * 0.5), y: size.height - baseHeight + floor((baseHeight - attachmentButtonSize.height) * 0.5)), size: attachmentButtonSize)) - - transition.setAlpha(view: attachmentButtonView, alpha: (component.audioRecorder != nil || component.videoRecordingStatus != nil) ? 0.0 : 1.0) } let inputActionButtonSize = self.inputActionButton.update( @@ -272,6 +271,13 @@ public final class MessageInputPanelComponent: Component { component.externalState.hasText = self.textFieldExternalState.hasText if component.audioRecorder != nil || component.videoRecordingStatus != nil { + if let dismissingMediaRecordingPanel = self.dismissingMediaRecordingPanel { + self.dismissingMediaRecordingPanel = nil + transition.setAlpha(view: dismissingMediaRecordingPanel, alpha: 0.0, completion: { [weak dismissingMediaRecordingPanel] _ in + dismissingMediaRecordingPanel?.removeFromSuperview() + }) + } + let mediaRecordingPanel: ComponentView var mediaRecordingPanelTransition = transition if let current = self.mediaRecordingPanel { @@ -292,7 +298,7 @@ public final class MessageInputPanelComponent: Component { environment: {}, containerSize: size ) - if let mediaRecordingPanelView = mediaRecordingPanel.view { + if let mediaRecordingPanelView = mediaRecordingPanel.view as? MediaRecordingPanelComponent.View { var animateIn = false if mediaRecordingPanelView.superview == nil { animateIn = true @@ -300,16 +306,43 @@ public final class MessageInputPanelComponent: Component { } mediaRecordingPanelTransition.setFrame(view: mediaRecordingPanelView, frame: CGRect(origin: CGPoint(), size: size)) if animateIn && !transition.animation.isImmediate { - transition.animateAlpha(view: mediaRecordingPanelView, from: 0.0, to: 1.0) + mediaRecordingPanelView.animateIn() } } + + if let attachmentButtonView = self.attachmentButton.view { + transition.setAlpha(view: attachmentButtonView, alpha: 0.0) + } } else { if let mediaRecordingPanel = self.mediaRecordingPanel { self.mediaRecordingPanel = nil - if let mediaRecordingPanelView = mediaRecordingPanel.view { - transition.setAlpha(view: mediaRecordingPanelView, alpha: 0.0, completion: { [weak mediaRecordingPanelView] _ in - mediaRecordingPanelView?.removeFromSuperview() + if let dismissingMediaRecordingPanel = self.dismissingMediaRecordingPanel { + self.dismissingMediaRecordingPanel = nil + transition.setAlpha(view: dismissingMediaRecordingPanel, alpha: 0.0, completion: { [weak dismissingMediaRecordingPanel] _ in + dismissingMediaRecordingPanel?.removeFromSuperview() + }) + } + + self.dismissingMediaRecordingPanel = mediaRecordingPanel.view + + if let mediaRecordingPanelView = mediaRecordingPanel.view as? MediaRecordingPanelComponent.View { + mediaRecordingPanelView.animateOut(dismissRecording: true, completion: { [weak self, weak mediaRecordingPanelView] in + let transition = Transition(animation: .curve(duration: 0.3, curve: .spring)) + + if let mediaRecordingPanelView = mediaRecordingPanelView { + transition.setAlpha(view: mediaRecordingPanelView, alpha: 0.0, completion: { [weak mediaRecordingPanelView] _ in + mediaRecordingPanelView?.removeFromSuperview() + }) + } + + guard let self else { + return + } + if self.mediaRecordingPanel == nil, let attachmentButtonView = self.attachmentButton.view { + transition.setAlpha(view: attachmentButtonView, alpha: 1.0) + transition.animateScale(view: attachmentButtonView, from: 0.001, to: 1.0) + } }) } } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift index 88f955f53b..30e23668f2 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryContainerScreen.swift @@ -461,7 +461,7 @@ private final class StoryContainerScreenComponent: Component { itemTransition.setFrame(view: view, frame: CGRect(origin: CGPoint(), size: itemLayout.size)) if let view = view as? StoryContentItem.View { - view.setIsProgressPaused(self.inputPanelExternalState.isEditing || self.attachmentController != nil) + view.setIsProgressPaused(self.inputPanelExternalState.isEditing || self.attachmentController != nil || self.audioRecorderValue != nil || self.videoRecorderValue != nil) } } } @@ -484,7 +484,7 @@ private final class StoryContainerScreenComponent: Component { for (_, visibleItem) in self.visibleItems { if let view = visibleItem.view.view { if let view = view as? StoryContentItem.View { - view.setIsProgressPaused(self.inputPanelExternalState.isEditing || self.attachmentController?.window != nil) + view.setIsProgressPaused(self.inputPanelExternalState.isEditing || self.attachmentController?.window != nil || self.audioRecorderValue != nil || self.videoRecorderValue != nil) } } } diff --git a/submodules/rlottie/LottieInstance.mm b/submodules/rlottie/LottieInstance.mm index f9da05da3e..1d40bc2aab 100755 --- a/submodules/rlottie/LottieInstance.mm +++ b/submodules/rlottie/LottieInstance.mm @@ -61,7 +61,7 @@ _dimensions = CGSizeMake(width, height); - if ((_frameRate > 60) || _animation->duration() > 9.0) { + if ((_frameRate > 360) || _animation->duration() > 9.0) { return nil; } }