From be9ce8501c35589e9613ec2e387447c344ee471f Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 11 Jun 2021 01:07:29 +0300 Subject: [PATCH 1/3] Fix video encoding failing on 4k 60fps videos --- .../Sources/TGMediaVideoConverter.m | 14 ++++++++++---- .../Sources/PresentationGroupCall.swift | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/submodules/LegacyComponents/Sources/TGMediaVideoConverter.m b/submodules/LegacyComponents/Sources/TGMediaVideoConverter.m index 35ecd6a849..5f17313390 100644 --- a/submodules/LegacyComponents/Sources/TGMediaVideoConverter.m +++ b/submodules/LegacyComponents/Sources/TGMediaVideoConverter.m @@ -362,14 +362,19 @@ AVMutableCompositionTrack *compositionTrack = [composition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid]; [compositionTrack insertTimeRange:timeRange ofTrack:videoTrack atTime:kCMTimeZero error:NULL]; - CMTime frameDuration = CMTimeMake(1, 30); + CMTime frameDuration30FPS = CMTimeMake(1, 30); + CMTime frameDuration = frameDuration30FPS; if (videoTrack.nominalFrameRate > 0) frameDuration = CMTimeMake(1, (int32_t)videoTrack.nominalFrameRate); else if (CMTimeCompare(videoTrack.minFrameDuration, kCMTimeZero) == 1) frameDuration = videoTrack.minFrameDuration; if (CMTimeCompare(frameDuration, kCMTimeZero) != 1 || !CMTIME_IS_VALID(frameDuration) || image != nil || entityRenderer != nil || adjustments.toolsApplied) - frameDuration = CMTimeMake(1, 30); + frameDuration = frameDuration30FPS; + + if (CMTimeCompare(frameDuration, frameDuration30FPS)) { + frameDuration = frameDuration30FPS; + } NSInteger fps = (NSInteger)(1.0 / CMTimeGetSeconds(frameDuration)); @@ -889,7 +894,7 @@ + (NSURL *)_randomTemporaryURL { - return [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSString alloc] initWithFormat:@"%x.tmp", (int)arc4random()]]]; + return [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:[[NSString alloc] initWithFormat:@"%x.mp4", (int)arc4random()]]]; } + (NSUInteger)estimatedSizeForPreset:(TGMediaVideoConversionPreset)preset duration:(NSTimeInterval)duration hasAudio:(bool)hasAudio @@ -1320,7 +1325,8 @@ static CGFloat progressOfSampleBufferInTimeRange(CMSampleBufferRef sampleBuffer, { AVVideoAverageBitRateKey: @([self _videoBitrateKbpsForPreset:preset] * 1000), AVVideoCleanApertureKey: videoCleanApertureSettings, - AVVideoPixelAspectRatioKey: videoAspectRatioSettings + AVVideoPixelAspectRatioKey: videoAspectRatioSettings, + AVVideoExpectedSourceFrameRateKey: @30 }; NSDictionary *hdVideoProperties = @ diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index f8b047ea8f..782803414c 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -2562,13 +2562,13 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.isVideoMutedDisposable.set(nil) self.genericCallContext?.disableVideo() self.isVideoMuted = true - + self.updateLocalVideoState() } } private func updateLocalVideoState() { - self.participantsContext?.updateVideoState(peerId: self.joinAsPeerId, isVideoMuted: self.videoCapturer == nil, isVideoPaused: self.isVideoMuted, isPresentationPaused: false) + self.participantsContext?.updateVideoState(peerId: self.joinAsPeerId, isVideoMuted: self.videoCapturer == nil, isVideoPaused: self.isVideoMuted, isPresentationPaused: nil) } public func switchVideoCamera() { From 4d952b97d085716e4ff73870d1e69911f61562c4 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 11 Jun 2021 03:21:17 +0300 Subject: [PATCH 2/3] Add blur to sticker placeholders --- .../Sources/StickerShimmerEffectNode.swift | 27 +++++++++++++++---- .../Sources/DefaultDayPresentationTheme.swift | 2 +- .../ChatMessageAnimatedStickerItemNode.swift | 23 ++++++++++++++++ .../Sources/ChatMessageStickerItemNode.swift | 23 ++++++++++++++++ 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift b/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift index b0d5a129d8..90bf804777 100644 --- a/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift +++ b/submodules/ShimmerEffect/Sources/StickerShimmerEffectNode.swift @@ -140,6 +140,7 @@ private func decodeStickerThumbnailData(_ data: Data) -> String { } public class StickerShimmerEffectNode: ASDisplayNode { + private var backdropNode: ASDisplayNode? private let backgroundNode: ASDisplayNode private let effectNode: ShimmerEffectForegroundNode private let foregroundNode: ASImageNode @@ -164,10 +165,24 @@ public class StickerShimmerEffectNode: ASDisplayNode { self.addSubnode(self.foregroundNode) } + public override func didLoad() { + super.didLoad() + + self.effectNode.layer.compositingFilter = "screenBlendMode" + } + public var isEmpty: Bool { return self.currentData == nil } + public func addBackdropNode(_ backdropNode: ASDisplayNode) { + if let current = self.backdropNode { + current.removeFromSupernode() + } + self.backdropNode = backdropNode + self.insertSubnode(backdropNode, at: 0) + } + public func updateAbsoluteRect(_ rect: CGRect, within containerSize: CGSize) { self.effectNode.updateAbsoluteRect(rect, within: containerSize) } @@ -190,6 +205,7 @@ public class StickerShimmerEffectNode: ASDisplayNode { self.effectNode.update(backgroundColor: backgroundColor == nil ? .clear : foregroundColor, foregroundColor: shimmeringColor) + let bounds = CGRect(origin: CGPoint(), size: size) let image = generateImage(size, rotatedContext: { size, context in if let backgroundColor = backgroundColor { context.setFillColor(backgroundColor.cgColor) @@ -219,7 +235,7 @@ public class StickerShimmerEffectNode: ASDisplayNode { UIGraphicsPopContext() } }) - + if backgroundColor == nil { self.foregroundNode.image = nil @@ -228,7 +244,7 @@ public class StickerShimmerEffectNode: ASDisplayNode { maskView = current } else { maskView = UIImageView() - maskView.frame = CGRect(origin: CGPoint(), size: size) + maskView.frame = bounds self.maskView = maskView self.view.mask = maskView } @@ -244,9 +260,10 @@ public class StickerShimmerEffectNode: ASDisplayNode { self.maskView?.image = image - self.backgroundNode.frame = CGRect(origin: CGPoint(), size: size) - self.foregroundNode.frame = CGRect(origin: CGPoint(), size: size) - self.effectNode.frame = CGRect(origin: CGPoint(), size: size) + self.backdropNode?.frame = bounds + self.backgroundNode.frame = bounds + self.foregroundNode.frame = bounds + self.effectNode.frame = bounds } } diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index af4691d8d7..9c13c92a9a 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -565,7 +565,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio selectionControlColors: PresentationThemeFillStrokeForeground(fillColor: UIColor(rgb: 0x007ee5), strokeColor: UIColor(rgb: 0xc7c7cc), foregroundColor: UIColor(rgb: 0xffffff)), deliveryFailedColors: PresentationThemeFillForeground(fillColor: UIColor(rgb: 0xff3b30), foregroundColor: UIColor(rgb: 0xffffff)), mediaHighlightOverlayColor: UIColor(white: 1.0, alpha: 0.6), - stickerPlaceholderColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor.withAlphaComponent(0.3), withoutWallpaper: UIColor(rgb: 0x748391, alpha: 0.25)), + stickerPlaceholderColor: PresentationThemeVariableColor(withWallpaper: serviceBackgroundColor, withoutWallpaper: UIColor(rgb: 0x748391, alpha: 0.25)), stickerPlaceholderShimmerColor: PresentationThemeVariableColor(withWallpaper: UIColor(rgb: 0xffffff, alpha: 0.2), withoutWallpaper: UIColor(rgb: 0x000000, alpha: 0.1)) ) diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index aa3d2b9eeb..a91c6074ac 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -22,6 +22,7 @@ import ManagedAnimationNode import SlotMachineAnimationNode import UniversalMediaPlayer import ShimmerEffect +import WallpaperBackgroundNode private let nameFont = Font.medium(14.0) private let inlineBotPrefixFont = Font.regular(14.0) @@ -158,6 +159,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { private let containerNode: ContextControllerSourceNode let imageNode: TransformImageNode private var enableSynchronousImageApply: Bool = false + private var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? private(set) var placeholderNode: StickerShimmerEffectNode private(set) var animationNode: GenericAnimatedStickerNode? private var didSetUpAnimationNode = false @@ -592,6 +594,16 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { rect.origin.y = containerSize.height - rect.maxY + self.insets.top self.placeholderNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize) + + if let backgroundNode = self.backgroundNode { + backgroundNode.update(rect: CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize) + } + } + } + + override func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { + if let backgroundNode = self.backgroundNode { + backgroundNode.offset(value: value, animationCurve: animationCurve, duration: duration) } } @@ -1001,6 +1013,17 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } if let file = file, let immediateThumbnailData = file.immediateThumbnailData { + if strongSelf.backgroundNode == nil { + if let backgroundNode = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { + strongSelf.backgroundNode = backgroundNode + strongSelf.placeholderNode.addBackdropNode(backgroundNode) + + if let (rect, size) = strongSelf.absoluteRect { + strongSelf.updateAbsoluteRect(rect, within: size) + } + } + } + let foregroundColor = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderColor, wallpaper: item.presentationData.theme.wallpaper) let shimmeringColor = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderShimmerColor, wallpaper: item.presentationData.theme.wallpaper) strongSelf.placeholderNode.update(backgroundColor: nil, foregroundColor: foregroundColor, shimmeringColor: shimmeringColor, data: immediateThumbnailData, size: animationNodeFrame.size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0)) diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 8cdec7adf4..ee20d76928 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -13,6 +13,7 @@ import StickerResources import ContextUI import Markdown import ShimmerEffect +import WallpaperBackgroundNode private let nameFont = Font.medium(14.0) private let inlineBotPrefixFont = Font.regular(14.0) @@ -22,6 +23,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView { let contextSourceNode: ContextExtractedContentContainingNode private let containerNode: ContextControllerSourceNode let imageNode: TransformImageNode + private var backgroundNode: WallpaperBackgroundNode.BubbleBackgroundNode? private var placeholderNode: StickerShimmerEffectNode var textNode: TextNode? @@ -249,6 +251,16 @@ class ChatMessageStickerItemNode: ChatMessageItemView { rect.origin.y = containerSize.height - rect.maxY + self.insets.top self.placeholderNode.updateAbsoluteRect(CGRect(origin: CGPoint(x: rect.minX + placeholderNode.frame.minX, y: rect.minY + placeholderNode.frame.minY), size: placeholderNode.frame.size), within: containerSize) + + if let backgroundNode = self.backgroundNode { + backgroundNode.update(rect: CGRect(origin: CGPoint(x: rect.minX + self.placeholderNode.frame.minX, y: rect.minY + self.placeholderNode.frame.minY), size: self.placeholderNode.frame.size), within: containerSize) + } + } + } + + override func applyAbsoluteOffset(value: CGPoint, animationCurve: ContainedViewLayoutTransitionCurve, duration: Double) { + if let backgroundNode = self.backgroundNode { + backgroundNode.offset(value: value, animationCurve: animationCurve, duration: duration) } } @@ -644,6 +656,17 @@ class ChatMessageStickerItemNode: ChatMessageItemView { strongSelf.enableSynchronousImageApply = false if let immediateThumbnailData = telegramFile?.immediateThumbnailData { + if strongSelf.backgroundNode == nil { + if let backgroundNode = item.controllerInteraction.presentationContext.backgroundNode?.makeBubbleBackground(for: .free) { + strongSelf.backgroundNode = backgroundNode + strongSelf.placeholderNode.addBackdropNode(backgroundNode) + + if let (rect, size) = strongSelf.absoluteRect { + strongSelf.updateAbsoluteRect(rect, within: size) + } + } + } + let foregroundColor = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderColor, wallpaper: item.presentationData.theme.wallpaper) let shimmeringColor = bubbleVariableColor(variableColor: item.presentationData.theme.theme.chat.message.stickerPlaceholderShimmerColor, wallpaper: item.presentationData.theme.wallpaper) From 8d0f3b86ea4679c8a1c81406462dc95f566ca6b1 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 11 Jun 2021 03:22:13 +0300 Subject: [PATCH 3/3] Various Fixes --- submodules/ChatListUI/Sources/ChatListController.swift | 4 ++++ submodules/Display/Source/NavigationButtonNode.swift | 6 +++++- .../TelegramUI/Sources/ChatMessageActionButtonsNode.swift | 6 +++--- submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 04f07dcc1a..686101084e 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -365,6 +365,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController strongSelf.navigationItem.setLeftBarButton(editItem, animated: true) } } + } else { + let editItem = UIBarButtonItem(title: strongSelf.presentationData.strings.Common_Edit, style: .plain, target: self, action: #selector(strongSelf.editPressed)) + editItem.accessibilityLabel = strongSelf.presentationData.strings.Common_Edit + strongSelf.navigationItem.setRightBarButton(editItem, animated: true) } let (hasProxy, connectsViaProxy) = proxy diff --git a/submodules/Display/Source/NavigationButtonNode.swift b/submodules/Display/Source/NavigationButtonNode.swift index 1314fb8dc6..4ad1cd4318 100644 --- a/submodules/Display/Source/NavigationButtonNode.swift +++ b/submodules/Display/Source/NavigationButtonNode.swift @@ -266,7 +266,11 @@ private final class NavigationButtonItemNode: ImmediateTextNode { let previousTouchCount = self.touchCount self.touchCount = max(0, self.touchCount - touches.count) - if previousTouchCount != 0 && self.touchCount == 0 && self.isEnabled { + var touchInside = true + if let touch = touches.first { + touchInside = self.touchInsideApparentBounds(touch) + } + if previousTouchCount != 0 && self.touchCount == 0 && self.isEnabled && touchInside { self.pressed() } } diff --git a/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift index 4886e18d4e..5baa9875ac 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionButtonsNode.swift @@ -100,11 +100,11 @@ private final class ChatMessageActionButtonNode: ASDisplayNode { case .url, .urlAuth: iconImage = incoming ? graphics.chatBubbleActionButtonIncomingLinkIconImage : graphics.chatBubbleActionButtonOutgoingLinkIconImage case .requestPhone: - iconImage = incoming ? graphics.chatBubbleActionButtonIncomingPhoneIconImage : graphics.chatBubbleActionButtonOutgoingLinkIconImage + iconImage = incoming ? graphics.chatBubbleActionButtonIncomingPhoneIconImage : graphics.chatBubbleActionButtonOutgoingPhoneIconImage case .requestMap: - iconImage = incoming ? graphics.chatBubbleActionButtonIncomingLocationIconImage : graphics.chatBubbleActionButtonOutgoingLinkIconImage + iconImage = incoming ? graphics.chatBubbleActionButtonIncomingLocationIconImage : graphics.chatBubbleActionButtonOutgoingLocationIconImage case .switchInline: - iconImage = incoming ? graphics.chatBubbleActionButtonIncomingShareIconImage : graphics.chatBubbleActionButtonOutgoingLinkIconImage + iconImage = incoming ? graphics.chatBubbleActionButtonIncomingShareIconImage : graphics.chatBubbleActionButtonOutgoingShareIconImage case .payment: iconImage = incoming ? graphics.chatBubbleActionButtonIncomingPaymentIconImage : graphics.chatBubbleActionButtonOutgoingPaymentIconImage default: diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 4a30c8f9aa..c69a12f77c 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1221,7 +1221,7 @@ private func editingItems(data: PeerInfoScreenData?, context: AccountContext, pr })) } - if channel.flags.contains(.isCreator) || (channel.adminRights != nil && channel.hasPermission(.pinMessages)) { + if channel.flags.contains(.isCreator) || (channel.adminRights != nil && channel.hasPermission(.sendMessages)) { let messagesShouldHaveSignatures: Bool switch channel.info { case let .broadcast(info):