diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index dfebb69a3d..3b3c26f7c5 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -303,6 +303,10 @@ public final class AccountViewTracker { private var nextSeenLiveLocationDisposableId: Int32 = 0 private var seenLiveLocationDisposables = DisposableDict() + private var updatedExtendedMediaMessageIdsAndTimestamps: [MessageId: Int32] = [:] + private var nextUpdatedExtendedMediaDisposableId: Int32 = 0 + private var updatedExtendedMediaDisposables = DisposableDict() + private var updatedUnsupportedMediaMessageIdsAndTimestamps: [MessageId: Int32] = [:] private var refreshSecretChatMediaMessageIdsAndTimestamps: [MessageId: Int32] = [:] private var nextUpdatedUnsupportedMediaDisposableId: Int32 = 0 @@ -966,6 +970,59 @@ public final class AccountViewTracker { } } + public func updatedExtendedMediaForMessageIds(messageIds: Set) { + self.queue.async { + var addedMessageIds: [MessageId] = [] + let timestamp = Int32(CFAbsoluteTimeGetCurrent()) + for messageId in messageIds { + let messageTimestamp = self.updatedExtendedMediaMessageIdsAndTimestamps[messageId] + if messageTimestamp == nil || messageTimestamp! < timestamp - 30 { + self.updatedExtendedMediaMessageIdsAndTimestamps[messageId] = timestamp + addedMessageIds.append(messageId) + } + } + + if !addedMessageIds.isEmpty { + for (peerId, messageIds) in messagesIdsGroupedByPeerId(Set(addedMessageIds)) { + let disposableId = self.nextUpdatedExtendedMediaDisposableId + self.nextUpdatedExtendedMediaDisposableId += 1 + + if let account = self.account { + let signal = account.postbox.transaction { transaction -> Peer? in + if let peer = transaction.getPeer(peerId) { + return peer + } else { + return nil + } + } + |> mapToSignal { peer -> Signal in + guard let peer = peer, let inputPeer = apiInputPeer(peer) else { + return .complete() + } + return account.network.request(Api.functions.messages.getExtendedMedia(peer: inputPeer, id: messageIds.map { $0.id })) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignal { updates -> Signal in + if let updates = updates { + account.stateManager.addUpdates(updates) + } + return .complete() + } + } + |> afterDisposed { [weak self] in + self?.queue.async { + self?.updatedExtendedMediaDisposables.set(nil, forKey: disposableId) + } + } + self.updatedExtendedMediaDisposables.set(signal.start(), forKey: disposableId) + } + } + } + } + } + public func updateUnsupportedMediaForMessageIds(messageIds: Set) { self.queue.async { var addedMessageIds: [MessageId] = [] diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index c8a74ff0b6..24bdeb324c 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -489,6 +489,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { private let refreshMediaProcessingManager = ChatMessageThrottledProcessingManager() private let messageMentionProcessingManager = ChatMessageThrottledProcessingManager(delay: 0.2) private let unseenReactionsProcessingManager = ChatMessageThrottledProcessingManager(delay: 0.2, submitInterval: 0.0) + private let extendedMediaProcessingManager = ChatMessageVisibleThrottledProcessingManager(interval: 5.0) + let prefetchManager: InChatPrefetchManager private var currentEarlierPrefetchMessages: [(Message, Media)] = [] private var currentLaterPrefetchMessages: [(Message, Media)] = [] @@ -733,6 +735,13 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } } + self.extendedMediaProcessingManager.process = { [weak self] messageIds in + guard let strongSelf = self else { + return + } + strongSelf.context.account.viewTracker.updatedExtendedMediaForMessageIds(messageIds: messageIds) + } + self.preloadPages = false switch self.mode { case .bubbles: @@ -1747,6 +1756,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { var messageIdsWithRefreshMedia: [MessageId] = [] var messageIdsWithUnseenPersonalMention: [MessageId] = [] var messageIdsWithUnseenReactions: [MessageId] = [] + var messageIdsWithInactiveExtendedMedia = Set() var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = [] if indexRange.0 <= indexRange.1 { @@ -1813,6 +1823,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if let representation = image.representations.last { downloadableResourceIds.append((message.id, representation.resource.id.stringRepresentation)) } + } else if let invoice = media as? TelegramMediaInvoice, let extendedMedia = invoice.extendedMedia, case .preview = extendedMedia { + messageIdsWithInactiveExtendedMedia.insert(message.id) } } if contentRequiredValidation { @@ -2024,6 +2036,9 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { if !downloadableResourceIds.isEmpty { let _ = markRecentDownloadItemsAsSeen(postbox: self.context.account.postbox, items: downloadableResourceIds).start() } + if !messageIdsWithInactiveExtendedMedia.isEmpty { + self.extendedMediaProcessingManager.update(messageIdsWithInactiveExtendedMedia) + } self.currentEarlierPrefetchMessages = toEarlierMediaMessages self.currentLaterPrefetchMessages = toLaterMediaMessages diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift index bcfda8f2d6..8429903a11 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift @@ -90,7 +90,7 @@ private class ExtendedMediaOverlayNode: ASDisplayNode { self.blurNode = NavigationBackgroundNode(color: .clear) self.highlightedBackgroundNode = ASDisplayNode() - self.highlightedBackgroundNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.3) + self.highlightedBackgroundNode.backgroundColor = UIColor(rgb: 0xffffff, alpha: 0.2) self.highlightedBackgroundNode.alpha = 0.0 self.iconNode = ASImageNode() @@ -150,7 +150,7 @@ private class ExtendedMediaOverlayNode: ASDisplayNode { self.highlightedBackgroundNode.frame = CGRect(origin: .zero, size: contentSize) self.blurNode.frame = self.highlightedBackgroundNode.frame self.blurNode.update(size: self.blurNode.frame.size, transition: .immediate) - self.blurNode.updateColor(color: UIColor(rgb: 0xffffff, alpha: 0.2), enableBlur: true, transition: .immediate) + self.blurNode.updateColor(color: UIColor(rgb: 0x000000, alpha: 0.5), enableBlur: true, transition: .immediate) self.iconNode.frame = CGRect(origin: CGPoint(x: self.buttonNode.frame.minX + padding, y: self.buttonNode.frame.minY + floorToScreenPixels((contentSize.height - iconSize.height) / 2.0) + 1.0), size: iconSize) self.textNode.frame = CGRect(origin: CGPoint(x: self.iconNode.frame.maxX + spacing, y: self.buttonNode.frame.minY + floorToScreenPixels((contentSize.height - textSize.height) / 2.0)), size: textSize) @@ -1673,14 +1673,12 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio if self.badgeNode == nil { let badgeNode = ChatMessageInteractiveMediaBadge() - let incoming: Bool - if let context = self.context, let message = self.message { - incoming = message.effectivelyIncoming(context.account.peerId) - } else { - incoming = false + var inset: CGFloat = 6.0 + if let corners = self.currentImageArguments?.corners, case .Tail = corners.bottomLeft { + inset = 10.0 } - badgeNode.frame = CGRect(origin: CGPoint(x: incoming ? 10.0 : 6.0, y: 6.0), size: CGSize(width: radialStatusSize, height: radialStatusSize)) + badgeNode.frame = CGRect(origin: CGPoint(x: inset, y: 6.0), size: CGSize(width: radialStatusSize, height: radialStatusSize)) badgeNode.pressed = { [weak self] in guard let strongSelf = self, let fetchStatus = strongSelf.fetchStatus else { return diff --git a/submodules/TelegramUI/Sources/ChatMessageThrottledProcessingManager.swift b/submodules/TelegramUI/Sources/ChatMessageThrottledProcessingManager.swift index 4def50a932..a7eaa0f5b2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageThrottledProcessingManager.swift +++ b/submodules/TelegramUI/Sources/ChatMessageThrottledProcessingManager.swift @@ -78,16 +78,33 @@ final class ChatMessageThrottledProcessingManager { final class ChatMessageVisibleThrottledProcessingManager { private let queue = Queue() - private let delay: Double + private let interval: Double private var currentIds = Set() var process: ((Set) -> Void)? - private var timer: SwiftSignalKit.Timer? + private let timer: SwiftSignalKit.Timer - init(delay: Double = 1.0) { - self.delay = delay + init(interval: Double = 5.0) { + self.interval = interval + + var completionImpl: (() -> Void)? + let timer = SwiftSignalKit.Timer(timeout: self.interval, repeat: true, completion: { + completionImpl?() + }, queue: self.queue) + self.timer = timer + timer.start() + + completionImpl = { [weak self] in + if let strongSelf = self, !strongSelf.currentIds.isEmpty { + strongSelf.process?(strongSelf.currentIds) + } + } + } + + deinit { + self.timer.invalidate() } func setProcess(process: @escaping (Set) -> Void) { @@ -100,21 +117,8 @@ final class ChatMessageVisibleThrottledProcessingManager { self.queue.async { if self.currentIds != ids { self.currentIds = ids - if self.timer == nil { - var completionImpl: (() -> Void)? - let timer = SwiftSignalKit.Timer(timeout: self.delay, repeat: false, completion: { - completionImpl?() - }, queue: self.queue) - completionImpl = { [weak self, weak timer] in - if let strongSelf = self { - if let timer = timer, strongSelf.timer === timer { - strongSelf.timer = nil - } - strongSelf.process?(strongSelf.currentIds) - } - } - self.timer = timer - timer.start() + if !self.currentIds.isEmpty { + self.process?(self.currentIds) } } }