diff --git a/BUCK b/BUCK index fdb72687df..faa9336477 100644 --- a/BUCK +++ b/BUCK @@ -87,6 +87,7 @@ apple_library( '//submodules/LegacyComponents:LegacyComponents', '//submodules/ffmpeg:opus', '//submodules/MtProtoKit:MtProtoKit', + '//submodules/libtgvoip:tgvoip', ], ) @@ -117,18 +118,18 @@ apple_library( deps = [ ':TelegramUIResources', ':Images', - ':TelegramUIPrivateModule#static', - '//submodules/SSignalKit:SwiftSignalKit#static', - '//submodules/SSignalKit:SSignalKit#static', - '//submodules/Postbox:Postbox#static', - '//submodules/TelegramCore:TelegramCore#static', - '//submodules/MtProtoKit:MtProtoKit#static', - '//submodules/ffmpeg:FFMpeg#static', - '//submodules/AsyncDisplayKit:AsyncDisplayKit#static', - '//submodules/Display:Display#static', - '//submodules/LegacyComponents:LegacyComponents#static', - '//submodules/lottie-ios:Lottie#static', - '//submodules/webp:WebPImage#static', + ':TelegramUIPrivateModule', + '//submodules/SSignalKit:SwiftSignalKit', + '//submodules/SSignalKit:SSignalKit', + '//submodules/Postbox:Postbox', + '//submodules/TelegramCore:TelegramCore', + '//submodules/MtProtoKit:MtProtoKit', + '//submodules/ffmpeg:FFMpeg', + '//submodules/AsyncDisplayKit:AsyncDisplayKit', + '//submodules/Display:Display', + '//submodules/LegacyComponents:LegacyComponents', + '//submodules/lottie-ios:Lottie', + '//submodules/webp:WebPImage', ], ) diff --git a/TelegramUI/ChatHistoryListNode.swift b/TelegramUI/ChatHistoryListNode.swift index 5393efdf25..6a51d915ff 100644 --- a/TelegramUI/ChatHistoryListNode.swift +++ b/TelegramUI/ChatHistoryListNode.swift @@ -320,7 +320,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { private let historyDisposable = MetaDisposable() private let readHistoryDisposable = MetaDisposable() - private let messageViewQueue = Queue() + private let messageViewQueue = Queue(name: "ChatHistoryListNode processing") private var dequeuedInitialTransitionOnLayout = false private var enqueuedHistoryViewTransition: (ChatHistoryListViewTransition, () -> Void)? @@ -502,7 +502,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { return (view, version) } - let previousView = Atomic(value: nil) + let previousView = Atomic<(ChatHistoryView, Int)?>(value: nil) let automaticDownloadNetworkType = context.account.networkType |> map { type -> MediaAutoDownloadNetworkType in switch type { @@ -516,9 +516,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { let previousHistoryAppearsCleared = Atomic(value: nil) + let nextTransitionVersion = Atomic(value: 0) + let historyViewTransition = combineLatest(queue: messageViewQueue, historyViewUpdate, self.chatPresentationDataPromise.get(), selectedMessages, automaticDownloadNetworkType, self.historyAppearsClearedPromise.get()) |> introduceError(Void.self) - |> mapToQueue { [weak self] update, chatPresentationData, selectedMessages, networkType, historyAppearsCleared -> Signal in + |> mapToQueue { [weak self] update, chatPresentationData, selectedMessages, networkType, historyAppearsCleared -> Signal<(ChatHistoryListViewTransition, Int), Void> in func applyHole() { Queue.mainQueue().async { if let strongSelf = self { @@ -590,7 +592,15 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { let associatedData = extractAssociatedData(chatLocation: chatLocation, view: view, automaticDownloadNetworkType: networkType) let processedView = ChatHistoryView(originalView: view, filteredEntries: chatHistoryEntriesForView(location: chatLocation, view: view, includeUnreadEntry: mode == .bubbles, includeEmptyEntry: mode == .bubbles && tagMask == nil, includeChatInfoEntry: mode == .bubbles, includeSearchEntry: includeSearchEntry && tagMask != nil, reverse: reverse, groupMessages: mode == .bubbles, selectedMessages: selectedMessages, presentationData: chatPresentationData, historyAppearsCleared: historyAppearsCleared), associatedData: associatedData, id: id) - let previous = previousView.swap(processedView) + let previousValueAndVersion = previousView.swap((processedView, update.1)) + let previous = previousValueAndVersion?.0 + + if let previousVersion = previousValueAndVersion?.1 { + if !GlobalExperimentalSettings.isAppStoreBuild { + precondition(update.1 >= previousVersion) + } + assert(update.1 >= previousVersion) + } if scrollPosition == nil, let originalScrollPosition = originalScrollPosition { switch originalScrollPosition { @@ -632,19 +642,27 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } } } + let transitionVersion = nextTransitionVersion.modify { $0 + 1 } return preparedChatHistoryViewTransition(from: previous, to: processedView, reason: reason, reverse: reverse, chatLocation: chatLocation, controllerInteraction: controllerInteraction, scrollPosition: updatedScrollPosition, initialData: initialData?.initialData, keyboardButtonsMessage: view.topTaggedMessages.first, cachedData: initialData?.cachedData, cachedDataMessages: initialData?.cachedDataMessages, readStateData: initialData?.readStateData, flashIndicators: flashIndicators) |> map({ - mappedChatHistoryViewListTransition(context: context, chatLocation: chatLocation, associatedData: associatedData, controllerInteraction: controllerInteraction, mode: mode, transition: $0) + (mappedChatHistoryViewListTransition(context: context, chatLocation: chatLocation, associatedData: associatedData, controllerInteraction: controllerInteraction, mode: mode, transition: $0), transitionVersion) }) |> runOn(prepareOnMainQueue ? Queue.mainQueue() : messageViewQueue) |> introduceError(Void.self) } } + let appliedTransitionVersion = Atomic(value: nil) + let appliedTransition = historyViewTransition |> deliverOnMainQueue - |> mapToQueue { [weak self] transition -> Signal in + |> mapToQueue { [weak self] (transition, version) -> Signal in if let strongSelf = self { + let previousAppliedVersion = appliedTransitionVersion.swap(version) ?? 0 + if !GlobalExperimentalSettings.isAppStoreBuild { + precondition(version == previousAppliedVersion + 1) + } + assert(version == previousAppliedVersion + 1) return strongSelf.enqueueHistoryViewTransition(transition) |> introduceError(Void.self) }