Merge commit '3f6ac92df77e0f26115998191176f58ab38b060c'

This commit is contained in:
Isaac 2024-01-14 22:13:50 +04:00
commit ea35164d1f
6 changed files with 359 additions and 85 deletions

View File

@ -1022,6 +1022,16 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
return rects
}
public func animateInstantVideoFromSnapshot(snapshotView: UIView, transition: CombinedTransition) {
for contentNode in self.contentNodes {
if let contentNode = contentNode as? ChatMessageInstantVideoBubbleContentNode {
snapshotView.frame = contentNode.interactiveVideoNode.view.convert(snapshotView.frame, from: self.view)
contentNode.interactiveVideoNode.animateFromSnapshot(snapshotView: snapshotView, transition: transition)
return
}
}
}
override public func didLoad() {
super.didLoad()

View File

@ -1778,9 +1778,16 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
if !self.animatedFadeIn {
self.animatedFadeIn = true
self.dateAndStatusNode.layer.animateAlpha(from: 0.0, to: self.dateAndStatusNode.alpha, duration: 0.15, delay: 0.18)
if let durationNode = self.durationNode {
durationNode.layer.animateAlpha(from: 0.0, to: durationNode.alpha, duration: 0.15, delay: 0.18)
}
if let durationBackgroundNode = self.durationBackgroundNode {
durationBackgroundNode.layer.animateAlpha(from: 0.0, to: durationBackgroundNode.alpha, duration: 0.15, delay: 0.18)
}
if let audioTranscriptionButton = self.audioTranscriptionButton {
audioTranscriptionButton.layer.animateAlpha(from: 0.0, to: audioTranscriptionButton.alpha, duration: 0.15, delay: 0.18)
}
}
}

View File

