From 8c5f0072bb790d295ceb0cdb24a90d7d65e3a82f Mon Sep 17 00:00:00 2001 From: Isaac <> Date: Fri, 11 Jul 2025 17:21:51 +0400 Subject: [PATCH] History optimizations --- .../Sources/State/AccountViewTracker.swift | 14 +++++- .../TelegramEngine/Messages/AdMessages.swift | 41 +++++++++++++---- .../Messages/TelegramEngineMessages.swift | 4 +- .../Chat/ChatControllerLoadDisplayNode.swift | 20 ++++++++ .../TelegramUI/Sources/ChatController.swift | 8 ++++ .../Sources/ChatControllerContentData.swift | 46 ++++--------------- .../Sources/ChatControllerNode.swift | 2 +- 7 files changed, 82 insertions(+), 53 deletions(-) diff --git a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift index 39d0bc8833..5021b1dfbc 100644 --- a/submodules/TelegramCore/Sources/State/AccountViewTracker.swift +++ b/submodules/TelegramCore/Sources/State/AccountViewTracker.swift @@ -1962,7 +1962,7 @@ public final class AccountViewTracker { let polled = self.polledChannel(peerId: peerId).start() var addHole = false - let pollingCompleted: Signal + var pollingCompleted: Signal if let context = self.channelPollingContexts[peerId] { if !context.isUpdatedValue { addHole = true @@ -1972,9 +1972,19 @@ public final class AccountViewTracker { addHole = true pollingCompleted = .single(true) } + + /*#if DEBUG + if "".isEmpty { + addHole = false + pollingCompleted = .single(true) + } + #endif*/ + let resetPeerHoleManagement = self.resetPeerHoleManagement let isAutomaticallyTracked = self.account!.postbox.transaction { transaction -> Bool in if transaction.getPeerChatListIndex(peerId) == nil { + transaction.resetIncomingReadStates([peerId: [Namespaces.Message.Cloud : PeerReadState.idBased( + maxIncomingReadId: 1, maxOutgoingReadId: 1, maxKnownId: 1, count: 0, markedUnread: false)]]) if addHole { resetPeerHoleManagement?(peerId) transaction.addHole(peerId: peerId, threadId: nil, namespace: Namespaces.Message.Cloud, space: .everywhere, range: 1 ... (Int32.max - 1)) @@ -2249,7 +2259,7 @@ public final class AccountViewTracker { return -1 } }, next: { [weak self] next, viewId in - if let strongSelf = self, let account = strongSelf.account { + if let strongSelf = self, let account = strongSelf.account, updateData { strongSelf.updateCachedPeerData(peerId: peerId, accountPeerId: account.peerId, viewId: viewId, hasCachedData: next.cachedData != nil) } }, disposed: { [weak self] viewId in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift index f4f8f084b2..bdec7f6acc 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/AdMessages.swift @@ -440,15 +440,14 @@ private class AdMessagesHistoryContextImpl { } } + private var isActivated: Bool = false private let disposable = MetaDisposable() - init(queue: Queue, account: Account, peerId: EnginePeer.Id, messageId: EngineMessage.Id?) { + init(queue: Queue, account: Account, peerId: EnginePeer.Id, messageId: EngineMessage.Id?, activateManually: Bool) { self.queue = queue self.account = account self.peerId = peerId self.messageId = messageId - - let accountPeerId = account.peerId self.stateValue = State(interPostInterval: nil, messages: []) @@ -467,6 +466,27 @@ private class AdMessagesHistoryContextImpl { }) } + if !activateManually { + self.activate() + } + } + + deinit { + self.disposable.dispose() + self.maskAsSeenDisposables.dispose() + } + + func activate() { + if self.isActivated { + return + } + self.isActivated = true + + let peerId = self.peerId + let accountPeerId = self.account.peerId + let account = self.account + let messageId = self.messageId + let signal: Signal<(interPostInterval: Int32?, startDelay: Int32?, betweenDelay: Int32?, messages: [Message]), NoError> = account.postbox.transaction { transaction -> Api.InputPeer? in return transaction.getPeer(peerId).flatMap(apiInputPeer) } @@ -563,11 +583,6 @@ private class AdMessagesHistoryContextImpl { strongSelf.stateValue = State(interPostInterval: interPostInterval, startDelay: startDelay, betweenDelay: betweenDelay, messages: messages) })) } - - deinit { - self.disposable.dispose() - self.maskAsSeenDisposables.dispose() - } func markAsSeen(opaqueId: Data) { let signal: Signal = self.account.network.request(Api.functions.messages.viewSponsoredMessage(randomId: Buffer(data: opaqueId))) @@ -629,13 +644,13 @@ public class AdMessagesHistoryContext { } } - public init(account: Account, peerId: EnginePeer.Id, messageId: EngineMessage.Id? = nil) { + public init(account: Account, peerId: EnginePeer.Id, messageId: EngineMessage.Id? = nil, activateManually: Bool = false) { self.peerId = peerId self.messageId = messageId let queue = self.queue self.impl = QueueLocalObject(queue: queue, generate: { - return AdMessagesHistoryContextImpl(queue: queue, account: account, peerId: peerId, messageId: messageId) + return AdMessagesHistoryContextImpl(queue: queue, account: account, peerId: peerId, messageId: messageId, activateManually: activateManually) }) } @@ -656,6 +671,12 @@ public class AdMessagesHistoryContext { impl.remove(opaqueId: opaqueId) } } + + public func activate() { + self.impl.with { impl in + impl.activate() + } + } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift index b1e1a49b2d..ae90822692 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/TelegramEngineMessages.swift @@ -415,8 +415,8 @@ public extension TelegramEngine { } } - public func adMessages(peerId: PeerId, messageId: EngineMessage.Id? = nil) -> AdMessagesHistoryContext { - return AdMessagesHistoryContext(account: self.account, peerId: peerId, messageId: messageId) + public func adMessages(peerId: PeerId, messageId: EngineMessage.Id? = nil, activateManually: Bool = false) -> AdMessagesHistoryContext { + return AdMessagesHistoryContext(account: self.account, peerId: peerId, messageId: messageId, activateManually: activateManually) } public func messageReadStats(id: MessageId) -> Signal { diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift index 3347ad119f..49c9f3e815 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerLoadDisplayNode.swift @@ -568,6 +568,26 @@ extension ChatControllerImpl { self.dismiss() } } + + self.updatePreloadNextChatPeerId() + } + + func updatePreloadNextChatPeerId() { + if !self.checkedPeerChatServiceActions { + return + } + + if self.preloadNextChatPeerId != self.contentData?.state.preloadNextChatPeerId { + self.preloadNextChatPeerId = self.contentData?.state.preloadNextChatPeerId + if let nextPeerId = self.contentData?.state.preloadNextChatPeerId { + let combinedDisposable = DisposableSet() + self.preloadNextChatPeerIdDisposable.set(combinedDisposable) + combinedDisposable.add(self.context.account.viewTracker.polledChannel(peerId: nextPeerId).startStrict()) + combinedDisposable.add(self.context.account.addAdditionalPreloadHistoryPeerId(peerId: nextPeerId)) + } else { + self.preloadNextChatPeerIdDisposable.set(nil) + } + } } func reloadCachedData() { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index cb3589cf7b..85005a457b 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -260,6 +260,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var didHandlePerformDismissAction: Bool = false var didInitializePersistentPeerInterfaceData: Bool = false + var preloadNextChatPeerId: EnginePeer.Id? = nil + let preloadNextChatPeerIdDisposable = MetaDisposable() + var accountPeerDisposable: Disposable? let cachedDataReady = Promise() @@ -6166,6 +6169,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.accountPeerDisposable?.dispose() self.contentDataDisposable?.dispose() self.updateMessageTodoDisposables?.dispose() + self.preloadNextChatPeerIdDisposable.dispose() } public func updatePresentationMode(_ mode: ChatControllerPresentationMode) { @@ -6910,6 +6914,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if case let .peer(peerId) = self.chatLocation { let _ = self.context.engine.peers.checkPeerChatServiceActions(peerId: peerId).startStandalone() + + self.context.account.viewTracker.forceUpdateCachedPeerData(peerId: peerId) + self.chatDisplayNode.adMessagesContext?.activate() + self.updatePreloadNextChatPeerId() } if self.chatLocation.peerId != nil && self.chatDisplayNode.frameForInputActionButton() != nil { diff --git a/submodules/TelegramUI/Sources/ChatControllerContentData.swift b/submodules/TelegramUI/Sources/ChatControllerContentData.swift index ebf5cdc9d3..5fc625bacd 100644 --- a/submodules/TelegramUI/Sources/ChatControllerContentData.swift +++ b/submodules/TelegramUI/Sources/ChatControllerContentData.swift @@ -142,6 +142,8 @@ extension ChatControllerImpl { var isGeneralThreadClosed: Bool? var premiumGiftOptions: [CachedPremiumGiftOption] = [] var removePaidMessageFeeData: ChatPresentationInterfaceState.RemovePaidMessageFeeData? + + var preloadNextChatPeerId: EnginePeer.Id? } private let presentationData: PresentationData @@ -152,9 +154,6 @@ extension ChatControllerImpl { private var preloadHistoryPeerId: PeerId? private let preloadHistoryPeerIdDisposable = MetaDisposable() - - private var preloadNextChatPeerId: PeerId? - private let preloadNextChatPeerIdDisposable = MetaDisposable() private var nextChannelToReadDisposable: Disposable? private let chatAdditionalDataDisposable = MetaDisposable() @@ -946,11 +945,7 @@ extension ChatControllerImpl { explicitelyCanPinMessages = true } - #if DEBUG - peerMonoforumId = nil - #endif - - let preloadHistoryPeerId = peerMonoforumId ?? peerDiscussionId + let preloadHistoryPeerId = peerMonoforumId// ?? peerDiscussionId if strongSelf.preloadHistoryPeerId != preloadHistoryPeerId { strongSelf.preloadHistoryPeerId = preloadHistoryPeerId if let preloadHistoryPeerId, let channel = peerView.peers[peerView.peerId] as? TelegramChannel, case .broadcast = channel.info { @@ -1056,18 +1051,8 @@ extension ChatControllerImpl { } let nextPeerId = nextPeer?.id - - if strongSelf.preloadNextChatPeerId != nextPeerId { - strongSelf.preloadNextChatPeerId = nextPeerId - if let nextPeerId = nextPeerId { - let combinedDisposable = DisposableSet() - strongSelf.preloadNextChatPeerIdDisposable.set(combinedDisposable) - combinedDisposable.add(context.account.viewTracker.polledChannel(peerId: nextPeerId).startStrict()) - combinedDisposable.add(context.account.addAdditionalPreloadHistoryPeerId(peerId: nextPeerId)) - } else { - strongSelf.preloadNextChatPeerIdDisposable.set(nil) - } - } + + strongSelf.state.preloadNextChatPeerId = nextPeerId if isUpdated { strongSelf.onUpdated?(previousState) @@ -1110,18 +1095,8 @@ extension ChatControllerImpl { } let nextPeerId = nextPeer?.peer.id - - if strongSelf.preloadNextChatPeerId != nextPeerId { - strongSelf.preloadNextChatPeerId = nextPeerId - if let nextPeerId = nextPeerId { - let combinedDisposable = DisposableSet() - strongSelf.preloadNextChatPeerIdDisposable.set(combinedDisposable) - combinedDisposable.add(context.account.viewTracker.polledChannel(peerId: nextPeerId).startStrict()) - combinedDisposable.add(context.account.addAdditionalPreloadHistoryPeerId(peerId: nextPeerId)) - } else { - strongSelf.preloadNextChatPeerIdDisposable.set(nil) - } - } + + strongSelf.state.preloadNextChatPeerId = nextPeerId if isUpdated { strongSelf.onUpdated?(previousState) @@ -1653,11 +1628,7 @@ extension ChatControllerImpl { explicitelyCanPinMessages = true } - #if DEBUG - peerMonoforumId = nil - #endif - - let preloadHistoryPeerId = peerMonoforumId ?? peerDiscussionId + let preloadHistoryPeerId = peerMonoforumId// ?? peerDiscussionId if strongSelf.preloadHistoryPeerId != preloadHistoryPeerId { strongSelf.preloadHistoryPeerId = preloadHistoryPeerId if let preloadHistoryPeerId { @@ -2377,7 +2348,6 @@ extension ChatControllerImpl { self.titleDisposable?.dispose() self.preloadSavedMessagesChatsDisposable?.dispose() self.preloadHistoryPeerIdDisposable.dispose() - self.preloadNextChatPeerIdDisposable.dispose() self.nextChannelToReadDisposable?.dispose() self.chatAdditionalDataDisposable.dispose() self.premiumOrStarsRequiredDisposable?.dispose() diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 62d5b14286..83be2a0282 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -707,7 +707,7 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate { } } if let displayAdPeer { - self.adMessagesContext = context.engine.messages.adMessages(peerId: displayAdPeer) + self.adMessagesContext = context.engine.messages.adMessages(peerId: displayAdPeer, activateManually: true) } else { self.adMessagesContext = nil }