From 383ab9e479e25f45df4e0defffb57d628dec423a Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 7 Mar 2025 17:52:50 +0100 Subject: [PATCH] Various improvements --- .../Resources/notifications/0.m4a | Bin 31724 -> 89149 bytes .../Sources/DirectAnimatedStickerNode.swift | 2 +- .../Sources/VideoStickerFrameSource.swift | 133 +++++++++------- .../Sources/AvatarVideoNode.swift | 150 +++++++++++++----- .../Sources/Node/ChatListItem.swift | 6 +- .../ChatSendMessageContextScreen.swift | 4 +- .../Sources/MessageItemView.swift | 2 +- .../NavigationTransitionCoordinator.swift | 4 + .../Sources/FFMpegFileReader.swift | 20 ++- .../Sources/PhotoResources.swift | 6 +- .../Sources/ReactionContextNode.swift | 12 +- .../TelegramCore/Sources/ForumChannels.swift | 2 +- .../State/AvailableMessageEffects.swift | 87 +++++----- .../SyncCore/SyncCore_InstantPage.swift | 2 +- .../SyncCore_StickerPackCollectionInfo.swift | 2 +- .../SyncCore/SyncCore_TelegramChannel.swift | 2 +- .../SyncCore/SyncCore_TelegramGroup.swift | 2 +- .../SyncCore/SyncCore_TelegramMediaFile.swift | 10 +- ...ore_TelegramPeerNotificationSettings.swift | 15 +- .../SyncCore/SyncCore_TelegramUser.swift | 2 +- .../Sources/Utils/MessageUtils.swift | 19 +++ .../PeerNotificationSoundStrings.swift | 13 +- .../ChatMessageDateAndStatusNode.swift | 2 +- .../ChatMessageInteractiveMediaNode.swift | 3 +- .../Sources/ChatMessageItemView.swift | 4 +- .../Sources/TopMessageReactions.swift | 2 +- .../Sources/EmojiTextAttachmentView.swift | 16 +- .../Sources/EmojiKeyboardItemLayer.swift | 2 +- .../Sources/EmojiPagerContentComponent.swift | 14 +- .../Sources/EmojiPagerContentSignals.swift | 30 ++-- .../Sources/PremiumBadgeView.swift | 2 +- .../Sources/VideoAnimationCache.swift | 4 +- .../ChatTextInputActionButtonsNode.swift | 2 +- 33 files changed, 373 insertions(+), 203 deletions(-) diff --git a/Telegram/Telegram-iOS/Resources/notifications/0.m4a b/Telegram/Telegram-iOS/Resources/notifications/0.m4a index e3f9bdcb2ab57322b4f8f1ca46d8e2ae8065ba95..f8026837be460f80fb5779d088a153424f7f189f 100644 GIT binary patch literal 89149 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