@ -0,0 +1,115 @@
import Foundation
import UIKit
import HierarchyTrackingLayer
import ComponentFlow
import Display
private let shadowImage: UIImage? = {
UIImage(named: "Stories/PanelGradient")
}()
final class LoadingEffectView: UIView {
private let duration: Double
private let hierarchyTrackingLayer: HierarchyTrackingLayer
private let gradientWidth: CGFloat
private let backgroundView: UIImageView
private let borderGradientView: UIImageView
private let borderContainerView: UIView
let borderMaskLayer: SimpleShapeLayer
init(effectAlpha: CGFloat, borderAlpha: CGFloat, gradientWidth: CGFloat = 200.0, duration: Double) {
self.hierarchyTrackingLayer = HierarchyTrackingLayer()
self.duration = duration
self.gradientWidth = gradientWidth
self.backgroundView = UIImageView()
self.borderGradientView = UIImageView()
self.borderContainerView = UIView()
self.borderMaskLayer = SimpleShapeLayer()
super.init(frame: .zero)
self.layer.addSublayer(self.hierarchyTrackingLayer)
self.hierarchyTrackingLayer.didEnterHierarchy = { [weak self] in
guard let self, self.bounds.width != 0.0 else {
return
}
self.updateAnimations(size: self.bounds.size)
}
let generateGradient: (CGFloat) -> UIImage? = { baseAlpha in
return generateImage(CGSize(width: self.gradientWidth, height: 16.0), opaque: false, scale: 1.0, rotatedContext: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
let foregroundColor = UIColor(white: 1.0, alpha: min(1.0, baseAlpha * 4.0))
if let shadowImage {
UIGraphicsPushContext(context)
for i in 0 ..< 2 {
let shadowFrame = CGRect(origin: CGPoint(x: CGFloat(i) * (size.width * 0.5), y: 0.0), size: CGSize(width: size.width * 0.5, height: size.height))
context.saveGState()
context.translateBy(x: shadowFrame.midX, y: shadowFrame.midY)
context.rotate(by: CGFloat(i == 0 ? 1.0 : -1.0) * CGFloat.pi * 0.5)
let adjustedRect = CGRect(origin: CGPoint(x: -shadowFrame.height * 0.5, y: -shadowFrame.width * 0.5), size: CGSize(width: shadowFrame.height, height: shadowFrame.width))
context.clip(to: adjustedRect, mask: shadowImage.cgImage!)
context.setFillColor(foregroundColor.cgColor)
context.fill(adjustedRect)
context.restoreGState()
}
UIGraphicsPopContext()
}
})
}
self.backgroundView.image = generateGradient(effectAlpha)
self.addSubview(self.backgroundView)
self.borderGradientView.image = generateGradient(borderAlpha)
self.borderContainerView.addSubview(self.borderGradientView)
self.addSubview(self.borderContainerView)
self.borderContainerView.layer.mask = self.borderMaskLayer
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func updateAnimations(size: CGSize) {
if self.backgroundView.layer.animation(forKey: "shimmer") != nil {
return
}
let animation = self.backgroundView.layer.makeAnimation(from: 0.0 as NSNumber, to: (size.width + self.gradientWidth + size.width * 0.2) as NSNumber, keyPath: "position.x", timingFunction: CAMediaTimingFunctionName.easeOut.rawValue, duration: self.duration, delay: 0.0, mediaTimingFunction: nil, removeOnCompletion: true, additive: true)
animation.repeatCount = Float.infinity
self.backgroundView.layer.add(animation, forKey: "shimmer")
self.borderGradientView.layer.add(animation, forKey: "shimmer")
}
func update(size: CGSize, transition: Transition) {
if self.backgroundView.bounds.size != size {
self.backgroundView.layer.removeAllAnimations()
self.borderMaskLayer.fillColor = nil
self.borderMaskLayer.strokeColor = UIColor.white.cgColor
let lineWidth: CGFloat = 3.0
self.borderMaskLayer.lineWidth = lineWidth
self.borderMaskLayer.path = UIBezierPath(ovalIn: CGRect(origin: .zero, size: size)).cgPath
transition.setFrame(view: self.backgroundView, frame: CGRect(origin: CGPoint(x: -self.gradientWidth, y: 0.0), size: CGSize(width: self.gradientWidth, height: size.height)))
transition.setFrame(view: self.borderContainerView, frame: CGRect(origin: CGPoint(), size: size))
transition.setFrame(view: self.borderGradientView, frame: CGRect(origin: CGPoint(x: -self.gradientWidth, y: 0.0), size: CGSize(width: self.gradientWidth, height: size.height)))
}
self.updateAnimations(size: size)
}
}

View File

