Better history-ad integration

This commit is contained in:
Ali 2022-11-01 15:17:08 +04:00
parent 554cd0e6fe
commit efe0566b79
15 changed files with 186 additions and 131 deletions

View File

@ -689,6 +689,10 @@ public final class Message {
self.associatedThreadInfo = associatedThreadInfo
}
public func withUpdatedStableVersion(stableVersion: UInt32) -> Message {
return Message(stableId: self.stableId, stableVersion: stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: self.text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
}
public func withUpdatedText(_ text: String) -> Message {
return Message(stableId: self.stableId, stableVersion: self.stableVersion, id: self.id, globallyUniqueId: self.globallyUniqueId, groupingKey: self.groupingKey, groupInfo: self.groupInfo, threadId: self.threadId, timestamp: self.timestamp, flags: self.flags, tags: self.tags, globalTags: self.globalTags, localTags: self.localTags, forwardInfo: self.forwardInfo, author: self.author, text: text, attributes: self.attributes, media: self.media, peers: self.peers, associatedMessages: self.associatedMessages, associatedMessageIds: self.associatedMessageIds, associatedMedia: self.associatedMedia, associatedThreadInfo: self.associatedThreadInfo)
}

View File

@ -4038,6 +4038,32 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
})], parseMarkdown: true), in: .window(.root), with: nil)
}
})
}, activateAdAction: { [weak self] messageId in
guard let self, let message = self.chatDisplayNode.historyNode.messageInCurrentHistoryView(messageId), let adAttribute = message.adAttribute else {
return
}
switch adAttribute.target {
case let .peer(id, messageId, startParam):
let navigationData: ChatControllerInteractionNavigateToPeer
if let bot = message.author as? TelegramUser, bot.botInfo != nil, let startParam = startParam {
navigationData = .withBotStartPayload(ChatControllerInitialBotStart(payload: startParam, behavior: .interactive))
} else {
var subject: ChatControllerSubject?
if let messageId = messageId {
subject = .message(id: .id(messageId), highlight: true, timecode: nil)
}
navigationData = .chat(textInputState: nil, subject: subject, peekData: nil)
}
let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: id))
|> deliverOnMainQueue).start(next: { [weak self] peer in
if let self, let peer = peer {
self.openPeer(peer: peer, navigation: navigationData, fromMessage: nil)
}
})
case let .join(_, joinHash):
self.controllerInteraction?.openJoinLink(joinHash)
}
}, requestMessageUpdate: { [weak self] id, scroll in
if let strongSelf = self {
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id, andScrollToItem: scroll)
@ -6554,13 +6580,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var minOffsetForNavigation: CGFloat = 40.0
strongSelf.chatDisplayNode.historyNode.enumerateItemNodes { itemNode in
if let itemNode = itemNode as? ChatMessageBubbleItemNode {
if let message = itemNode.item?.content.firstMessage, message.adAttribute != nil {
if let message = itemNode.item?.content.firstMessage, let adAttribute = message.adAttribute {
minOffsetForNavigation += itemNode.bounds.height
switch offset {
case let .known(offset):
if offset <= 50.0 {
strongSelf.chatDisplayNode.historyNode.adSeenProcessingManager.add([message.id])
strongSelf.chatDisplayNode.historyNode.markAdAsSeen(opaqueId: adAttribute.opaqueId)
}
default:
break

View File

@ -141,6 +141,7 @@ public final class ChatControllerInteraction {
let openLargeEmojiInfo: (String, String?, TelegramMediaFile) -> Void
let openJoinLink: (String) -> Void
let openWebView: (String, String, Bool, Bool) -> Void
let activateAdAction: (EngineMessage.Id) -> Void
let requestMessageUpdate: (MessageId, Bool) -> Void
let cancelInteractiveKeyboardGestures: () -> Void
@ -248,6 +249,7 @@ public final class ChatControllerInteraction {
openLargeEmojiInfo: @escaping (String, String?, TelegramMediaFile) -> Void,
openJoinLink: @escaping (String) -> Void,
openWebView: @escaping (String, String, Bool, Bool) -> Void,
activateAdAction: @escaping (EngineMessage.Id) -> Void,
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
cancelInteractiveKeyboardGestures: @escaping () -> Void,
dismissTextInput: @escaping () -> Void,
@ -338,6 +340,7 @@ public final class ChatControllerInteraction {
self.openLargeEmojiInfo = openLargeEmojiInfo
self.openJoinLink = openJoinLink
self.openWebView = openWebView
self.activateAdAction = activateAdAction
self.requestMessageUpdate = requestMessageUpdate
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
self.dismissTextInput = dismissTextInput

View File

@ -25,7 +25,7 @@ func chatHistoryEntriesForView(
customChannelDiscussionReadState: MessageId?,
customThreadOutgoingReadState: MessageId?,
cachedData: CachedPeerData?,
adMessages: (interPostInterval: Int32?, messages: [Message]),
adMessage: Message?,
dynamicAdMessages: [Message]
) -> [ChatHistoryEntry] {
if historyAppearsCleared {
@ -339,11 +339,10 @@ func chatHistoryEntriesForView(
}
if view.laterId == nil && !view.isLoading {
if !entries.isEmpty, case let .MessageEntry(lastMessage, _, _, _, _, _) = entries[entries.count - 1], !adMessages.messages.isEmpty, adMessages.interPostInterval == nil {
var nextAdMessageId: Int32 = 1
if let message = adMessages.messages.first {
if !entries.isEmpty, case let .MessageEntry(lastMessage, _, _, _, _, _) = entries[entries.count - 1], let message = adMessage {
var nextAdMessageId: Int32 = 10000
let updatedMessage = Message(
stableId: UInt32.max - 1 - UInt32(nextAdMessageId),
stableId: ChatHistoryListNode.fixedAdMessageStableId,
stableVersion: message.stableVersion,
id: MessageId(peerId: message.id.peerId, namespace: message.id.namespace, id: nextAdMessageId),
globallyUniqueId: nil,
@ -357,7 +356,7 @@ func chatHistoryEntriesForView(
localTags: message.localTags,
forwardInfo: message.forwardInfo,
author: message.author,
text: message.text,
text: /*"\(message.adAttribute!.opaqueId.hashValue)" + */message.text,
attributes: message.attributes,
media: message.media,
peers: message.peers,
@ -370,7 +369,6 @@ func chatHistoryEntriesForView(
entries.append(.MessageEntry(updatedMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false)))
}
}
}
} else if includeSearchEntry {
if view.laterId == nil {
if !view.entries.isEmpty {

View File

@ -408,6 +408,8 @@ public enum ChatHistoryListSource {
}
public final class ChatHistoryListNode: ListView, ChatHistoryNode {
static let fixedAdMessageStableId: UInt32 = UInt32.max - 5000
private let context: AccountContext
private let chatLocation: ChatLocation
private let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
@ -495,7 +497,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
private let messageProcessingManager = ChatMessageThrottledProcessingManager()
private let messageWithReactionsProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 4.0)
let adSeenProcessingManager = ChatMessageThrottledProcessingManager()
private let seenLiveLocationProcessingManager = ChatMessageThrottledProcessingManager()
private let unsupportedMessageProcessingManager = ChatMessageThrottledProcessingManager()
private let refreshMediaProcessingManager = ChatMessageThrottledProcessingManager()
@ -606,18 +607,20 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
private var contentInsetAnimator: DisplayLinkAnimator?
private let adMessagesContext: AdMessagesHistoryContext?
private var adMessagesDisposable: Disposable?
private var preloadAdPeerId: PeerId?
private let preloadAdPeerDisposable = MetaDisposable()
private var pendingDynamicAdMessages: [Message] = []
private var pendingDynamicAdMessageInterval: Int?
private var remainingDynamicAdMessageInterval: Int?
private var remainingDynamicAdMessageDistance: CGFloat?
private var nextPendingDynamicMessageId: Int32 = 1
private var dynamicAdMessages: ([Message], Int) = ([], 0) {
private var allAdMessages: (fixed: Message?, opportunistic: [Message], version: Int) = (nil, [], 0) {
didSet {
self.dynamicAdMessagesPromise.set(.single(self.dynamicAdMessages))
self.allAdMessagesPromise.set(.single(self.allAdMessages))
}
}
private let dynamicAdMessagesPromise = Promise<([Message], Int)>(([], 0))
private let allAdMessagesPromise = Promise<(fixed: Message?, opportunistic: [Message], version: Int)>((nil, [], 0))
private var seenMessageIds = Set<MessageId>()
private var refreshDisplayedItemRangeTimer: SwiftSignalKit.Timer?
@ -686,35 +689,43 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
super.init()
adMessages = adMessages
|> afterNext { [weak self] interPostInterval, messages in
Queue.mainQueue().async {
guard let strongSelf = self else {
self.adMessagesDisposable = (adMessages
|> deliverOnMainQueue).start(next: { [weak self] interPostInterval, messages in
guard let self else {
return
}
if let interPostInterval = interPostInterval {
strongSelf.pendingDynamicAdMessages = messages
strongSelf.pendingDynamicAdMessageInterval = Int(interPostInterval)
strongSelf.remainingDynamicAdMessageInterval = Int(interPostInterval)
self.pendingDynamicAdMessages = messages
self.pendingDynamicAdMessageInterval = Int(interPostInterval)
if self.remainingDynamicAdMessageInterval == nil {
self.remainingDynamicAdMessageInterval = Int(interPostInterval)
}
if self.remainingDynamicAdMessageDistance == nil {
self.remainingDynamicAdMessageDistance = self.bounds.height
}
self.allAdMessages = (messages.first, [], 0)
} else {
var adPeerId: PeerId?
adPeerId = messages.first?.author?.id
if strongSelf.preloadAdPeerId != adPeerId {
strongSelf.preloadAdPeerId = adPeerId
if self.preloadAdPeerId != adPeerId {
self.preloadAdPeerId = adPeerId
if let adPeerId = adPeerId {
let combinedDisposable = DisposableSet()
strongSelf.preloadAdPeerDisposable.set(combinedDisposable)
combinedDisposable.add(strongSelf.context.account.viewTracker.polledChannel(peerId: adPeerId).start())
combinedDisposable.add(strongSelf.context.account.addAdditionalPreloadHistoryPeerId(peerId: adPeerId))
self.preloadAdPeerDisposable.set(combinedDisposable)
combinedDisposable.add(self.context.account.viewTracker.polledChannel(peerId: adPeerId).start())
combinedDisposable.add(self.context.account.addAdditionalPreloadHistoryPeerId(peerId: adPeerId))
} else {
strongSelf.preloadAdPeerDisposable.set(nil)
}
}
self.preloadAdPeerDisposable.set(nil)
}
}
self.allAdMessages = (messages.first, [], 0)
}
})
self.clipsToBounds = false
@ -737,16 +748,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
self.messageWithReactionsProcessingManager.process = { [weak context] messageIds in
context?.account.viewTracker.updateReactionsForMessageIds(messageIds: messageIds)
}
self.adSeenProcessingManager.process = { [weak self] messageIds in
guard let strongSelf = self, let adMessagesContext = strongSelf.adMessagesContext else {
return
}
for id in messageIds {
if let message = strongSelf.messageInCurrentHistoryView(id), let adAttribute = message.adAttribute {
adMessagesContext.markAsSeen(opaqueId: adAttribute.opaqueId)
}
}
}
self.seenLiveLocationProcessingManager.process = { [weak context] messageIds in
context?.account.viewTracker.updateSeenLiveLocationForMessageIds(messageIds: messageIds)
}
@ -1096,15 +1097,14 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
additionalAnimatedEmojiStickers,
customChannelDiscussionReadState,
customThreadOutgoingReadState,
adMessages,
availableReactions,
defaultReaction,
accountPeer,
audioTranscriptionSuggestion,
promises,
topicAuthorId,
self.dynamicAdMessagesPromise.get()
).start(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, adMessages, availableReactions, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, dynamicAdMessages in
self.allAdMessagesPromise.get()
).start(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, availableReactions, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, allAdMessages in
let (historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, currentlyPlayingMessageIdAndType, scrollToMessageId) = promises
let currentlyPlayingMessageId = currentlyPlayingMessageIdAndType?.0
@ -1265,12 +1265,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
customChannelDiscussionReadState: customChannelDiscussionReadState,
customThreadOutgoingReadState: customThreadOutgoingReadState,
cachedData: data.cachedData,
adMessages: adMessages,
dynamicAdMessages: dynamicAdMessages.0
adMessage: allAdMessages.fixed,
dynamicAdMessages: allAdMessages.opportunistic
)
let lastHeaderId = filteredEntries.last.flatMap { listMessageDateHeaderId(timestamp: $0.index.timestamp) } ?? 0
let processedView = ChatHistoryView(originalView: view, filteredEntries: filteredEntries, associatedData: associatedData, lastHeaderId: lastHeaderId, id: id, locationInput: update.2, ignoreMessagesInTimestampRange: update.3)
let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages, dynamicAdMessages.1))
let previousValueAndVersion = previousView.swap((processedView, update.1, selectedMessages, allAdMessages.version))
let previous = previousValueAndVersion?.0
let previousSelectedMessages = previousValueAndVersion?.2
@ -1323,7 +1323,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
var disableAnimations = false
var forceSynchronous = false
if let previousValueAndVersion = previousValueAndVersion, dynamicAdMessages.1 != previousValueAndVersion.3 {
if let previousValueAndVersion = previousValueAndVersion, allAdMessages.version != previousValueAndVersion.3 {
reason = ChatHistoryViewTransitionReason.Reload
disableAnimations = true
forceSynchronous = true
@ -1688,6 +1688,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
self.preloadAdPeerDisposable.dispose()
self.refreshDisplayedItemRangeTimer?.invalidate()
self.genericReactionEffectDisposable?.dispose()
self.adMessagesDisposable?.dispose()
}
private func attemptReadingReactions() {
@ -1895,7 +1896,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
let initialMessage = self.pendingDynamicAdMessages.removeFirst()
let message = Message(
stableId: UInt32.max - 1 - UInt32(self.nextPendingDynamicMessageId),
stableVersion: 1,
stableVersion: initialMessage.stableVersion,
id: MessageId(peerId: initialMessage.id.peerId, namespace: initialMessage.id.namespace, id: self.nextPendingDynamicMessageId),
globallyUniqueId: nil,
groupingKey: nil,
@ -1908,7 +1909,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
localTags: initialMessage.localTags,
forwardInfo: initialMessage.forwardInfo,
author: initialMessage.author,
text: initialMessage.text,
text: /*"\(initialMessage.adAttribute!.opaqueId.hashValue)" + */initialMessage.text,
attributes: initialMessage.attributes,
media: initialMessage.media,
peers: initialMessage.peers,
@ -1919,12 +1920,26 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
)
self.nextPendingDynamicMessageId += 1
var dynamicAdMessages = self.dynamicAdMessages
dynamicAdMessages.0.append(message)
dynamicAdMessages.1 += 1
self.dynamicAdMessages = dynamicAdMessages
var allAdMessages = self.allAdMessages
if allAdMessages.fixed?.adAttribute?.opaqueId == message.adAttribute?.opaqueId {
allAdMessages.fixed = self.pendingDynamicAdMessages.first?.withUpdatedStableVersion(stableVersion: UInt32(self.nextPendingDynamicMessageId))
}
allAdMessages.opportunistic.append(message)
allAdMessages.version += 1
self.allAdMessages = allAdMessages
}
}
//TODO:loc mark all ads as seen
}
func markAdAsSeen(opaqueId: Data) {
for i in 0 ..< self.pendingDynamicAdMessages.count {
if let pendingAttribute = self.pendingDynamicAdMessages[i].adAttribute, pendingAttribute.opaqueId == opaqueId {
self.pendingDynamicAdMessages.remove(at: i)
break
}
}
self.adMessagesContext?.markAsSeen(opaqueId: opaqueId)
}
private func processDisplayedItemRangeChanged(displayedRange: ListViewDisplayedItemRange, transactionState: ChatHistoryTransactionOpaqueState) {
@ -1952,10 +1967,13 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
var messageIdsWithUnseenReactions: [MessageId] = []
var messageIdsWithInactiveExtendedMedia = Set<MessageId>()
var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = []
var allVisibleAnchorMessageIds: [MessageId] = []
var allVisibleAnchorMessageIds: [(MessageId, Int)] = []
var visibleAdOpaqueIds: [Data] = []
if indexRange.0 <= indexRange.1 {
for i in (indexRange.0 ... indexRange.1) {
let nodeIndex = historyView.filteredEntries.count - 1 - i
switch historyView.filteredEntries[i] {
case let .MessageEntry(message, _, _, _, _, _):
var hasUnconsumedMention = false
@ -1985,6 +2003,10 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
contentRequiredValidation = true
} else if let attribute = attribute as? ReactionsMessageAttribute, attribute.hasUnseen {
hasUnseenReactions = true
} else if let attribute = attribute as? AdMessageAttribute {
if message.stableId != ChatHistoryListNode.fixedAdMessageStableId {
visibleAdOpaqueIds.append(attribute.opaqueId)
}
}
}
for media in message.media {
@ -2044,7 +2066,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
topVisibleMessageRange = ChatTopVisibleMessageRange(lowerBound: message.index, upperBound: message.index, isLast: i == historyView.filteredEntries.count - 1)
}
if message.id.namespace == Namespaces.Message.Cloud, self.remainingDynamicAdMessageInterval != nil {
allVisibleAnchorMessageIds.append(message.id)
allVisibleAnchorMessageIds.append((message.id, nodeIndex))
}
case let .MessageGroupEntry(_, messages, _):
for (message, _, _, _, _) in messages {
@ -2099,7 +2121,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
}
if let message = messages.first {
if message.0.id.namespace == Namespaces.Message.Cloud, self.remainingDynamicAdMessageInterval != nil {
allVisibleAnchorMessageIds.append(message.0.id)
allVisibleAnchorMessageIds.append((message.0.id, nodeIndex))
}
}
default:
@ -2242,6 +2264,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
if !messageIdsWithInactiveExtendedMedia.isEmpty {
self.extendedMediaProcessingManager.update(messageIdsWithInactiveExtendedMedia)
}
if !visibleAdOpaqueIds.isEmpty {
for opaqueId in visibleAdOpaqueIds {
self.markAdAsSeen(opaqueId: opaqueId)
}
}
self.currentEarlierPrefetchMessages = toEarlierMediaMessages
self.currentLaterPrefetchMessages = toLaterMediaMessages
@ -2275,15 +2302,23 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
if let visible = displayedRange.visibleRange {
let indexRange = (historyView.filteredEntries.count - 1 - visible.lastIndex, historyView.filteredEntries.count - 1 - visible.firstIndex)
if indexRange.0 <= indexRange.1 {
for messageId in allVisibleAnchorMessageIds {
for (messageId, nodeIndex) in allVisibleAnchorMessageIds {
guard let itemNode = self.itemNodeAtIndex(nodeIndex) else {
continue
}
//TODO:loc optimize eviction
if self.seenMessageIds.insert(messageId).inserted, let remainingDynamicAdMessageIntervalValue = self.remainingDynamicAdMessageInterval {
let pendingInterval = remainingDynamicAdMessageIntervalValue - 1
if pendingInterval <= 0 {
if self.seenMessageIds.insert(messageId).inserted, let remainingDynamicAdMessageIntervalValue = self.remainingDynamicAdMessageInterval, let remainingDynamicAdMessageDistanceValue = self.remainingDynamicAdMessageDistance {
let itemHeight = itemNode.bounds.height
let remainingDynamicAdMessageInterval = remainingDynamicAdMessageIntervalValue - 1
let remainingDynamicAdMessageDistance = remainingDynamicAdMessageDistanceValue - itemHeight
if remainingDynamicAdMessageInterval <= 0 && remainingDynamicAdMessageDistance <= 0.0 {
self.remainingDynamicAdMessageInterval = self.pendingDynamicAdMessageInterval
self.remainingDynamicAdMessageDistance = self.bounds.height
self.maybeInsertPendingAdMessage(historyView: historyView, toLaterRange: toLaterRange, toEarlierRange: toEarlierRange)
} else {
self.remainingDynamicAdMessageInterval = pendingInterval
self.remainingDynamicAdMessageInterval = remainingDynamicAdMessageInterval
self.remainingDynamicAdMessageDistance = remainingDynamicAdMessageDistance
}
}
}

View File

@ -94,10 +94,6 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData)
if preloaded {
if tagMask == nil && view.entries.isEmpty {
print("")
}
return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id)
} else {
if view.isLoading {
@ -168,10 +164,6 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
}
}
if tagMask == nil && view.entries.isEmpty {
print("")
}
preloaded = true
return .HistoryView(view: view, type: .Initial(fadeIn: fadeIn), scrollPosition: scrollPosition, flashIndicators: false, originalScrollPosition: nil, initialData: ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData), id: location.id)
}

View File

@ -373,6 +373,7 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
let peerId: PeerId
let peer: Peer?
let messageReference: MessageReference?
let adMessageId: EngineMessage.Id?
let effectiveTimestamp: Int32
let presentationData: ChatPresentationData
let context: AccountContext
@ -382,6 +383,11 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
self.peerId = peerId
self.peer = peer
self.messageReference = messageReference
if message.adAttribute != nil {
self.adMessageId = message.id
} else {
self.adMessageId = nil
}
var effectiveTimestamp = message.timestamp
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) {
@ -412,7 +418,7 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
}
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
return ChatMessageAvatarHeaderNode(peerId: self.peerId, peer: self.peer, messageReference: self.messageReference, presentationData: self.presentationData, context: self.context, controllerInteraction: self.controllerInteraction, synchronousLoad: synchronousLoad)
return ChatMessageAvatarHeaderNode(peerId: self.peerId, peer: self.peer, messageReference: self.messageReference, adMessageId: self.adMessageId, presentationData: self.presentationData, context: self.context, controllerInteraction: self.controllerInteraction, synchronousLoad: synchronousLoad)
}
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) {
@ -435,6 +441,7 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
private let peerId: PeerId
private let messageReference: MessageReference?
private let peer: Peer?
private let adMessageId: EngineMessage.Id?
private let containerNode: ContextControllerSourceNode
private let avatarNode: AvatarNode
@ -459,10 +466,11 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
}
}
init(peerId: PeerId, peer: Peer?, messageReference: MessageReference?, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction, synchronousLoad: Bool) {
init(peerId: PeerId, peer: Peer?, messageReference: MessageReference?, adMessageId: EngineMessage.Id?, presentationData: ChatPresentationData, context: AccountContext, controllerInteraction: ChatControllerInteraction, synchronousLoad: Bool) {
self.peerId = peerId
self.peer = peer
self.messageReference = messageReference
self.adMessageId = adMessageId
self.presentationData = presentationData
self.context = context
self.controllerInteraction = controllerInteraction
@ -636,6 +644,9 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
if self.peerId.namespace == Namespaces.Peer.Empty, case let .message(_, id, _, _, _) = self.messageReference?.content {
self.controllerInteraction.displayMessageTooltip(id, self.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, self.avatarNode.frame)
} else if let peer = self.peer {
if let adMessageId = self.adMessageId {
self.controllerInteraction.activateAdAction(adMessageId)
} else {
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
self.controllerInteraction.openPeer(EnginePeer(peer), .chat(textInputState: nil, subject: nil, peekData: nil), self.messageReference, false)
} else {
@ -644,6 +655,7 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
}
}
}
}
private func updateVideoVisibility() {
let context = self.context

View File

@ -63,28 +63,8 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
}
self.contentNode.activateAction = { [weak self] in
if let strongSelf = self, let item = strongSelf.item {
if let adAttribute = item.message.adAttribute {
switch adAttribute.target {
case let .peer(id, messageId, startParam):
let navigationData: ChatControllerInteractionNavigateToPeer
if let bot = item.message.author as? TelegramUser, bot.botInfo != nil, let startParam = startParam {
navigationData = .withBotStartPayload(ChatControllerInitialBotStart(payload: startParam, behavior: .interactive))
} else {
var subject: ChatControllerSubject?
if let messageId = messageId {
subject = .message(id: .id(messageId), highlight: true, timecode: nil)
}
navigationData = .chat(textInputState: nil, subject: subject, peekData: nil)
}
let _ = (item.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: id))
|> deliverOnMainQueue).start(next: { peer in
if let peer = peer {
item.controllerInteraction.openPeer(peer, navigationData, nil, false)
}
})
case let .join(_, joinHash):
item.controllerInteraction.openJoinLink(joinHash)
}
if let _ = item.message.adAttribute {
item.controllerInteraction.activateAdAction(item.message.id)
} else {
var webPageContent: TelegramMediaWebpageLoadedContent?
for media in item.message.media {

View File

@ -540,6 +540,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _, _, _ in
}, activateAdAction: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -161,6 +161,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _, _, _ in
}, activateAdAction: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -154,6 +154,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _, _, _ in
}, activateAdAction: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -2599,6 +2599,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _, _, _ in
}, activateAdAction: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -1348,6 +1348,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
}, openLargeEmojiInfo: { _, _, _ in
}, openJoinLink: { _ in
}, openWebView: { _, _, _, _ in
}, activateAdAction: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {
}, dismissTextInput: {

View File

@ -626,7 +626,7 @@ tgcalls::VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(tgcalls:
}
std::shared_ptr<tgcalls::VideoCaptureInterface> interface = strongSelf->_interface;
if (false && requestClone) {
/*if (false && requestClone) {
VideoSampleBufferView *remoteRenderer = [[VideoSampleBufferView alloc] initWithFrame:CGRectZero];
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
@ -643,7 +643,7 @@ tgcalls::VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(tgcalls:
}
completion(remoteRenderer, cloneRenderer);
} else if ([VideoMetalView isSupported]) {
} else */if ([VideoMetalView isSupported]) {
VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectZero];
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;

@ -1 +1 @@
Subproject commit c8f6a173253e88fc77ef4ceece919a786023108e
Subproject commit 07b225568fb596ba44d472c3fa413da2f8bd3f2e