Y9h$-+U(sg0#KYFl+`Z$r{CZI^0+Nopsmtk9M~@ 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 I|Ci-|003U+zW@LL literal 31724 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 A3;+NC diff --git a/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift b/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift index 49eac5f5b5..eea15a90c1 100644 --- a/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift +++ b/submodules/AnimatedStickerNode/Sources/DirectAnimatedStickerNode.swift @@ -112,7 +112,7 @@ public final class DirectAnimatedStickerNode: ASDisplayNode, AnimatedStickerNode } if source.isVideo { - if let videoSource = makeVideoStickerDirectFrameSource(queue: DirectAnimatedStickerNode.sharedQueue, path: path, width: width, height: height, cachePathPrefix: nil, unpremultiplyAlpha: false) { + if let videoSource = makeVideoStickerDirectFrameSource(queue: DirectAnimatedStickerNode.sharedQueue, path: path, hintVP9: true, width: width, height: height, cachePathPrefix: nil, unpremultiplyAlpha: false) { strongSelf.setupPlayback(videoSource: videoSource) } } else { diff --git a/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift b/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift index fba3e52733..120ad0e2e9 100644 --- a/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift +++ b/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift @@ -273,8 +273,8 @@ private final class VideoStickerFrameSourceCache { private let useCache = true -public func makeVideoStickerDirectFrameSource(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool) -> AnimatedStickerFrameSource? { - return VideoStickerDirectFrameSource(queue: queue, path: path, width: width, height: height, cachePathPrefix: cachePathPrefix, unpremultiplyAlpha: unpremultiplyAlpha) +public func makeVideoStickerDirectFrameSource(queue: Queue, path: String, hintVP9: Bool, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool) -> AnimatedStickerFrameSource? { + return VideoStickerDirectFrameSource(queue: queue, path: path, isVP9: hintVP9, width: width, height: height, cachePathPrefix: cachePathPrefix, unpremultiplyAlpha: unpremultiplyAlpha) } public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { @@ -290,7 +290,7 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { public var duration: Double fileprivate var currentFrame: Int - private let source: SoftwareVideoSource? + private var source: FFMpegFileReader? public var frameIndex: Int { if self.frameCount == 0 { @@ -300,7 +300,7 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { } } - public init?(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool = true) { + public init?(queue: Queue, path: String, isVP9: Bool = true, width: Int, height: Int, cachePathPrefix: String?, unpremultiplyAlpha: Bool = true) { self.queue = queue self.path = path self.width = width @@ -329,12 +329,25 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { self.frameCount = 1 self.duration = 0.0 } else { - let source = SoftwareVideoSource(path: path, hintVP9: true, unpremultiplyAlpha: unpremultiplyAlpha) - self.source = source + let source = FFMpegFileReader( + source: .file(path), + passthroughDecoder: false, + useHardwareAcceleration: false, + selectedStream: .mediaType(.video), + seek: nil, + maxReadablePts: nil + ) + if let source { + self.source = source + self.frameRate = min(30, source.frameRate()) + self.duration = source.duration().seconds + } else { + self.source = nil + self.frameRate = 30 + self.duration = 0.0 + } self.image = nil - self.frameRate = min(30, source.getFramerate()) self.frameCount = 0 - self.duration = source.reportedDuration.seconds } } @@ -365,56 +378,66 @@ public final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { } else if useCache, let cache = self.cache, let yuvData = cache.readUncompressedYuvaFrame(index: frameIndex) { return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.width * 2, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount) } else if let source = self.source { - let frameAndLoop = source.readFrame(maxPts: nil) - if frameAndLoop.0 == nil { - if frameAndLoop.3 { - if self.frameCount == 0 { - if let cache = self.cache { - if cache.storedFrames == frameIndex { - self.frameCount = frameIndex - cache.storeFrameRateAndCount(frameRate: self.frameRate, frameCount: self.frameCount) - } else { - Logger.shared.log("VideoSticker", "Missed a frame? \(frameIndex) \(cache.storedFrames)") - } - } else { - self.frameCount = frameIndex - } + let frameAndLoop = source.readFrame(argb: true) + switch frameAndLoop { + case let .frame(frame): + var frameData = Data(count: self.bytesPerRow * self.height) + frameData.withUnsafeMutableBytes { buffer -> Void in + guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { + return } - self.currentFrame = 0 - } else { - Logger.shared.log("VideoSticker", "Skipped a frame?") + + let imageBuffer = CMSampleBufferGetImageBuffer(frame.sampleBuffer) + CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0)) + let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!) + let width = CVPixelBufferGetWidth(imageBuffer!) + let height = CVPixelBufferGetHeight(imageBuffer!) + let srcData = CVPixelBufferGetBaseAddress(imageBuffer!) + + var sourceBuffer = vImage_Buffer(data: srcData, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow) + var destBuffer = vImage_Buffer(data: bytes, height: vImagePixelCount(self.height), width: vImagePixelCount(self.width), rowBytes: self.bytesPerRow) + + let _ = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, vImage_Flags(kvImageDoNotTile)) + + CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0)) } - return nil - } - - guard let frame = frameAndLoop.0 else { - return nil - } - - var frameData = Data(count: self.bytesPerRow * self.height) - frameData.withUnsafeMutableBytes { buffer -> Void in - guard let bytes = buffer.baseAddress?.assumingMemoryBound(to: UInt8.self) else { - return - } - - let imageBuffer = CMSampleBufferGetImageBuffer(frame.sampleBuffer) - CVPixelBufferLockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0)) - let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer!) - let width = CVPixelBufferGetWidth(imageBuffer!) - let height = CVPixelBufferGetHeight(imageBuffer!) - let srcData = CVPixelBufferGetBaseAddress(imageBuffer!) - - var sourceBuffer = vImage_Buffer(data: srcData, height: vImagePixelCount(height), width: vImagePixelCount(width), rowBytes: bytesPerRow) - var destBuffer = vImage_Buffer(data: bytes, height: vImagePixelCount(self.height), width: vImagePixelCount(self.width), rowBytes: self.bytesPerRow) - - let _ = vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, vImage_Flags(kvImageDoNotTile)) - - CVPixelBufferUnlockBaseAddress(imageBuffer!, CVPixelBufferLockFlags(rawValue: 0)) - } - self.cache?.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData) - - return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount, multiplyAlpha: true) + self.cache?.storeUncompressedRgbFrame(index: frameIndex, rgbData: frameData) + + return AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount, multiplyAlpha: true) + case .endOfStream: + if self.frameCount == 0 { + if let cache = self.cache { + if cache.storedFrames == frameIndex { + self.frameCount = frameIndex + cache.storeFrameRateAndCount(frameRate: self.frameRate, frameCount: self.frameCount) + } else { + Logger.shared.log("VideoSticker", "Missed a frame? \(frameIndex) \(cache.storedFrames)") + } + } else { + self.frameCount = frameIndex + } + } + self.currentFrame = 0 + self.source = FFMpegFileReader( + source: .file(self.path), + passthroughDecoder: false, + useHardwareAcceleration: false, + selectedStream: .mediaType(.video), + seek: nil, + maxReadablePts: nil + ) + + if let cache = self.cache { + if let yuvData = cache.readUncompressedYuvaFrame(index: self.currentFrame) { + return AnimatedStickerFrame(data: yuvData, type: .yuva, width: self.width, height: self.height, bytesPerRow: self.width * 2, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount) + } + } + + return nil + case .waitingForMoreData, .error: + return nil + } } else { return nil } diff --git a/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift b/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift index 9cdfac6a64..bb787e1836 100644 --- a/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift +++ b/submodules/AvatarVideoNode/Sources/AvatarVideoNode.swift @@ -25,6 +25,7 @@ public final class AvatarVideoNode: ASDisplayNode { private var emojiMarkup: TelegramMediaImage.EmojiMarkup? + private var videoFileDisposable: Disposable? private var fileDisposable = MetaDisposable() private var animationFile: TelegramMediaFile? private var itemLayer: EmojiKeyboardItemLayer? @@ -32,6 +33,7 @@ public final class AvatarVideoNode: ASDisplayNode { private var animationNode: AnimatedStickerNode? private let stickerFetchedDisposable = MetaDisposable() + private var videoItemLayer: EmojiKeyboardItemLayer? private var videoNode: UniversalVideoNode? private var videoContent: NativeVideoContent? private let playbackStartDisposable = MetaDisposable() @@ -55,6 +57,7 @@ public final class AvatarVideoNode: ASDisplayNode { } deinit { + self.videoFileDisposable?.dispose() self.fileDisposable.dispose() self.stickerFetchedDisposable.dispose() self.playbackStartDisposable.dispose() @@ -137,6 +140,7 @@ public final class AvatarVideoNode: ASDisplayNode { self.videoLoopCount += 1 if self.videoLoopCount >= maxVideoLoopCount { self.itemLayer?.isVisibleForAnimations = false + self.videoItemLayer?.isVisibleForAnimations = false } } } @@ -211,6 +215,9 @@ public final class AvatarVideoNode: ASDisplayNode { if videoContent.id != self.videoContent?.id { self.videoNode?.removeFromSupernode() self.videoContent = videoContent + + self.videoFileDisposable?.dispose() + self.videoFileDisposable = fetchedMediaResource(mediaBox: self.context.account.postbox.mediaBox, userLocation: .peer(peer.id), userContentType: .avatar, reference: videoFileReference.resourceReference(videoFileReference.media.resource)).startStrict() } } } @@ -231,56 +238,111 @@ public final class AvatarVideoNode: ASDisplayNode { } self.animationNode?.visibility = isVisible if isVisible, let videoContent = self.videoContent, self.videoLoopCount < maxVideoLoopCount { - if self.videoNode == nil { - let context = self.context - let mediaManager = context.sharedContext.mediaManager - let videoNode = UniversalVideoNode(context: context, postbox: context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: VideoDecoration(), content: videoContent, priority: .embedded) - videoNode.clipsToBounds = true - videoNode.isUserInteractionEnabled = false - videoNode.isHidden = true - videoNode.playbackCompleted = { [weak self] in - if let strongSelf = self { - strongSelf.videoLoopCount += 1 - if strongSelf.videoLoopCount >= maxVideoLoopCount { - if let videoNode = strongSelf.videoNode { - strongSelf.videoNode = nil - videoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak videoNode] _ in - videoNode?.removeFromSupernode() - }) + var useDirectCache = false + if self.internalSize.width <= 200.0 { + useDirectCache = true + } + + if useDirectCache { + if self.videoItemLayer == nil { + let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(videoContent.fileReference.media)) + let videoItemLayer = EmojiKeyboardItemLayer( + item: EmojiPagerContentComponent.Item( + animationData: animationData, + content: .animation(animationData), + itemFile: TelegramMediaFile.Accessor(videoContent.fileReference.media), + subgroupId: nil, + icon: .none, + tintMode: .none + ), + context: self.context, + attemptSynchronousLoad: false, + content: .animation(animationData), + cache: self.context.animationCache, + renderer: self.context.animationRenderer, + placeholderColor: .clear, + blurredBadgeColor: .clear, + accentIconColor: .white, + pointSize: self.internalSize, + onUpdateDisplayPlaceholder: { _, _ in + } + ) + videoItemLayer.onLoop = { [weak self] in + if let self { + self.videoLoopCount += 1 + if self.videoLoopCount >= maxVideoLoopCount { + self.itemLayer?.isVisibleForAnimations = false } } } + + self.videoItemLayer = videoItemLayer + self.layer.addSublayer(videoItemLayer) } - - if let _ = videoContent.startTimestamp { - self.playbackStartDisposable.set((videoNode.status - |> map { status -> Bool in - if let status = status, case .playing = status.status { - return true - } else { - return false - } - } - |> filter { playing in - return playing - } - |> take(1) - |> deliverOnMainQueue).startStrict(completed: { [weak self] in + } else { + if let videoItemLayer = self.videoItemLayer { + self.videoItemLayer = nil + videoItemLayer.removeFromSuperlayer() + } + } + + if useDirectCache { + if let videoNode = self.videoNode { + self.videoNode = nil + videoNode.removeFromSupernode() + } + } else { + if self.videoNode == nil { + let context = self.context + let mediaManager = context.sharedContext.mediaManager + let videoNode = UniversalVideoNode(context: context, postbox: context.account.postbox, audioSession: mediaManager.audioSession, manager: mediaManager.universalVideoManager, decoration: VideoDecoration(), content: videoContent, priority: .embedded) + videoNode.clipsToBounds = true + videoNode.isUserInteractionEnabled = false + videoNode.isHidden = true + videoNode.playbackCompleted = { [weak self] in if let strongSelf = self { - Queue.mainQueue().after(0.15) { - strongSelf.videoNode?.isHidden = false + strongSelf.videoLoopCount += 1 + if strongSelf.videoLoopCount >= maxVideoLoopCount { + if let videoNode = strongSelf.videoNode { + strongSelf.videoNode = nil + videoNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak videoNode] _ in + videoNode?.removeFromSupernode() + }) + } } } - })) - } else { - self.playbackStartDisposable.set(nil) - videoNode.isHidden = false + } + + if let _ = videoContent.startTimestamp { + self.playbackStartDisposable.set((videoNode.status + |> map { status -> Bool in + if let status = status, case .playing = status.status { + return true + } else { + return false + } + } + |> filter { playing in + return playing + } + |> take(1) + |> deliverOnMainQueue).startStrict(completed: { [weak self] in + if let strongSelf = self { + Queue.mainQueue().after(0.15) { + strongSelf.videoNode?.isHidden = false + } + } + })) + } else { + self.playbackStartDisposable.set(nil) + videoNode.isHidden = false + } + videoNode.canAttachContent = true + videoNode.play() + + self.addSubnode(videoNode) + self.videoNode = videoNode } - videoNode.canAttachContent = true - videoNode.play() - - self.addSubnode(videoNode) - self.videoNode = videoNode } } else if let videoNode = self.videoNode { self.videoNode = nil @@ -289,6 +351,7 @@ public final class AvatarVideoNode: ASDisplayNode { if self.videoLoopCount < maxVideoLoopCount { self.itemLayer?.isVisibleForAnimations = isVisible } + self.videoItemLayer?.isVisibleForAnimations = isVisible } public func updateLayout(size: CGSize, cornerRadius: CGFloat, transition: ContainedViewLayoutTransition) { @@ -301,6 +364,9 @@ public final class AvatarVideoNode: ASDisplayNode { videoNode.frame = CGRect(origin: .zero, size: size) videoNode.updateLayout(size: size, transition: transition) } + if let videoItemLayer = self.videoItemLayer { + videoItemLayer.frame = CGRect(origin: .zero, size: size) + } let itemSize = CGSize(width: size.width * 0.67, height: size.height * 0.67) let itemFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - itemSize.width) / 2.0), y: floorToScreenPixels((size.height - itemSize.height) / 2.0)), size: itemSize) diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 3c2c57a158..86d3f3b783 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -1747,7 +1747,11 @@ public class ChatListItemNode: ItemListRevealOptionsItemNode { self.avatarNode.font = avatarPlaceholderFont(size: avatarFontSize) } } - self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, clipStyle: isForumAvatar ? .roundedRect : .round, synchronousLoad: synchronousLoads, displayDimensions: CGSize(width: 60.0, height: 60.0)) + if peer.smallProfileImage != nil && overrideImage == nil { + self.avatarNode.setPeerV2(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, clipStyle: isForumAvatar ? .roundedRect : .round, synchronousLoad: synchronousLoads, displayDimensions: CGSize(width: 60.0, height: 60.0)) + } else { + self.avatarNode.setPeer(context: item.context, theme: item.presentationData.theme, peer: peer, overrideImage: overrideImage, emptyColor: item.presentationData.theme.list.mediaPlaceholderColor, clipStyle: isForumAvatar ? .roundedRect : .round, synchronousLoad: synchronousLoads, displayDimensions: CGSize(width: 60.0, height: 60.0)) + } if peer.isPremium && peer.id != item.context.account.peerId { let context = item.context diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift index 93e5152744..f329936da6 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift @@ -954,10 +954,10 @@ final class ChatSendMessageContextScreenComponent: Component { } var customEffectResource: (FileMediaReference, MediaResource)? - if let effectAnimation = messageEffect.effectAnimation { + if let effectAnimation = messageEffect.effectAnimation?._parse() { customEffectResource = (FileMediaReference.standalone(media: effectAnimation), effectAnimation.resource) } else { - let effectSticker = messageEffect.effectSticker + let effectSticker = messageEffect.effectSticker._parse() if let effectFile = effectSticker.videoThumbnails.first { customEffectResource = (FileMediaReference.standalone(media: effectSticker), effectFile.resource) } diff --git a/submodules/ChatSendMessageActionUI/Sources/MessageItemView.swift b/submodules/ChatSendMessageActionUI/Sources/MessageItemView.swift index 3fddcea629..0dee40ddfd 100644 --- a/submodules/ChatSendMessageActionUI/Sources/MessageItemView.swift +++ b/submodules/ChatSendMessageActionUI/Sources/MessageItemView.swift @@ -309,7 +309,7 @@ final class MessageItemView: UIView { } let effectIconContent: ChatSendMessageScreenEffectIcon.Content if let staticIcon = effect.staticIcon { - effectIconContent = .file(staticIcon) + effectIconContent = .file(staticIcon._parse()) } else { effectIconContent = .text(effect.emoticon) } diff --git a/submodules/Display/Source/NavigationTransitionCoordinator.swift b/submodules/Display/Source/NavigationTransitionCoordinator.swift index 89152cc22b..3643832216 100644 --- a/submodules/Display/Source/NavigationTransitionCoordinator.swift +++ b/submodules/Display/Source/NavigationTransitionCoordinator.swift @@ -52,6 +52,8 @@ final class NavigationTransitionCoordinator { private var currentCompletion: (() -> Void)? private var didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? + private var frameRateLink: SharedDisplayLinkDriver.Link? + init(transition: NavigationTransition, isInteractive: Bool, isFlat: Bool, container: NavigationContainer, topNode: ASDisplayNode, topNavigationBar: NavigationBar?, bottomNode: ASDisplayNode, bottomNavigationBar: NavigationBar?, didUpdateProgress: ((CGFloat, ContainedViewLayoutTransition, CGRect, CGRect) -> Void)? = nil) { self.transition = transition self.isInteractive = isInteractive @@ -114,6 +116,8 @@ final class NavigationTransitionCoordinator { self.maybeCreateNavigationBarTransition() self.updateProgress(0.0, transition: .immediate, completion: {}) + + self.frameRateLink = SharedDisplayLinkDriver.shared.add(framesPerSecond: .max, { _ in }) } required init(coder aDecoder: NSCoder) { diff --git a/submodules/MediaPlayer/Sources/FFMpegFileReader.swift b/submodules/MediaPlayer/Sources/FFMpegFileReader.swift index 7bb1b7d2d6..804279808b 100644 --- a/submodules/MediaPlayer/Sources/FFMpegFileReader.swift +++ b/submodules/MediaPlayer/Sources/FFMpegFileReader.swift @@ -403,6 +403,22 @@ public final class FFMpegFileReader { deinit { } + public func frameRate() -> Int { + if let stream = self.stream { + return Int(stream.info.fps.seconds) + } else { + return 0 + } + } + + public func duration() -> CMTime { + if let stream = self.stream { + return stream.info.duration + } else { + return .zero + } + } + private func readPacketInternal() -> FFMpegPacket? { guard let avFormatContext = self.avFormatContext else { return nil @@ -452,7 +468,7 @@ public final class FFMpegFileReader { return nil } - public func readFrame() -> ReadFrameResult { + public func readFrame(argb: Bool = false) -> ReadFrameResult { guard let stream = self.stream else { return .error } @@ -461,7 +477,7 @@ public final class FFMpegFileReader { var result: MediaTrackFrame? switch stream.decoder { case let .video(decoder): - result = decoder.decode(ptsOffset: nil, forceARGB: false, unpremultiplyAlpha: false, displayImmediately: false) + result = decoder.decode(ptsOffset: nil, forceARGB: argb, unpremultiplyAlpha: false, displayImmediately: false) case let .videoPassthrough(decoder): result = decoder.decode() case let .audio(decoder): diff --git a/submodules/PhotoResources/Sources/PhotoResources.swift b/submodules/PhotoResources/Sources/PhotoResources.swift index 46a8a8e5a8..b6c3d06e48 100644 --- a/submodules/PhotoResources/Sources/PhotoResources.swift +++ b/submodules/PhotoResources/Sources/PhotoResources.swift @@ -448,7 +448,7 @@ private func chatMessageImageFileThumbnailDatas(account: Account, userLocation: return signal } -private func chatMessageVideoDatas(postbox: Postbox, userLocation: MediaResourceUserLocation, customUserContentType: MediaResourceUserContentType? = nil, fileReference: FileMediaReference, previewSourceFileReference: FileMediaReference?, thumbnailSize: Bool = false, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, forceThumbnail: Bool = false) -> Signal?, Bool>, NoError> { +private func chatMessageVideoDatas(postbox: Postbox, userLocation: MediaResourceUserLocation, customUserContentType: MediaResourceUserContentType? = nil, fileReference: FileMediaReference, previewSourceFileReference: FileMediaReference?, alternativeFileAndRange: Signal<(TelegramMediaFile, Range), NoError>? = nil, thumbnailSize: Bool = false, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, forceThumbnail: Bool = false) -> Signal?, Bool>, NoError> { let fullSizeResource = fileReference.media.resource var reducedSizeResource: MediaResource? if let videoThumbnail = fileReference.media.videoThumbnails.first { @@ -1627,7 +1627,7 @@ public func mediaGridMessageVideo(postbox: Postbox, userLocation: MediaResourceU } } -public func internalMediaGridMessageVideo(postbox: Postbox, userLocation: MediaResourceUserLocation, customUserContentType: MediaResourceUserContentType? = nil, videoReference: FileMediaReference, previewSourceFileReference: FileMediaReference? = nil, imageReference: ImageMediaReference? = nil, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false, blurred: Bool = false) -> Signal<(() -> CGSize?, (TransformImageArguments) -> DrawingContext?), NoError> { +public func internalMediaGridMessageVideo(postbox: Postbox, userLocation: MediaResourceUserLocation, customUserContentType: MediaResourceUserContentType? = nil, videoReference: FileMediaReference, previewSourceFileReference: FileMediaReference? = nil, imageReference: ImageMediaReference? = nil, alternativeFileAndRange: Signal<(TelegramMediaFile, Range), NoError>? = nil, onlyFullSize: Bool = false, useLargeThumbnail: Bool = false, synchronousLoad: Bool = false, autoFetchFullSizeThumbnail: Bool = false, overlayColor: UIColor? = nil, nilForEmptyResult: Bool = false, useMiniThumbnailIfAvailable: Bool = false, blurred: Bool = false) -> Signal<(() -> CGSize?, (TransformImageArguments) -> DrawingContext?), NoError> { let signal: Signal?, Bool>, NoError> if let imageReference = imageReference { signal = chatMessagePhotoDatas(postbox: postbox, userLocation: userLocation, customUserContentType: customUserContentType, photoReference: imageReference, tryAdditionalRepresentations: true, synchronousLoad: synchronousLoad, forceThumbnail: blurred) @@ -1638,7 +1638,7 @@ public func internalMediaGridMessageVideo(postbox: Postbox, userLocation: MediaR return Tuple(thumbnailData, fullSizeData.flatMap({ Tuple($0, "") }), fullSizeComplete) } } else { - signal = chatMessageVideoDatas(postbox: postbox, userLocation: userLocation, customUserContentType: customUserContentType, fileReference: videoReference, previewSourceFileReference: previewSourceFileReference, onlyFullSize: onlyFullSize, useLargeThumbnail: useLargeThumbnail, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail, forceThumbnail: blurred) + signal = chatMessageVideoDatas(postbox: postbox, userLocation: userLocation, customUserContentType: customUserContentType, fileReference: videoReference, previewSourceFileReference: previewSourceFileReference, alternativeFileAndRange: alternativeFileAndRange, onlyFullSize: onlyFullSize, useLargeThumbnail: useLargeThumbnail, synchronousLoad: synchronousLoad, autoFetchFullSizeThumbnail: autoFetchFullSizeThumbnail, forceThumbnail: blurred) } return signal diff --git a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift index bc4608d87b..e04b1c2a89 100644 --- a/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift +++ b/submodules/ReactionSelectionNode/Sources/ReactionContextNode.swift @@ -1893,7 +1893,7 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { for i in 0 ..< 2 { let groupId = i == 0 ? "reactions" : "stickers" for item in i == 0 ? reactionEffects : stickerEffects { - let itemFile: TelegramMediaFile = item.effectSticker + let itemFile = item.effectSticker var tintMode: EmojiPagerContentComponent.Item.TintMode = .none if itemFile.isCustomTemplateEmoji { @@ -1917,11 +1917,11 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { } } - let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile), partialReference: .none) + let animationData = EntityKeyboardAnimationData(file: itemFile, partialReference: .none) let resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: TelegramMediaFile.Accessor(itemFile), + itemFile: itemFile, subgroupId: nil, icon: icon, tintMode: tintMode @@ -2257,7 +2257,7 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { for i in 0 ..< 2 { let groupId = i == 0 ? "reactions" : "stickers" for item in i == 0 ? reactionEffects : stickerEffects { - let itemFile: TelegramMediaFile = item.effectSticker + let itemFile = item.effectSticker var tintMode: EmojiPagerContentComponent.Item.TintMode = .none if itemFile.isCustomTemplateEmoji { @@ -2281,11 +2281,11 @@ public final class ReactionContextNode: ASDisplayNode, ASScrollViewDelegate { } } - let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile), partialReference: .none) + let animationData = EntityKeyboardAnimationData(file: itemFile, partialReference: .none) let resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: TelegramMediaFile.Accessor(itemFile), + itemFile: itemFile, subgroupId: nil, icon: icon, tintMode: tintMode diff --git a/submodules/TelegramCore/Sources/ForumChannels.swift b/submodules/TelegramCore/Sources/ForumChannels.swift index 52ba6b348c..8b8a9fccce 100644 --- a/submodules/TelegramCore/Sources/ForumChannels.swift +++ b/submodules/TelegramCore/Sources/ForumChannels.swift @@ -976,7 +976,7 @@ func applyLoadMessageHistoryThreadsResults(accountPeerId: PeerId, transaction: T transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenReaction, namespace: Namespaces.Message.Cloud, customTag: nil, count: item.unreadReactionsCount, maxId: item.topMessage) if item.topMessage != 0 { - transaction.removeHole(peerId: result.peerId, threadId: item.threadId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: item.topMessage ... (Int32.max - 1)) + //transaction.removeHole(peerId: result.peerId, threadId: item.threadId, namespace: Namespaces.Message.Cloud, space: .everywhere, range: item.topMessage ... (Int32.max - 1)) } for message in result.messages { diff --git a/submodules/TelegramCore/Sources/State/AvailableMessageEffects.swift b/submodules/TelegramCore/Sources/State/AvailableMessageEffects.swift index 8070509f5e..f5bf7e5baa 100644 --- a/submodules/TelegramCore/Sources/State/AvailableMessageEffects.swift +++ b/submodules/TelegramCore/Sources/State/AvailableMessageEffects.swift @@ -2,6 +2,8 @@ import Foundation import TelegramApi import Postbox import SwiftSignalKit +import FlatBuffers +import FlatSerialization public final class AvailableMessageEffects: Equatable, Codable { public final class MessageEffect: Equatable, Codable { @@ -10,24 +12,27 @@ public final class AvailableMessageEffects: Equatable, Codable { case isPremium case emoticon case staticIcon + case staticIconData = "sid" case effectSticker + case effectStickerData = "esd" case effectAnimation + case effectAnimationData = "ead" } public let id: Int64 public let isPremium: Bool public let emoticon: String - public let staticIcon: TelegramMediaFile? - public let effectSticker: TelegramMediaFile - public let effectAnimation: TelegramMediaFile? + public let staticIcon: TelegramMediaFile.Accessor? + public let effectSticker: TelegramMediaFile.Accessor + public let effectAnimation: TelegramMediaFile.Accessor? public init( id: Int64, isPremium: Bool, emoticon: String, - staticIcon: TelegramMediaFile?, - effectSticker: TelegramMediaFile, - effectAnimation: TelegramMediaFile? + staticIcon: TelegramMediaFile.Accessor?, + effectSticker: TelegramMediaFile.Accessor, + effectAnimation: TelegramMediaFile.Accessor? ) { self.id = id self.isPremium = isPremium @@ -66,19 +71,28 @@ public final class AvailableMessageEffects: Equatable, Codable { self.isPremium = try container.decodeIfPresent(Bool.self, forKey: .isPremium) ?? false self.emoticon = try container.decode(String.self, forKey: .emoticon) - if let staticIconData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .staticIcon) { - self.staticIcon = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: staticIconData.data))) + if let staticIconData = try container.decodeIfPresent(Data.self, forKey: .staticIconData) { + var byteBuffer = ByteBuffer(data: staticIconData) + self.staticIcon = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, staticIconData) + } else if let staticIconData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .staticIcon) { + self.staticIcon = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: staticIconData.data)))) } else { self.staticIcon = nil } - do { + if let effectStickerData = try container.decodeIfPresent(Data.self, forKey: .effectStickerData) { + var byteBuffer = ByteBuffer(data: effectStickerData) + self.effectSticker = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, effectStickerData) + } else { let effectStickerData = try container.decode(AdaptedPostboxDecoder.RawObjectData.self, forKey: .effectSticker) - self.effectSticker = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectStickerData.data))) + self.effectSticker = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectStickerData.data)))) } - if let effectAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .effectAnimation) { - self.effectAnimation = TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectAnimationData.data))) + if let effectAnimationData = try container.decodeIfPresent(Data.self, forKey: .effectAnimationData) { + var byteBuffer = ByteBuffer(data: effectAnimationData) + self.effectAnimation = TelegramMediaFile.Accessor(FlatBuffers_getRoot(byteBuffer: &byteBuffer) as TelegramCore_TelegramMediaFile, effectAnimationData) + } else if let effectAnimationData = try container.decodeIfPresent(AdaptedPostboxDecoder.RawObjectData.self, forKey: .effectAnimation) { + self.effectAnimation = TelegramMediaFile.Accessor(TelegramMediaFile(decoder: PostboxDecoder(buffer: MemoryBuffer(data: effectAnimationData.data)))) } else { self.effectAnimation = nil } @@ -91,12 +105,26 @@ public final class AvailableMessageEffects: Equatable, Codable { try container.encode(self.emoticon, forKey: .emoticon) try container.encode(self.isPremium, forKey: .isPremium) - if let staticIcon = self.staticIcon { - try container.encode(PostboxEncoder().encodeObjectToRawData(staticIcon), forKey: .staticIcon) + let encodeFileItem: (TelegramMediaFile.Accessor, CodingKeys) throws -> Void = { file, key in + if let serializedFile = file._wrappedData { + try container.encode(serializedFile, forKey: key) + } else if let file = file._wrappedFile { + var builder = FlatBufferBuilder(initialSize: 1024) + let value = file.encodeToFlatBuffers(builder: &builder) + builder.finish(offset: value) + let serializedFile = builder.data + try container.encode(serializedFile, forKey: key) + } else { + preconditionFailure() + } } - try container.encode(PostboxEncoder().encodeObjectToRawData(self.effectSticker), forKey: .effectSticker) + + if let staticIcon = self.staticIcon { + try encodeFileItem(staticIcon, .staticIconData) + } + try encodeFileItem(self.effectSticker, .effectStickerData) if let effectAnimation = self.effectAnimation { - try container.encode(PostboxEncoder().encodeObjectToRawData(effectAnimation), forKey: .effectAnimation) + try encodeFileItem(effectAnimation, .effectAnimationData) } } } @@ -142,8 +170,6 @@ public final class AvailableMessageEffects: Equatable, Codable { } } -//availableEffect flags:# premium_required:flags.2?true id:long emoticon:string static_icon_id:flags.0?long effect_sticker_id:long effect_animation_id:flags.1?long = AvailableEffect; - private extension AvailableMessageEffects.MessageEffect { convenience init?(apiMessageEffect: Api.AvailableEffect, files: [Int64: TelegramMediaFile]) { switch apiMessageEffect { @@ -157,9 +183,9 @@ private extension AvailableMessageEffects.MessageEffect { id: id, isPremium: isPremium, emoticon: emoticon, - staticIcon: staticIconId.flatMap({ files[$0] }), - effectSticker: effectSticker, - effectAnimation: effectAnimationId.flatMap({ files[$0] }) + staticIcon: staticIconId.flatMap({ files[$0].flatMap(TelegramMediaFile.Accessor.init) }), + effectSticker: TelegramMediaFile.Accessor(effectSticker), + effectAnimation: effectAnimationId.flatMap({ files[$0].flatMap(TelegramMediaFile.Accessor.init) }) ) } } @@ -289,22 +315,3 @@ func managedSynchronizeAvailableMessageEffects(postbox: Postbox, network: Networ ) |> restart } - -public extension Message { - func messageEffect(availableMessageEffects: AvailableMessageEffects?) -> AvailableMessageEffects.MessageEffect? { - guard let availableMessageEffects else { - return nil - } - for attribute in self.attributes { - if let attribute = attribute as? EffectMessageAttribute { - for effect in availableMessageEffects.messageEffects { - if effect.id == attribute.id { - return effect - } - } - break - } - } - return nil - } -} diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_InstantPage.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_InstantPage.swift index 24288a45ba..b00622915e 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_InstantPage.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_InstantPage.swift @@ -1411,7 +1411,7 @@ public final class InstantPage: PostboxCoding, Equatable { self.url = decoder.decodeStringForKey("url", orElse: "") self.views = decoder.decodeOptionalInt32ForKey("v") - #if DEBUG + #if DEBUG && false var builder = FlatBufferBuilder(initialSize: 1024) let offset = self.encodeToFlatBuffers(builder: &builder) builder.finish(offset: offset) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift index 1af0e79bda..682296a622 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_StickerPackCollectionInfo.swift @@ -104,7 +104,7 @@ public final class StickerPackCollectionInfo: ItemCollectionInfo, Equatable { encoder.encodeInt32(self.flags.rawValue, forKey: "f") encoder.encodeInt32(self.count, forKey: "n") - #if DEBUG + #if DEBUG && false var builder = FlatBufferBuilder(initialSize: 1024) let offset = self.encodeToFlatBuffers(builder: &builder) builder.finish(offset: offset) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift index 375710f705..af19a2fdf2 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramChannel.swift @@ -347,7 +347,7 @@ public final class TelegramChannel: Peer, Equatable { self.verificationIconFileId = decoder.decodeOptionalInt64ForKey("vfid") self.sendPaidMessageStars = decoder.decodeCodable(StarsAmount.self, forKey: "sendPaidMessageStars") - #if DEBUG + #if DEBUG && false var builder = FlatBufferBuilder(initialSize: 1024) let offset = self.encodeToFlatBuffers(builder: &builder) builder.finish(offset: offset) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramGroup.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramGroup.swift index 975cab50bc..aacc14a215 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramGroup.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramGroup.swift @@ -207,7 +207,7 @@ public final class TelegramGroup: Peer, Equatable { self.creationDate = decoder.decodeInt32ForKey("d", orElse: 0) self.version = Int(decoder.decodeInt32ForKey("v", orElse: 0)) - #if DEBUG + #if DEBUG && false var builder = FlatBufferBuilder(initialSize: 1024) let offset = self.encodeToFlatBuffers(builder: &builder) builder.finish(offset: offset) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index 2f396b8031..981c09d4c6 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -698,8 +698,7 @@ public final class TelegramMediaFile: Media, Equatable, Codable { } else if let lhsWrappedData = lhs._wrappedData, let rhsWrappedData = rhs._wrappedData { return lhsWrappedData == rhsWrappedData } else { - assertionFailure() - return false + return lhs._parse() == rhs._parse() } } } @@ -903,13 +902,6 @@ public final class TelegramMediaFile: Media, Equatable, Codable { try container.encode(postboxEncoder.makeData(), forKey: .data) } - public func encodeToFlatBuffersData() -> Data { - var builder = FlatBufferBuilder(initialSize: 1024) - let value = self.encodeToFlatBuffers(builder: &builder) - builder.finish(offset: value) - return builder.data - } - public init(flatBuffersObject: TelegramCore_TelegramMediaFile) throws { self.fileId = MediaId(namespace: flatBuffersObject.fileId.namespace, id: flatBuffersObject.fileId.id) self.partialReference = try flatBuffersObject.partialReference.flatMap { try PartialMediaReference(flatBuffersObject: $0 ) } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramPeerNotificationSettings.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramPeerNotificationSettings.swift index 71ade1cead..78df24b4f2 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramPeerNotificationSettings.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramPeerNotificationSettings.swift @@ -21,10 +21,21 @@ private let cloudSoundMapping: [Int32: Int64] = [ 108: 5078299559046677216, 109: 5078299559046677217, 110: 5078299559046677218, - 111: 5078299559046677219 + 111: 5078299559046677219, + 200: 5032932652722685163, + 201: 5032932652722685160, + 202: 5032932652722685159, + 203: 5032932652722685158, + 204: 5032932652722685168, + 205: 5032932652722685167, + 206: 5032932652722685166, + 207: 5032932652722685165, + 208: 5032932652722685164, + 209: 5032932652722685162, + 210: 5032932652722685161 ] -public let defaultCloudPeerNotificationSound: PeerMessageSound = .cloud(fileId: cloudSoundMapping[100]!) +public let defaultCloudPeerNotificationSound: PeerMessageSound = .cloud(fileId: cloudSoundMapping[200]!) public enum CloudSoundBuiltinCategory { case modern diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift index dcc7911f07..fb5cd2970d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramUser.swift @@ -331,7 +331,7 @@ public final class TelegramUser: Peer, Equatable { self.subscriberCount = decoder.decodeOptionalInt32ForKey("ssc") self.verificationIconFileId = decoder.decodeOptionalInt64ForKey("vfid") - #if DEBUG + #if DEBUG && false var builder = FlatBufferBuilder(initialSize: 1024) let offset = self.encodeToFlatBuffers(builder: &builder) builder.finish(offset: offset) diff --git a/submodules/TelegramCore/Sources/Utils/MessageUtils.swift b/submodules/TelegramCore/Sources/Utils/MessageUtils.swift index 71c8071ddf..cb3b5a8c40 100644 --- a/submodules/TelegramCore/Sources/Utils/MessageUtils.swift +++ b/submodules/TelegramCore/Sources/Utils/MessageUtils.swift @@ -642,3 +642,22 @@ public func _internal_parseMediaAttachment(data: Data) -> Media? { return nil } } + +public extension Message { + func messageEffect(availableMessageEffects: AvailableMessageEffects?) -> AvailableMessageEffects.MessageEffect? { + guard let availableMessageEffects else { + return nil + } + for attribute in self.attributes { + if let attribute = attribute as? EffectMessageAttribute { + for effect in availableMessageEffects.messageEffects { + if effect.id == attribute.id { + return effect + } + } + break + } + } + return nil + } +} diff --git a/submodules/TelegramStringFormatting/Sources/PeerNotificationSoundStrings.swift b/submodules/TelegramStringFormatting/Sources/PeerNotificationSoundStrings.swift index 697670cb05..bcc088c7a9 100644 --- a/submodules/TelegramStringFormatting/Sources/PeerNotificationSoundStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/PeerNotificationSoundStrings.swift @@ -14,7 +14,18 @@ private let modernSoundsNamePaths: [KeyPath] = [ \.NotificationsSound_Keys, \.NotificationsSound_Popcorn, \.NotificationsSound_Pulse, - \.NotificationsSound_Synth + \.NotificationsSound_Synth, + \.NotificationsSound_Rebound, + \.NotificationsSound_Antic, + \.NotificationsSound_Cheers, + \.NotificationsSound_Droplet, + \.NotificationsSound_Handoff, + \.NotificationsSound_Milestone, + \.NotificationsSound_Passage, + \.NotificationsSound_Portal, + \.NotificationsSound_Rattle, + \.NotificationsSound_Slide, + \.NotificationsSound_Welcome ] private let classicSoundNamePaths: [KeyPath] = [ diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift index 7665ed8d47..44698bdff0 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageDateAndStatusNode/Sources/ChatMessageDateAndStatusNode.swift @@ -1116,7 +1116,7 @@ public class ChatMessageDateAndStatusNode: ASDisplayNode { var centerAnimation: TelegramMediaFile? - centerAnimation = messageEffect.staticIcon + centerAnimation = messageEffect.staticIcon?._parse() node.update( context: arguments.context, diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift index 5946804836..4b569bba1e 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageInteractiveMediaNode/Sources/ChatMessageInteractiveMediaNode.swift @@ -2286,7 +2286,8 @@ public final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTr if automaticDownload != .none, let file = media as? TelegramMediaFile, NativeVideoContent.isHLSVideo(file: file) { let postbox = context.account.postbox - let fetchSignal = HLSVideoContent.minimizedHLSQualityPreloadData(postbox: context.account.postbox, file: .message(message: MessageReference(message), media: file), userLocation: .peer(message.id.peerId), prefixSeconds: 10, autofetchPlaylist: true, codecConfiguration: HLSCodecConfiguration(context: context)) + let fetchSignal: Signal + fetchSignal = HLSVideoContent.minimizedHLSQualityPreloadData(postbox: context.account.postbox, file: .message(message: MessageReference(message), media: file), userLocation: .peer(message.id.peerId), prefixSeconds: 10, autofetchPlaylist: true, codecConfiguration: HLSCodecConfiguration(context: context)) |> mapToSignal { fileAndRange -> Signal in guard let fileAndRange else { return .complete() diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift b/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift index 0a346026bc..8634e2b9d2 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageItemView/Sources/ChatMessageItemView.swift @@ -938,13 +938,13 @@ open class ChatMessageItemView: ListViewItemNode, ChatMessageItemNodeProtocol { } self.playedEffectAnimation = true - if let effectAnimation = effect.effectAnimation { + if let effectAnimation = effect.effectAnimation?._parse() { self.playEffectAnimation(resource: effectAnimation.resource) if self.fetchEffectDisposable == nil { self.fetchEffectDisposable = freeMediaFileResourceInteractiveFetched(account: item.context.account, userLocation: .other, fileReference: .standalone(media: effectAnimation), resource: effectAnimation.resource).startStrict() } } else { - let effectSticker = effect.effectSticker + let effectSticker = effect.effectSticker._parse() if let effectFile = effectSticker.videoThumbnails.first { self.playEffectAnimation(resource: effectFile.resource) if self.fetchEffectDisposable == nil { diff --git a/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift b/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift index be3736f8ce..d817a3b4b7 100644 --- a/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift +++ b/submodules/TelegramUI/Components/Chat/TopMessageReactions/Sources/TopMessageReactions.swift @@ -501,7 +501,7 @@ public func effectMessageReactions(context: AccountContext) -> Signal<[ReactionI } existingIds.insert(messageEffect.id) - let mainFile = TelegramMediaFile.Accessor(messageEffect.effectSticker) + let mainFile = messageEffect.effectSticker result.append(ReactionItem( reaction: ReactionItem.Reaction(rawValue: .custom(messageEffect.id)), diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index b942c311a5..a8fe5fc285 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -82,18 +82,20 @@ public func generateTopicIcon(title: String, backgroundColors: [UIColor], stroke }) } -public enum AnimationCacheAnimationType { +public enum AnimationCacheAnimationType: Equatable { case still case lottie - case video + case video(isVP9: Bool) } public extension AnimationCacheAnimationType { init(file: TelegramMediaFile) { if file.isVideoSticker || file.isVideoEmoji { - self = .video + self = .video(isVP9: true) } else if file.isAnimatedSticker { self = .lottie + } else if file.isVideo { + self = .video(isVP9: false) } else { self = .still } @@ -122,8 +124,8 @@ public func animationCacheFetchFile(postbox: Postbox, userLocation: MediaResourc } switch type { - case .video: - cacheVideoAnimation(path: result, width: Int(options.size.width), height: Int(options.size.height), writer: options.writer, firstFrameOnly: options.firstFrameOnly, customColor: customColor) + case let .video(isVP9): + cacheVideoAnimation(path: result, hintVP9: isVP9, width: Int(options.size.width), height: Int(options.size.height), writer: options.writer, firstFrameOnly: options.firstFrameOnly, customColor: customColor) case .lottie: guard let data = try? Data(contentsOf: URL(fileURLWithPath: result)) else { options.writer.finish() @@ -153,8 +155,8 @@ public func animationCacheLoadLocalFile(name: String, type: AnimationCacheAnimat } switch type { - case .video: - cacheVideoAnimation(path: result, width: Int(options.size.width), height: Int(options.size.height), writer: options.writer, firstFrameOnly: options.firstFrameOnly, customColor: customColor) + case let .video(isVP9): + cacheVideoAnimation(path: result, hintVP9: isVP9, width: Int(options.size.width), height: Int(options.size.height), writer: options.writer, firstFrameOnly: options.firstFrameOnly, customColor: customColor) case .lottie: guard let data = try? Data(contentsOf: URL(fileURLWithPath: result)) else { options.writer.finish() diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift index db8ad96529..9e693c07c7 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiKeyboardItemLayer.swift @@ -33,7 +33,7 @@ public final class EmojiKeyboardItemLayer: MultiAnimationRenderTarget { case locked case featured case text(String) - case customFile(TelegramMediaFile) + case customFile(TelegramMediaFile.Accessor) } public let item: EmojiPagerContentComponent.Item diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 6811ddf78d..d8cb082c80 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -43,10 +43,10 @@ public final class EntityKeyboardAnimationData: Equatable { case gift(String) } - public enum ItemType { + public enum ItemType: Equatable { case still case lottie - case video + case video(isVP9: Bool) var animationCacheAnimationType: AnimationCacheAnimationType { switch self { @@ -54,8 +54,8 @@ public final class EntityKeyboardAnimationData: Equatable { return .still case .lottie: return .lottie - case .video: - return .video + case let .video(isVP9): + return .video(isVP9: isVP9) } } } @@ -105,9 +105,11 @@ public final class EntityKeyboardAnimationData: Equatable { public convenience init(file: TelegramMediaFile.Accessor, isReaction: Bool = false, partialReference: PartialMediaReference? = nil) { let type: ItemType if file.isVideoSticker || file.isVideoEmoji { - type = .video + type = .video(isVP9: true) } else if file.isAnimatedSticker { type = .lottie + } else if file.isVideo { + type = .video(isVP9: false) } else { type = .still } @@ -406,7 +408,7 @@ public final class EmojiPagerContentComponent: Component { case locked case premium case text(String) - case customFile(TelegramMediaFile) + case customFile(TelegramMediaFile.Accessor) } public enum TintMode: Equatable { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift index e5631ac485..65d4422d7a 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentSignals.swift @@ -287,7 +287,9 @@ public extension EmojiPagerContentComponent { if item.file.isAnimatedSticker { type = .lottie } else if item.file.isVideoEmoji || item.file.isVideoSticker { - type = .video + type = .video(isVP9: true) + } else if item.file.isVideo { + type = .video(isVP9: false) } else { type = .still } @@ -1390,7 +1392,9 @@ public extension EmojiPagerContentComponent { if item.file.isAnimatedSticker { type = .lottie } else if item.file.isVideoEmoji || item.file.isVideoSticker { - type = .video + type = .video(isVP9: true) + } else if item.file.isVideo { + type = .video(isVP9: false) } else { type = .still } @@ -1477,7 +1481,9 @@ public extension EmojiPagerContentComponent { if item.file.isAnimatedSticker { type = .lottie } else if item.file.isVideoEmoji || item.file.isVideoSticker { - type = .video + type = .video(isVP9: true) + } else if item.file.isVideo { + type = .video(isVP9: false) } else { type = .still } @@ -1774,7 +1780,9 @@ public extension EmojiPagerContentComponent { if item.file.isAnimatedSticker { type = .lottie } else if item.file.isVideoEmoji || item.file.isVideoSticker { - type = .video + type = .video(isVP9: true) + } else if item.file.isVideo { + type = .video(isVP9: false) } else { type = .still } @@ -2011,7 +2019,9 @@ public extension EmojiPagerContentComponent { if item.file.isAnimatedSticker { type = .lottie } else if item.file.isVideoEmoji || item.file.isVideoSticker { - type = .video + type = .video(isVP9: true) + } else if item.file.isVideo { + type = .video(isVP9: false) } else { type = .still } @@ -2090,7 +2100,9 @@ public extension EmojiPagerContentComponent { if item.file.isAnimatedSticker { type = .lottie } else if item.file.isVideoEmoji || item.file.isVideoSticker { - type = .video + type = .video(isVP9: true) + } else if item.file.isVideo { + type = .video(isVP9: false) } else { type = .still } @@ -2234,7 +2246,7 @@ public extension EmojiPagerContentComponent { continue } - let itemFile: TelegramMediaFile = item.effectSticker + let itemFile = item.effectSticker var tintMode: Item.TintMode = .none if itemFile.isCustomTemplateEmoji { @@ -2258,11 +2270,11 @@ public extension EmojiPagerContentComponent { } } - let animationData = EntityKeyboardAnimationData(file: TelegramMediaFile.Accessor(itemFile), partialReference: .none) + let animationData = EntityKeyboardAnimationData(file: itemFile, partialReference: .none) let resultItem = EmojiPagerContentComponent.Item( animationData: animationData, content: .animation(animationData), - itemFile: TelegramMediaFile.Accessor(itemFile), + itemFile: itemFile, subgroupId: nil, icon: icon, tintMode: tintMode diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/PremiumBadgeView.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/PremiumBadgeView.swift index d2d5c1f6c7..e3d20690f8 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/PremiumBadgeView.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/PremiumBadgeView.swift @@ -81,7 +81,7 @@ final class PremiumBadgeView: UIView { context: self.context, userLocation: .other, attemptSynchronousLoad: false, - file: customFile, + file: customFile._parse(), cache: self.context.animationCache, renderer: self.context.animationRenderer, unique: false, diff --git a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift index 77a642802d..5eaa7014cb 100644 --- a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift +++ b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift @@ -18,9 +18,9 @@ private func roundUp(_ numToRound: Int, multiple: Int) -> Int { return numToRound + multiple - remainder } -public func cacheVideoAnimation(path: String, width: Int, height: Int, writer: AnimationCacheItemWriter, firstFrameOnly: Bool, customColor: UIColor?) { +public func cacheVideoAnimation(path: String, hintVP9: Bool, width: Int, height: Int, writer: AnimationCacheItemWriter, firstFrameOnly: Bool, customColor: UIColor?) { let work: () -> Void = { - guard let frameSource = makeVideoStickerDirectFrameSource(queue: writer.queue, path: path, width: roundUp(width, multiple: 16), height: roundUp(height, multiple: 16), cachePathPrefix: nil, unpremultiplyAlpha: false) else { + guard let frameSource = makeVideoStickerDirectFrameSource(queue: writer.queue, path: path, hintVP9: hintVP9, width: roundUp(width, multiple: 16), height: roundUp(height, multiple: 16), cachePathPrefix: nil, unpremultiplyAlpha: false) else { return } let frameDuration = 1.0 / Double(frameSource.frameRate) diff --git a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift index b54ea987e4..40722128c5 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputActionButtonsNode.swift @@ -102,7 +102,7 @@ private final class EffectBadgeView: UIView { } let effectIconContent: ChatSendMessageScreenEffectIcon.Content if let staticIcon = effect.staticIcon { - effectIconContent = .file(staticIcon) + effectIconContent = .file(staticIcon._parse()) } else { effectIconContent = .text(effect.emoticon) }