@ -76,8 +76,10 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
let context: AccountContext
let cameraState: CameraState
let previewFrame: CGRect
let isPreviewing: Bool
let isMuted: Bool
let totalDuration: Double
let getController: () -> VideoMessageCameraScreen?
let present: (ViewController) -> Void
let push: (ViewController) -> Void
@ -88,8 +90,10 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
init(
context: AccountContext,
cameraState: CameraState,
previewFrame: CGRect,
isPreviewing: Bool,
isMuted: Bool,
totalDuration: Double,
getController: @escaping () -> VideoMessageCameraScreen?,
present: @escaping (ViewController) -> Void,
push: @escaping (ViewController) -> Void,
@ -99,8 +103,10 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
) {
self.context = context
self.cameraState = cameraState
self.previewFrame = previewFrame
self.isPreviewing = isPreviewing
self.isMuted = isMuted
self.totalDuration = totalDuration
self.getController = getController
self.present = present
self.push = push
@ -113,6 +119,9 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
if lhs.context !== rhs.context {
return false
}
if lhs.previewFrame != rhs.previewFrame {
return false
}
if lhs.cameraState != rhs.cameraState {
return false
}
@ -122,6 +131,9 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
if lhs.isMuted != rhs.isMuted {
return false
}
if lhs.totalDuration != rhs.totalDuration {
return false
}
return true
}
@ -244,12 +256,12 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
let duration = initialDuration + recordingData.duration
if let self, let controller = self.getController() {
controller.updateCameraState({ $0.updatedDuration(duration) }, transition: .easeInOut(duration: 0.1))
if duration > 59.0 {
self.stopVideoRecording()
}
if isFirstRecording {
controller.node.setupLiveUpload(filePath: recordingData.filePath)
}
if duration > 59.5 {
controller.onStop()
}
}
}))
}
@ -304,6 +316,8 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
let viewOnceButton = Child(PlainButtonComponent.self)
let recordMoreButton = Child(PlainButtonComponent.self)
let muteIcon = Child(ZStack<Empty>.self)
return { context in
let environment = context.environment[ViewControllerComponentContainer.Environment.self].value
@ -319,15 +333,23 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
var showRecordMore = false
if component.isPreviewing {
showViewOnce = true
showRecordMore = true
viewOnceOffset = 67.0
if component.totalDuration < 59.0 {
showRecordMore = true
viewOnceOffset = 67.0
} else {
viewOnceOffset = 14.0
}
} else if case .handsFree = component.cameraState.recording {
showViewOnce = true
}
if let controller = component.getController(), !controller.viewOnceAvailable {
showViewOnce = false
if let controller = component.getController() {
if controller.isSendingImmediately || controller.scheduledLock {
showViewOnce = true
}
if !controller.viewOnceAvailable {
showViewOnce = false
}
}
if !component.isPreviewing {
@ -444,14 +466,35 @@ private final class VideoMessageCameraScreenComponent: CombinedComponent {
)
}
// var isVideoRecording = false
// if case .video = component.cameraState.mode {
// isVideoRecording = true
// } else if component.cameraState.recording != .none {
// isVideoRecording = true
// }
if component.isPreviewing && component.isMuted {
let muteIcon = muteIcon.update(
component: ZStack([
AnyComponentWithIdentity(
id: "background",
component: AnyComponent(
RoundedRectangle(color: UIColor(rgb: 0x000000, alpha: 0.3), cornerRadius: 24.0)
)
),
AnyComponentWithIdentity(
id: "icon",
component: AnyComponent(
BundleIconComponent(
name: "Chat/Message/InstantVideoMute",
tintColor: .white
)
)
)
]),
availableSize: CGSize(width: 24.0, height: 24.0),
transition: context.transition
)
context.add(muteIcon
.position(CGPoint(x: component.previewFrame.midX, y: component.previewFrame.maxY - 24.0))
.appear(.default(scale: true, alpha: true))
.disappear(.default(scale: true, alpha: true))
)
}
return availableSize
}
}
@ -483,13 +526,16 @@ public class VideoMessageCameraScreen: ViewController {
fileprivate let containerView: UIView
fileprivate let componentHost: ComponentView<ViewControllerComponentContainer.Environment>
fileprivate let previewContainerView: UIView
private var previewSnapshotView: UIView?
private var previewBlurView: BlurView
fileprivate var mainPreviewView: CameraSimplePreviewView
fileprivate var additionalPreviewView: CameraSimplePreviewView
private var progressView: RecordingProgressView
private let loadingView: LoadingEffectView
private var resultPreviewView: ResultPreviewView?
private var cameraStateDisposable: Disposable?
private let idleTimerExtensionDisposable = MetaDisposable()
@ -560,6 +606,11 @@ public class VideoMessageCameraScreen: ViewController {
self.progressView = RecordingProgressView(frame: .zero)
self.loadingView = LoadingEffectView(effectAlpha: 0.1, borderAlpha: 0.25, duration: 1.0)
self.previewBlurView = BlurView()
self.previewBlurView.isUserInteractionEnabled = false
if isDualCameraEnabled {
self.mainPreviewView.resetPlaceholder(front: false)
self.additionalPreviewView.resetPlaceholder(front: true)
@ -589,17 +640,27 @@ public class VideoMessageCameraScreen: ViewController {
self.previewContainerView.addSubview(self.mainPreviewView)
self.previewContainerView.addSubview(self.additionalPreviewView)
self.previewContainerView.addSubview(self.progressView)
self.previewContainerView.addSubview(self.previewBlurView)
self.previewContainerView.addSubview(self.loadingView)
self.completion.connect { [weak self] result in
if let self {
self.addCaptureResult(result)
}
}
self.mainPreviewView.removePlaceholder(delay: 0.0)
if isDualCameraEnabled {
self.mainPreviewView.removePlaceholder(delay: 0.0)
}
self.withReadyCamera(isFirstTime: true, {
self.additionalPreviewView.removePlaceholder(delay: 0.35)
self.startRecording.invoke(Void())
if isDualCameraEnabled {
self.mainPreviewView.removePlaceholder(delay: 0.0)
}
self.loadingView.alpha = 0.0
self.additionalPreviewView.removePlaceholder(delay: 0.0)
Queue.mainQueue().after(0.15) {
self.startRecording.invoke(Void())
}
})
self.idleTimerExtensionDisposable.set(self.context.sharedContext.applicationBindings.pushIdleTimerExtension())
@ -744,10 +805,43 @@ public class VideoMessageCameraScreen: ViewController {
func resumeCameraCapture() {
if !self.mainPreviewView.isEnabled {
if let snapshotView = self.previewContainerView.snapshotView(afterScreenUpdates: false) {
self.previewContainerView.insertSubview(snapshotView, belowSubview: self.previewBlurView)
self.previewSnapshotView = snapshotView
}
self.mainPreviewView.isEnabled = true
self.additionalPreviewView.isEnabled = true
self.camera?.startCapture()
UIView.animate(withDuration: 0.25, animations: {
self.loadingView.alpha = 1.0
self.previewBlurView.effect = UIBlurEffect(style: .dark)
})
let action = { [weak self] in
guard let self else {
return
}
UIView.animate(withDuration: 0.4, animations: {
self.previewBlurView.effect = nil
self.previewSnapshotView?.alpha = 0.0
}, completion: { _ in
self.previewSnapshotView?.removeFromSuperview()
self.previewSnapshotView = nil
})
}
if #available(iOS 13.0, *) {
let _ = (self.mainPreviewView.isPreviewing
|> filter { $0 }
|> take(1)).startStandalone(next: { _ in
action()
})
} else {
Queue.mainQueue().after(1.0) {
action()
}
}
self.cameraIsActive = true
self.requestUpdateLayout(transition: .immediate)
}
@ -776,10 +870,12 @@ public class VideoMessageCameraScreen: ViewController {
self.transitioningToPreview = false
let composition = composition(with: self.results)
controller.updatePreviewState({ _ in
return PreviewState(composition: composition, trimRange: nil, isMuted: true)
}, transition: .spring(duration: 0.4))
if !controller.isSendingImmediately {
let composition = composition(with: self.results)
controller.updatePreviewState({ _ in
return PreviewState(composition: composition, trimRange: nil, isMuted: true)
}, transition: .spring(duration: 0.4))
}
}
private func debugSaveResult(path: String) {
@ -797,8 +893,16 @@ public class VideoMessageCameraScreen: ViewController {
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let result = super.hitTest(point, with: event)
if let resultPreviewView = self.resultPreviewView {
if resultPreviewView.bounds.contains(self.view.convert(point, to: resultPreviewView)) {
return resultPreviewView
}
}
if let controller = self.controller, let layout = self.validLayout {
if point.y > layout.size.height - controller.inputPanelFrame.height - 34.0 {
let insets = layout.insets(options: .input)
if point.y > layout.size.height - insets.bottom - controller.inputPanelFrame.height {
if layout.metrics.isTablet {
if point.x < layout.size.width * 0.33 {
return result
@ -807,6 +911,7 @@ public class VideoMessageCameraScreen: ViewController {
return nil
}
}
return result
}
@ -916,8 +1021,6 @@ public class VideoMessageCameraScreen: ViewController {
let isFirstTime = self.validLayout == nil
self.validLayout = layout
// let isTablet = layout.metrics.isTablet
let environment = ViewControllerComponentContainer.Environment(
statusBarHeight: layout.statusBarHeight ?? 0.0,
navigationHeight: 0.0,
@ -944,7 +1047,45 @@ public class VideoMessageCameraScreen: ViewController {
self.didAppear()
}
let backgroundFrame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: controller.inputPanelFrame.minY))
var backgroundFrame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: controller.inputPanelFrame.minY))
if backgroundFrame.maxY < layout.size.height - 100.0 && (layout.inputHeight ?? 0.0).isZero {
backgroundFrame = CGRect(origin: .zero, size: CGSize(width: layout.size.width, height: layout.size.height - layout.intrinsicInsets.bottom - controller.inputPanelFrame.height))
}
transition.setPosition(view: self.backgroundView, position: backgroundFrame.center)
transition.setBounds(view: self.backgroundView, bounds: CGRect(origin: .zero, size: backgroundFrame.size))
transition.setPosition(view: self.containerView, position: backgroundFrame.center)
transition.setBounds(view: self.containerView, bounds: CGRect(origin: .zero, size: backgroundFrame.size))
let availableHeight = layout.size.height - (layout.inputHeight ?? 0.0)
let previewSide = min(369.0, layout.size.width - 24.0)
let previewFrame: CGRect
if layout.metrics.isTablet {
previewFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - previewSide) / 2.0), y: max(layout.statusBarHeight ?? 0.0 + 24.0, availableHeight * 0.2 - previewSide / 2.0)), size: CGSize(width: previewSide, height: previewSide))
} else {
previewFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - previewSide) / 2.0), y: max(layout.statusBarHeight ?? 0.0 + 16.0, availableHeight * 0.4 - previewSide / 2.0)), size: CGSize(width: previewSide, height: previewSide))
}
if !self.animatingIn {
transition.setFrame(view: self.previewContainerView, frame: previewFrame)
}
transition.setCornerRadius(layer: self.previewContainerView.layer, cornerRadius: previewSide / 2.0)
let previewInnerFrame = CGRect(origin: .zero, size: previewFrame.size)
let additionalPreviewSize = CGSize(width: previewFrame.size.width, height: previewFrame.size.width / 3.0 * 4.0)
let additionalPreviewInnerFrame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((previewFrame.height - additionalPreviewSize.height) / 2.0)), size: additionalPreviewSize)
self.mainPreviewView.frame = previewInnerFrame
self.additionalPreviewView.frame = additionalPreviewInnerFrame
self.progressView.frame = previewInnerFrame
self.progressView.value = CGFloat(self.cameraState.duration / 60.0)
transition.setAlpha(view: self.additionalPreviewView, alpha: self.cameraState.position == .front ? 1.0 : 0.0)
self.previewBlurView.frame = previewInnerFrame
self.previewSnapshotView?.frame = previewInnerFrame
self.loadingView.update(size: previewInnerFrame.size, transition: .immediate)
let componentSize = self.componentHost.update(
transition: transition,
@ -952,8 +1093,10 @@ public class VideoMessageCameraScreen: ViewController {
VideoMessageCameraScreenComponent(
context: self.context,
cameraState: self.cameraState,
previewFrame: previewFrame,
isPreviewing: self.previewState != nil || self.transitioningToPreview,
isMuted: self.previewState?.isMuted ?? true,
totalDuration: self.previewState?.composition.duration.seconds ?? 0.0,
getController: { [weak self] in
return self?.controller
},
@ -984,37 +1127,6 @@ public class VideoMessageCameraScreen: ViewController {
transition.setFrame(view: componentView, frame: componentFrame)
}
transition.setPosition(view: self.backgroundView, position: backgroundFrame.center)
transition.setBounds(view: self.backgroundView, bounds: CGRect(origin: .zero, size: backgroundFrame.size))
transition.setPosition(view: self.containerView, position: backgroundFrame.center)
transition.setBounds(view: self.containerView, bounds: CGRect(origin: .zero, size: backgroundFrame.size))
let availableHeight = layout.size.height - (layout.inputHeight ?? 0.0)
let previewSide = min(369.0, layout.size.width - 24.0)
let previewFrame: CGRect
if layout.metrics.isTablet {
previewFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - previewSide) / 2.0), y: max(layout.statusBarHeight ?? 0.0 + 24.0, availableHeight * 0.2 - previewSide / 2.0)), size: CGSize(width: previewSide, height: previewSide))
} else {
previewFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - previewSide) / 2.0), y: max(layout.statusBarHeight ?? 0.0 + 16.0, availableHeight * 0.4 - previewSide / 2.0)), size: CGSize(width: previewSide, height: previewSide))
}
if !self.animatingIn {
transition.setFrame(view: self.previewContainerView, frame: previewFrame)
}
transition.setCornerRadius(layer: self.previewContainerView.layer, cornerRadius: previewSide / 2.0)
let previewInnerFrame = CGRect(origin: .zero, size: previewFrame.size)
let additionalPreviewSize = CGSize(width: previewFrame.size.width, height: previewFrame.size.width / 3.0 * 4.0)
let additionalPreviewInnerFrame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((previewFrame.height - additionalPreviewSize.height) / 2.0)), size: additionalPreviewSize)
self.mainPreviewView.frame = previewInnerFrame
self.additionalPreviewView.frame = additionalPreviewInnerFrame
self.progressView.frame = previewInnerFrame
self.progressView.value = CGFloat(self.cameraState.duration / 60.0)
transition.setAlpha(view: self.additionalPreviewView, alpha: self.cameraState.position == .front ? 1.0 : 0.0)
if let previewState = self.previewState {
if previewState.composition !== self.resultPreviewView?.composition {
self.resultPreviewView?.removeFromSuperview()
@ -1105,10 +1217,7 @@ public class VideoMessageCameraScreen: ViewController {
private let micLevelValue = ValuePromise<Float>(0.0)
private let durationValue = ValuePromise<TimeInterval>(0.0)
public let recordingStatus: RecordingStatus
public var onDismiss: (Bool) -> Void = { _ in
}
public var onStop: () -> Void = {
}
@ -1251,6 +1360,7 @@ public class VideoMessageCameraScreen: ViewController {
super.displayNodeDidLoad()
}
fileprivate var isSendingImmediately = false
public func sendVideoRecording() {
if case .none = self.cameraState.recording, self.node.results.isEmpty {
self.completion(nil)
@ -1259,6 +1369,7 @@ public class VideoMessageCameraScreen: ViewController {
if case .none = self.cameraState.recording {
} else {
self.isSendingImmediately = true
self.waitingForNextResult = true
self.node.stopRecording.invoke(Void())
}
@ -1362,6 +1473,8 @@ public class VideoMessageCameraScreen: ViewController {
private var waitingForNextResult = false
public func stopVideoRecording() -> Bool {
self.node.dismissAllTooltips()
self.waitingForNextResult = true
self.node.transitioningToPreview = true
self.node.requestUpdateLayout(transition: .spring(duration: 0.4))
@ -1376,6 +1489,7 @@ public class VideoMessageCameraScreen: ViewController {
public func lockVideoRecording() {
if case .none = self.cameraState.recording {
self.scheduledLock = true
self.node.requestUpdateLayout(transition: .spring(duration: 0.4))
} else {
self.updateCameraState({ $0.updatedRecording(.handsFree) }, transition: .spring(duration: 0.4))
}
@ -1396,7 +1510,7 @@ public class VideoMessageCameraScreen: ViewController {
}
public func hideVideoSnapshot() {
self.node.previewContainerView.alpha = 0.02
self.node.previewContainerView.isHidden = true
}
public func updateTrimRange(start: Double, end: Double, updatedEnd: Bool, apply: Bool) {
@ -1465,3 +1579,46 @@ private func composition(with results: [VideoMessageCameraScreen.CaptureResult])
}
return composition
}
private class BlurView: UIVisualEffectView {
private func setup() {
for subview in self.subviews {
if subview.description.contains("VisualEffectSubview") {
subview.isHidden = true
}
}
if let sublayer = self.layer.sublayers?[0], let filters = sublayer.filters {
sublayer.backgroundColor = nil
sublayer.isOpaque = false
let allowedKeys: [String] = [
"gaussianBlur"
]
sublayer.filters = filters.filter { filter in
guard let filter = filter as? NSObject else {
return true
}
let filterName = String(describing: filter)
if !allowedKeys.contains(filterName) {
return false
}
return true
}
}
}
override var effect: UIVisualEffect? {
get {
return super.effect
}
set {
super.effect = newValue
self.setup()
}
}
override func didAddSubview(_ subview: UIView) {
super.didAddSubview(subview)
self.setup()
}
}

View File

@ -6195,19 +6195,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
if let videoRecorder = videoRecorder {
strongSelf.recorderFeedback?.impact(.light)
videoRecorder.onDismiss = { [weak self] isCancelled in
self?.chatDisplayNode.updateRecordedMediaDeleted(isCancelled)
self?.beginMediaRecordingRequestId += 1
self?.lockMediaRecordingRequestId = nil
self?.videoRecorder.set(.single(nil))
}
videoRecorder.onStop = {
if let strongSelf = self {
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: true, {
$0.updatedInputTextPanelState { panelState in
return panelState.withUpdatedMediaRecordingState(.video(status: .editing, isLocked: false))
}
})
strongSelf.dismissMediaRecorder(.pause)
}
}
strongSelf.present(videoRecorder, in: .window(.root))
@ -15352,7 +15342,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
func deactivateRaiseGesture() {
self.raiseToListenActivateRecordingTimer?.invalidate()
self.raiseToListenActivateRecordingTimer = nil
self.dismissMediaRecorder(.preview)
self.dismissMediaRecorder(.pause)
}
func requestAudioRecorder(beginWithTone: Bool) {
@ -15617,12 +15607,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
}))
// self.updateChatPresentationInterfaceState(animated: true, interactive: true, {
// $0.updatedInputTextPanelState { panelState in
// return panelState.withUpdatedMediaRecordingState(.video(status: .editing, isLocked: false))
// }
// })
}
default:
self.recorderDataDisposable.set(nil)
@ -15687,6 +15671,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
self.videoRecorder.set(.single(nil))
}
self.recorderDataDisposable.set(nil)
self.chatDisplayNode.updateRecordedMediaDeleted(true)
self.updateChatPresentationInterfaceState(animated: true, interactive: true, {
$0.updatedRecordedMediaPreview(nil)

View File

@ -635,7 +635,7 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
case let .videoMessage(videoMessage):
let combinedTransition = CombinedTransition(horizontal: .animated(duration: horizontalDuration, curve: ChatMessageTransitionNodeImpl.horizontalAnimationCurve), vertical: .animated(duration: verticalDuration, curve: ChatMessageTransitionNodeImpl.verticalAnimationCurve))
if let itemNode = self.itemNode as? ChatMessageInstantVideoItemNode {
if let itemNode = self.itemNode as? ChatMessageBubbleItemNode {
itemNode.cancelInsertionAnimations()
self.contextSourceNode.isExtractedToContextPreview = true
@ -659,7 +659,7 @@ public final class ChatMessageTransitionNodeImpl: ASDisplayNode, ChatMessageTran
strongSelf.endAnimation()
})
itemNode.animateFromSnapshot(snapshotView: videoMessage.view, transition: combinedTransition)
itemNode.animateInstantVideoFromSnapshot(snapshotView: videoMessage.view, transition: combinedTransition)
}
case let .mediaInput(mediaInput):
if let snapshotView = mediaInput.extractSnapshot() {