mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Better history-ad integration
This commit is contained in:
parent
554cd0e6fe
commit
efe0566b79
@ -689,6 +689,10 @@ public final class Message {
|
|||||||
self.associatedThreadInfo = associatedThreadInfo
|
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 {
|
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)
|
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)
|
||||||
}
|
}
|
||||||
|
@ -4038,6 +4038,32 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
})], parseMarkdown: true), in: .window(.root), with: nil)
|
})], 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
|
}, requestMessageUpdate: { [weak self] id, scroll in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id, andScrollToItem: scroll)
|
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id, andScrollToItem: scroll)
|
||||||
@ -6554,13 +6580,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
var minOffsetForNavigation: CGFloat = 40.0
|
var minOffsetForNavigation: CGFloat = 40.0
|
||||||
strongSelf.chatDisplayNode.historyNode.enumerateItemNodes { itemNode in
|
strongSelf.chatDisplayNode.historyNode.enumerateItemNodes { itemNode in
|
||||||
if let itemNode = itemNode as? ChatMessageBubbleItemNode {
|
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
|
minOffsetForNavigation += itemNode.bounds.height
|
||||||
|
|
||||||
switch offset {
|
switch offset {
|
||||||
case let .known(offset):
|
case let .known(offset):
|
||||||
if offset <= 50.0 {
|
if offset <= 50.0 {
|
||||||
strongSelf.chatDisplayNode.historyNode.adSeenProcessingManager.add([message.id])
|
strongSelf.chatDisplayNode.historyNode.markAdAsSeen(opaqueId: adAttribute.opaqueId)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
|
@ -141,6 +141,7 @@ public final class ChatControllerInteraction {
|
|||||||
let openLargeEmojiInfo: (String, String?, TelegramMediaFile) -> Void
|
let openLargeEmojiInfo: (String, String?, TelegramMediaFile) -> Void
|
||||||
let openJoinLink: (String) -> Void
|
let openJoinLink: (String) -> Void
|
||||||
let openWebView: (String, String, Bool, Bool) -> Void
|
let openWebView: (String, String, Bool, Bool) -> Void
|
||||||
|
let activateAdAction: (EngineMessage.Id) -> Void
|
||||||
|
|
||||||
let requestMessageUpdate: (MessageId, Bool) -> Void
|
let requestMessageUpdate: (MessageId, Bool) -> Void
|
||||||
let cancelInteractiveKeyboardGestures: () -> Void
|
let cancelInteractiveKeyboardGestures: () -> Void
|
||||||
@ -248,6 +249,7 @@ public final class ChatControllerInteraction {
|
|||||||
openLargeEmojiInfo: @escaping (String, String?, TelegramMediaFile) -> Void,
|
openLargeEmojiInfo: @escaping (String, String?, TelegramMediaFile) -> Void,
|
||||||
openJoinLink: @escaping (String) -> Void,
|
openJoinLink: @escaping (String) -> Void,
|
||||||
openWebView: @escaping (String, String, Bool, Bool) -> Void,
|
openWebView: @escaping (String, String, Bool, Bool) -> Void,
|
||||||
|
activateAdAction: @escaping (EngineMessage.Id) -> Void,
|
||||||
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
|
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
|
||||||
cancelInteractiveKeyboardGestures: @escaping () -> Void,
|
cancelInteractiveKeyboardGestures: @escaping () -> Void,
|
||||||
dismissTextInput: @escaping () -> Void,
|
dismissTextInput: @escaping () -> Void,
|
||||||
@ -338,6 +340,7 @@ public final class ChatControllerInteraction {
|
|||||||
self.openLargeEmojiInfo = openLargeEmojiInfo
|
self.openLargeEmojiInfo = openLargeEmojiInfo
|
||||||
self.openJoinLink = openJoinLink
|
self.openJoinLink = openJoinLink
|
||||||
self.openWebView = openWebView
|
self.openWebView = openWebView
|
||||||
|
self.activateAdAction = activateAdAction
|
||||||
self.requestMessageUpdate = requestMessageUpdate
|
self.requestMessageUpdate = requestMessageUpdate
|
||||||
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
|
||||||
self.dismissTextInput = dismissTextInput
|
self.dismissTextInput = dismissTextInput
|
||||||
|
@ -25,7 +25,7 @@ func chatHistoryEntriesForView(
|
|||||||
customChannelDiscussionReadState: MessageId?,
|
customChannelDiscussionReadState: MessageId?,
|
||||||
customThreadOutgoingReadState: MessageId?,
|
customThreadOutgoingReadState: MessageId?,
|
||||||
cachedData: CachedPeerData?,
|
cachedData: CachedPeerData?,
|
||||||
adMessages: (interPostInterval: Int32?, messages: [Message]),
|
adMessage: Message?,
|
||||||
dynamicAdMessages: [Message]
|
dynamicAdMessages: [Message]
|
||||||
) -> [ChatHistoryEntry] {
|
) -> [ChatHistoryEntry] {
|
||||||
if historyAppearsCleared {
|
if historyAppearsCleared {
|
||||||
@ -339,36 +339,34 @@ func chatHistoryEntriesForView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if view.laterId == nil && !view.isLoading {
|
if view.laterId == nil && !view.isLoading {
|
||||||
if !entries.isEmpty, case let .MessageEntry(lastMessage, _, _, _, _, _) = entries[entries.count - 1], !adMessages.messages.isEmpty, adMessages.interPostInterval == nil {
|
if !entries.isEmpty, case let .MessageEntry(lastMessage, _, _, _, _, _) = entries[entries.count - 1], let message = adMessage {
|
||||||
var nextAdMessageId: Int32 = 1
|
var nextAdMessageId: Int32 = 10000
|
||||||
if let message = adMessages.messages.first {
|
let updatedMessage = Message(
|
||||||
let updatedMessage = Message(
|
stableId: ChatHistoryListNode.fixedAdMessageStableId,
|
||||||
stableId: UInt32.max - 1 - UInt32(nextAdMessageId),
|
stableVersion: message.stableVersion,
|
||||||
stableVersion: message.stableVersion,
|
id: MessageId(peerId: message.id.peerId, namespace: message.id.namespace, id: nextAdMessageId),
|
||||||
id: MessageId(peerId: message.id.peerId, namespace: message.id.namespace, id: nextAdMessageId),
|
globallyUniqueId: nil,
|
||||||
globallyUniqueId: nil,
|
groupingKey: nil,
|
||||||
groupingKey: nil,
|
groupInfo: nil,
|
||||||
groupInfo: nil,
|
threadId: nil,
|
||||||
threadId: nil,
|
timestamp: lastMessage.timestamp,
|
||||||
timestamp: lastMessage.timestamp,
|
flags: message.flags,
|
||||||
flags: message.flags,
|
tags: message.tags,
|
||||||
tags: message.tags,
|
globalTags: message.globalTags,
|
||||||
globalTags: message.globalTags,
|
localTags: message.localTags,
|
||||||
localTags: message.localTags,
|
forwardInfo: message.forwardInfo,
|
||||||
forwardInfo: message.forwardInfo,
|
author: message.author,
|
||||||
author: message.author,
|
text: /*"\(message.adAttribute!.opaqueId.hashValue)" + */message.text,
|
||||||
text: message.text,
|
attributes: message.attributes,
|
||||||
attributes: message.attributes,
|
media: message.media,
|
||||||
media: message.media,
|
peers: message.peers,
|
||||||
peers: message.peers,
|
associatedMessages: message.associatedMessages,
|
||||||
associatedMessages: message.associatedMessages,
|
associatedMessageIds: message.associatedMessageIds,
|
||||||
associatedMessageIds: message.associatedMessageIds,
|
associatedMedia: message.associatedMedia,
|
||||||
associatedMedia: message.associatedMedia,
|
associatedThreadInfo: message.associatedThreadInfo
|
||||||
associatedThreadInfo: message.associatedThreadInfo
|
)
|
||||||
)
|
nextAdMessageId += 1
|
||||||
nextAdMessageId += 1
|
entries.append(.MessageEntry(updatedMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false)))
|
||||||
entries.append(.MessageEntry(updatedMessage, presentationData, false, nil, .none, ChatMessageEntryAttributes(rank: nil, isContact: false, contentTypeHint: .generic, updatingMedia: nil, isPlaying: false, isCentered: false)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if includeSearchEntry {
|
} else if includeSearchEntry {
|
||||||
|
@ -408,6 +408,8 @@ public enum ChatHistoryListSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
||||||
|
static let fixedAdMessageStableId: UInt32 = UInt32.max - 5000
|
||||||
|
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private let chatLocation: ChatLocation
|
private let chatLocation: ChatLocation
|
||||||
private let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
private let chatLocationContextHolder: Atomic<ChatLocationContextHolder?>
|
||||||
@ -495,7 +497,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
private let messageProcessingManager = ChatMessageThrottledProcessingManager()
|
private let messageProcessingManager = ChatMessageThrottledProcessingManager()
|
||||||
private let messageWithReactionsProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 4.0)
|
private let messageWithReactionsProcessingManager = ChatMessageThrottledProcessingManager(submitInterval: 4.0)
|
||||||
let adSeenProcessingManager = ChatMessageThrottledProcessingManager()
|
|
||||||
private let seenLiveLocationProcessingManager = ChatMessageThrottledProcessingManager()
|
private let seenLiveLocationProcessingManager = ChatMessageThrottledProcessingManager()
|
||||||
private let unsupportedMessageProcessingManager = ChatMessageThrottledProcessingManager()
|
private let unsupportedMessageProcessingManager = ChatMessageThrottledProcessingManager()
|
||||||
private let refreshMediaProcessingManager = ChatMessageThrottledProcessingManager()
|
private let refreshMediaProcessingManager = ChatMessageThrottledProcessingManager()
|
||||||
@ -606,18 +607,20 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
private var contentInsetAnimator: DisplayLinkAnimator?
|
private var contentInsetAnimator: DisplayLinkAnimator?
|
||||||
|
|
||||||
private let adMessagesContext: AdMessagesHistoryContext?
|
private let adMessagesContext: AdMessagesHistoryContext?
|
||||||
|
private var adMessagesDisposable: Disposable?
|
||||||
private var preloadAdPeerId: PeerId?
|
private var preloadAdPeerId: PeerId?
|
||||||
private let preloadAdPeerDisposable = MetaDisposable()
|
private let preloadAdPeerDisposable = MetaDisposable()
|
||||||
private var pendingDynamicAdMessages: [Message] = []
|
private var pendingDynamicAdMessages: [Message] = []
|
||||||
private var pendingDynamicAdMessageInterval: Int?
|
private var pendingDynamicAdMessageInterval: Int?
|
||||||
private var remainingDynamicAdMessageInterval: Int?
|
private var remainingDynamicAdMessageInterval: Int?
|
||||||
|
private var remainingDynamicAdMessageDistance: CGFloat?
|
||||||
private var nextPendingDynamicMessageId: Int32 = 1
|
private var nextPendingDynamicMessageId: Int32 = 1
|
||||||
private var dynamicAdMessages: ([Message], Int) = ([], 0) {
|
private var allAdMessages: (fixed: Message?, opportunistic: [Message], version: Int) = (nil, [], 0) {
|
||||||
didSet {
|
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 seenMessageIds = Set<MessageId>()
|
||||||
|
|
||||||
private var refreshDisplayedItemRangeTimer: SwiftSignalKit.Timer?
|
private var refreshDisplayedItemRangeTimer: SwiftSignalKit.Timer?
|
||||||
@ -686,35 +689,43 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
|
|
||||||
super.init()
|
super.init()
|
||||||
|
|
||||||
adMessages = adMessages
|
self.adMessagesDisposable = (adMessages
|
||||||
|> afterNext { [weak self] interPostInterval, messages in
|
|> deliverOnMainQueue).start(next: { [weak self] interPostInterval, messages in
|
||||||
Queue.mainQueue().async {
|
guard let self else {
|
||||||
guard let strongSelf = self else {
|
return
|
||||||
return
|
}
|
||||||
|
|
||||||
|
if let interPostInterval = 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
|
||||||
}
|
}
|
||||||
|
|
||||||
if let interPostInterval = interPostInterval {
|
self.allAdMessages = (messages.first, [], 0)
|
||||||
strongSelf.pendingDynamicAdMessages = messages
|
} else {
|
||||||
strongSelf.pendingDynamicAdMessageInterval = Int(interPostInterval)
|
var adPeerId: PeerId?
|
||||||
strongSelf.remainingDynamicAdMessageInterval = Int(interPostInterval)
|
adPeerId = messages.first?.author?.id
|
||||||
} else {
|
|
||||||
var adPeerId: PeerId?
|
if self.preloadAdPeerId != adPeerId {
|
||||||
adPeerId = messages.first?.author?.id
|
self.preloadAdPeerId = adPeerId
|
||||||
|
if let adPeerId = adPeerId {
|
||||||
if strongSelf.preloadAdPeerId != adPeerId {
|
let combinedDisposable = DisposableSet()
|
||||||
strongSelf.preloadAdPeerId = adPeerId
|
self.preloadAdPeerDisposable.set(combinedDisposable)
|
||||||
if let adPeerId = adPeerId {
|
combinedDisposable.add(self.context.account.viewTracker.polledChannel(peerId: adPeerId).start())
|
||||||
let combinedDisposable = DisposableSet()
|
combinedDisposable.add(self.context.account.addAdditionalPreloadHistoryPeerId(peerId: adPeerId))
|
||||||
strongSelf.preloadAdPeerDisposable.set(combinedDisposable)
|
} else {
|
||||||
combinedDisposable.add(strongSelf.context.account.viewTracker.polledChannel(peerId: adPeerId).start())
|
self.preloadAdPeerDisposable.set(nil)
|
||||||
combinedDisposable.add(strongSelf.context.account.addAdditionalPreloadHistoryPeerId(peerId: adPeerId))
|
|
||||||
} else {
|
|
||||||
strongSelf.preloadAdPeerDisposable.set(nil)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.allAdMessages = (messages.first, [], 0)
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
self.clipsToBounds = false
|
self.clipsToBounds = false
|
||||||
|
|
||||||
@ -737,16 +748,6 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
self.messageWithReactionsProcessingManager.process = { [weak context] messageIds in
|
self.messageWithReactionsProcessingManager.process = { [weak context] messageIds in
|
||||||
context?.account.viewTracker.updateReactionsForMessageIds(messageIds: messageIds)
|
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
|
self.seenLiveLocationProcessingManager.process = { [weak context] messageIds in
|
||||||
context?.account.viewTracker.updateSeenLiveLocationForMessageIds(messageIds: messageIds)
|
context?.account.viewTracker.updateSeenLiveLocationForMessageIds(messageIds: messageIds)
|
||||||
}
|
}
|
||||||
@ -1096,15 +1097,14 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
additionalAnimatedEmojiStickers,
|
additionalAnimatedEmojiStickers,
|
||||||
customChannelDiscussionReadState,
|
customChannelDiscussionReadState,
|
||||||
customThreadOutgoingReadState,
|
customThreadOutgoingReadState,
|
||||||
adMessages,
|
|
||||||
availableReactions,
|
availableReactions,
|
||||||
defaultReaction,
|
defaultReaction,
|
||||||
accountPeer,
|
accountPeer,
|
||||||
audioTranscriptionSuggestion,
|
audioTranscriptionSuggestion,
|
||||||
promises,
|
promises,
|
||||||
topicAuthorId,
|
topicAuthorId,
|
||||||
self.dynamicAdMessagesPromise.get()
|
self.allAdMessagesPromise.get()
|
||||||
).start(next: { [weak self] update, chatPresentationData, selectedMessages, updatingMedia, networkType, animatedEmojiStickers, additionalAnimatedEmojiStickers, customChannelDiscussionReadState, customThreadOutgoingReadState, adMessages, availableReactions, defaultReaction, accountPeer, suggestAudioTranscription, promises, topicAuthorId, dynamicAdMessages in
|
).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 (historyAppearsCleared, pendingUnpinnedAllMessages, pendingRemovedMessages, currentlyPlayingMessageIdAndType, scrollToMessageId) = promises
|
||||||
let currentlyPlayingMessageId = currentlyPlayingMessageIdAndType?.0
|
let currentlyPlayingMessageId = currentlyPlayingMessageIdAndType?.0
|
||||||
|
|
||||||
@ -1265,12 +1265,12 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
customChannelDiscussionReadState: customChannelDiscussionReadState,
|
customChannelDiscussionReadState: customChannelDiscussionReadState,
|
||||||
customThreadOutgoingReadState: customThreadOutgoingReadState,
|
customThreadOutgoingReadState: customThreadOutgoingReadState,
|
||||||
cachedData: data.cachedData,
|
cachedData: data.cachedData,
|
||||||
adMessages: adMessages,
|
adMessage: allAdMessages.fixed,
|
||||||
dynamicAdMessages: dynamicAdMessages.0
|
dynamicAdMessages: allAdMessages.opportunistic
|
||||||
)
|
)
|
||||||
let lastHeaderId = filteredEntries.last.flatMap { listMessageDateHeaderId(timestamp: $0.index.timestamp) } ?? 0
|
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 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 previous = previousValueAndVersion?.0
|
||||||
let previousSelectedMessages = previousValueAndVersion?.2
|
let previousSelectedMessages = previousValueAndVersion?.2
|
||||||
|
|
||||||
@ -1323,7 +1323,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
var disableAnimations = false
|
var disableAnimations = false
|
||||||
var forceSynchronous = false
|
var forceSynchronous = false
|
||||||
|
|
||||||
if let previousValueAndVersion = previousValueAndVersion, dynamicAdMessages.1 != previousValueAndVersion.3 {
|
if let previousValueAndVersion = previousValueAndVersion, allAdMessages.version != previousValueAndVersion.3 {
|
||||||
reason = ChatHistoryViewTransitionReason.Reload
|
reason = ChatHistoryViewTransitionReason.Reload
|
||||||
disableAnimations = true
|
disableAnimations = true
|
||||||
forceSynchronous = true
|
forceSynchronous = true
|
||||||
@ -1688,6 +1688,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
self.preloadAdPeerDisposable.dispose()
|
self.preloadAdPeerDisposable.dispose()
|
||||||
self.refreshDisplayedItemRangeTimer?.invalidate()
|
self.refreshDisplayedItemRangeTimer?.invalidate()
|
||||||
self.genericReactionEffectDisposable?.dispose()
|
self.genericReactionEffectDisposable?.dispose()
|
||||||
|
self.adMessagesDisposable?.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func attemptReadingReactions() {
|
private func attemptReadingReactions() {
|
||||||
@ -1895,7 +1896,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
let initialMessage = self.pendingDynamicAdMessages.removeFirst()
|
let initialMessage = self.pendingDynamicAdMessages.removeFirst()
|
||||||
let message = Message(
|
let message = Message(
|
||||||
stableId: UInt32.max - 1 - UInt32(self.nextPendingDynamicMessageId),
|
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),
|
id: MessageId(peerId: initialMessage.id.peerId, namespace: initialMessage.id.namespace, id: self.nextPendingDynamicMessageId),
|
||||||
globallyUniqueId: nil,
|
globallyUniqueId: nil,
|
||||||
groupingKey: nil,
|
groupingKey: nil,
|
||||||
@ -1908,7 +1909,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
localTags: initialMessage.localTags,
|
localTags: initialMessage.localTags,
|
||||||
forwardInfo: initialMessage.forwardInfo,
|
forwardInfo: initialMessage.forwardInfo,
|
||||||
author: initialMessage.author,
|
author: initialMessage.author,
|
||||||
text: initialMessage.text,
|
text: /*"\(initialMessage.adAttribute!.opaqueId.hashValue)" + */initialMessage.text,
|
||||||
attributes: initialMessage.attributes,
|
attributes: initialMessage.attributes,
|
||||||
media: initialMessage.media,
|
media: initialMessage.media,
|
||||||
peers: initialMessage.peers,
|
peers: initialMessage.peers,
|
||||||
@ -1919,12 +1920,26 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
)
|
)
|
||||||
self.nextPendingDynamicMessageId += 1
|
self.nextPendingDynamicMessageId += 1
|
||||||
|
|
||||||
var dynamicAdMessages = self.dynamicAdMessages
|
var allAdMessages = self.allAdMessages
|
||||||
dynamicAdMessages.0.append(message)
|
if allAdMessages.fixed?.adAttribute?.opaqueId == message.adAttribute?.opaqueId {
|
||||||
dynamicAdMessages.1 += 1
|
allAdMessages.fixed = self.pendingDynamicAdMessages.first?.withUpdatedStableVersion(stableVersion: UInt32(self.nextPendingDynamicMessageId))
|
||||||
self.dynamicAdMessages = dynamicAdMessages
|
}
|
||||||
|
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) {
|
private func processDisplayedItemRangeChanged(displayedRange: ListViewDisplayedItemRange, transactionState: ChatHistoryTransactionOpaqueState) {
|
||||||
@ -1952,10 +1967,13 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
var messageIdsWithUnseenReactions: [MessageId] = []
|
var messageIdsWithUnseenReactions: [MessageId] = []
|
||||||
var messageIdsWithInactiveExtendedMedia = Set<MessageId>()
|
var messageIdsWithInactiveExtendedMedia = Set<MessageId>()
|
||||||
var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = []
|
var downloadableResourceIds: [(messageId: MessageId, resourceId: String)] = []
|
||||||
var allVisibleAnchorMessageIds: [MessageId] = []
|
var allVisibleAnchorMessageIds: [(MessageId, Int)] = []
|
||||||
|
var visibleAdOpaqueIds: [Data] = []
|
||||||
|
|
||||||
if indexRange.0 <= indexRange.1 {
|
if indexRange.0 <= indexRange.1 {
|
||||||
for i in (indexRange.0 ... indexRange.1) {
|
for i in (indexRange.0 ... indexRange.1) {
|
||||||
|
let nodeIndex = historyView.filteredEntries.count - 1 - i
|
||||||
|
|
||||||
switch historyView.filteredEntries[i] {
|
switch historyView.filteredEntries[i] {
|
||||||
case let .MessageEntry(message, _, _, _, _, _):
|
case let .MessageEntry(message, _, _, _, _, _):
|
||||||
var hasUnconsumedMention = false
|
var hasUnconsumedMention = false
|
||||||
@ -1985,6 +2003,10 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
contentRequiredValidation = true
|
contentRequiredValidation = true
|
||||||
} else if let attribute = attribute as? ReactionsMessageAttribute, attribute.hasUnseen {
|
} else if let attribute = attribute as? ReactionsMessageAttribute, attribute.hasUnseen {
|
||||||
hasUnseenReactions = true
|
hasUnseenReactions = true
|
||||||
|
} else if let attribute = attribute as? AdMessageAttribute {
|
||||||
|
if message.stableId != ChatHistoryListNode.fixedAdMessageStableId {
|
||||||
|
visibleAdOpaqueIds.append(attribute.opaqueId)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for media in message.media {
|
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)
|
topVisibleMessageRange = ChatTopVisibleMessageRange(lowerBound: message.index, upperBound: message.index, isLast: i == historyView.filteredEntries.count - 1)
|
||||||
}
|
}
|
||||||
if message.id.namespace == Namespaces.Message.Cloud, self.remainingDynamicAdMessageInterval != nil {
|
if message.id.namespace == Namespaces.Message.Cloud, self.remainingDynamicAdMessageInterval != nil {
|
||||||
allVisibleAnchorMessageIds.append(message.id)
|
allVisibleAnchorMessageIds.append((message.id, nodeIndex))
|
||||||
}
|
}
|
||||||
case let .MessageGroupEntry(_, messages, _):
|
case let .MessageGroupEntry(_, messages, _):
|
||||||
for (message, _, _, _, _) in messages {
|
for (message, _, _, _, _) in messages {
|
||||||
@ -2099,7 +2121,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
}
|
}
|
||||||
if let message = messages.first {
|
if let message = messages.first {
|
||||||
if message.0.id.namespace == Namespaces.Message.Cloud, self.remainingDynamicAdMessageInterval != nil {
|
if message.0.id.namespace == Namespaces.Message.Cloud, self.remainingDynamicAdMessageInterval != nil {
|
||||||
allVisibleAnchorMessageIds.append(message.0.id)
|
allVisibleAnchorMessageIds.append((message.0.id, nodeIndex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -2242,6 +2264,11 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
if !messageIdsWithInactiveExtendedMedia.isEmpty {
|
if !messageIdsWithInactiveExtendedMedia.isEmpty {
|
||||||
self.extendedMediaProcessingManager.update(messageIdsWithInactiveExtendedMedia)
|
self.extendedMediaProcessingManager.update(messageIdsWithInactiveExtendedMedia)
|
||||||
}
|
}
|
||||||
|
if !visibleAdOpaqueIds.isEmpty {
|
||||||
|
for opaqueId in visibleAdOpaqueIds {
|
||||||
|
self.markAdAsSeen(opaqueId: opaqueId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.currentEarlierPrefetchMessages = toEarlierMediaMessages
|
self.currentEarlierPrefetchMessages = toEarlierMediaMessages
|
||||||
self.currentLaterPrefetchMessages = toLaterMediaMessages
|
self.currentLaterPrefetchMessages = toLaterMediaMessages
|
||||||
@ -2275,15 +2302,23 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode {
|
|||||||
if let visible = displayedRange.visibleRange {
|
if let visible = displayedRange.visibleRange {
|
||||||
let indexRange = (historyView.filteredEntries.count - 1 - visible.lastIndex, historyView.filteredEntries.count - 1 - visible.firstIndex)
|
let indexRange = (historyView.filteredEntries.count - 1 - visible.lastIndex, historyView.filteredEntries.count - 1 - visible.firstIndex)
|
||||||
if indexRange.0 <= indexRange.1 {
|
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
|
//TODO:loc optimize eviction
|
||||||
if self.seenMessageIds.insert(messageId).inserted, let remainingDynamicAdMessageIntervalValue = self.remainingDynamicAdMessageInterval {
|
if self.seenMessageIds.insert(messageId).inserted, let remainingDynamicAdMessageIntervalValue = self.remainingDynamicAdMessageInterval, let remainingDynamicAdMessageDistanceValue = self.remainingDynamicAdMessageDistance {
|
||||||
let pendingInterval = remainingDynamicAdMessageIntervalValue - 1
|
let itemHeight = itemNode.bounds.height
|
||||||
if pendingInterval <= 0 {
|
|
||||||
|
let remainingDynamicAdMessageInterval = remainingDynamicAdMessageIntervalValue - 1
|
||||||
|
let remainingDynamicAdMessageDistance = remainingDynamicAdMessageDistanceValue - itemHeight
|
||||||
|
if remainingDynamicAdMessageInterval <= 0 && remainingDynamicAdMessageDistance <= 0.0 {
|
||||||
self.remainingDynamicAdMessageInterval = self.pendingDynamicAdMessageInterval
|
self.remainingDynamicAdMessageInterval = self.pendingDynamicAdMessageInterval
|
||||||
|
self.remainingDynamicAdMessageDistance = self.bounds.height
|
||||||
self.maybeInsertPendingAdMessage(historyView: historyView, toLaterRange: toLaterRange, toEarlierRange: toEarlierRange)
|
self.maybeInsertPendingAdMessage(historyView: historyView, toLaterRange: toLaterRange, toEarlierRange: toEarlierRange)
|
||||||
} else {
|
} else {
|
||||||
self.remainingDynamicAdMessageInterval = pendingInterval
|
self.remainingDynamicAdMessageInterval = remainingDynamicAdMessageInterval
|
||||||
|
self.remainingDynamicAdMessageDistance = remainingDynamicAdMessageDistance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,11 +93,7 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
|
|||||||
|
|
||||||
let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData)
|
let combinedInitialData = ChatHistoryCombinedInitialData(initialData: initialData, buttonKeyboardMessage: view.topTaggedMessages.first, cachedData: cachedData, cachedDataMessages: cachedDataMessages, readStateData: readStateData)
|
||||||
|
|
||||||
if preloaded {
|
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)
|
return .HistoryView(view: view, type: .Generic(type: updateType), scrollPosition: nil, flashIndicators: false, originalScrollPosition: nil, initialData: combinedInitialData, id: location.id)
|
||||||
} else {
|
} else {
|
||||||
if view.isLoading {
|
if view.isLoading {
|
||||||
@ -168,10 +164,6 @@ func chatHistoryViewForLocation(_ location: ChatHistoryLocationInput, ignoreMess
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tagMask == nil && view.entries.isEmpty {
|
|
||||||
print("")
|
|
||||||
}
|
|
||||||
|
|
||||||
preloaded = true
|
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)
|
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)
|
||||||
}
|
}
|
||||||
|
@ -373,6 +373,7 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
|
|||||||
let peerId: PeerId
|
let peerId: PeerId
|
||||||
let peer: Peer?
|
let peer: Peer?
|
||||||
let messageReference: MessageReference?
|
let messageReference: MessageReference?
|
||||||
|
let adMessageId: EngineMessage.Id?
|
||||||
let effectiveTimestamp: Int32
|
let effectiveTimestamp: Int32
|
||||||
let presentationData: ChatPresentationData
|
let presentationData: ChatPresentationData
|
||||||
let context: AccountContext
|
let context: AccountContext
|
||||||
@ -382,6 +383,11 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
|
|||||||
self.peerId = peerId
|
self.peerId = peerId
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.messageReference = messageReference
|
self.messageReference = messageReference
|
||||||
|
if message.adAttribute != nil {
|
||||||
|
self.adMessageId = message.id
|
||||||
|
} else {
|
||||||
|
self.adMessageId = nil
|
||||||
|
}
|
||||||
|
|
||||||
var effectiveTimestamp = message.timestamp
|
var effectiveTimestamp = message.timestamp
|
||||||
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) {
|
if let forwardInfo = message.forwardInfo, forwardInfo.flags.contains(.isImported) {
|
||||||
@ -412,7 +418,7 @@ final class ChatMessageAvatarHeader: ListViewItemHeader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func node(synchronousLoad: Bool) -> ListViewItemHeaderNode {
|
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?) {
|
func updateNode(_ node: ListViewItemHeaderNode, previous: ListViewItemHeader?, next: ListViewItemHeader?) {
|
||||||
@ -435,6 +441,7 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
private let peerId: PeerId
|
private let peerId: PeerId
|
||||||
private let messageReference: MessageReference?
|
private let messageReference: MessageReference?
|
||||||
private let peer: Peer?
|
private let peer: Peer?
|
||||||
|
private let adMessageId: EngineMessage.Id?
|
||||||
|
|
||||||
private let containerNode: ContextControllerSourceNode
|
private let containerNode: ContextControllerSourceNode
|
||||||
private let avatarNode: AvatarNode
|
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.peerId = peerId
|
||||||
self.peer = peer
|
self.peer = peer
|
||||||
self.messageReference = messageReference
|
self.messageReference = messageReference
|
||||||
|
self.adMessageId = adMessageId
|
||||||
self.presentationData = presentationData
|
self.presentationData = presentationData
|
||||||
self.context = context
|
self.context = context
|
||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
@ -636,10 +644,14 @@ final class ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
|||||||
if self.peerId.namespace == Namespaces.Peer.Empty, case let .message(_, id, _, _, _) = self.messageReference?.content {
|
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)
|
self.controllerInteraction.displayMessageTooltip(id, self.presentationData.strings.Conversation_ForwardAuthorHiddenTooltip, self, self.avatarNode.frame)
|
||||||
} else if let peer = self.peer {
|
} else if let peer = self.peer {
|
||||||
if let channel = peer as? TelegramChannel, case .broadcast = channel.info {
|
if let adMessageId = self.adMessageId {
|
||||||
self.controllerInteraction.openPeer(EnginePeer(peer), .chat(textInputState: nil, subject: nil, peekData: nil), self.messageReference, false)
|
self.controllerInteraction.activateAdAction(adMessageId)
|
||||||
} else {
|
} else {
|
||||||
self.controllerInteraction.openPeer(EnginePeer(peer), .info, self.messageReference, false)
|
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 {
|
||||||
|
self.controllerInteraction.openPeer(EnginePeer(peer), .info, self.messageReference, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,28 +63,8 @@ final class ChatMessageWebpageBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
}
|
}
|
||||||
self.contentNode.activateAction = { [weak self] in
|
self.contentNode.activateAction = { [weak self] in
|
||||||
if let strongSelf = self, let item = strongSelf.item {
|
if let strongSelf = self, let item = strongSelf.item {
|
||||||
if let adAttribute = item.message.adAttribute {
|
if let _ = item.message.adAttribute {
|
||||||
switch adAttribute.target {
|
item.controllerInteraction.activateAdAction(item.message.id)
|
||||||
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)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
var webPageContent: TelegramMediaWebpageLoadedContent?
|
var webPageContent: TelegramMediaWebpageLoadedContent?
|
||||||
for media in item.message.media {
|
for media in item.message.media {
|
||||||
|
@ -540,6 +540,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, openLargeEmojiInfo: { _, _, _ in
|
}, openLargeEmojiInfo: { _, _, _ in
|
||||||
}, openJoinLink: { _ in
|
}, openJoinLink: { _ in
|
||||||
}, openWebView: { _, _, _, _ in
|
}, openWebView: { _, _, _, _ in
|
||||||
|
}, activateAdAction: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -161,6 +161,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
|
|||||||
}, openLargeEmojiInfo: { _, _, _ in
|
}, openLargeEmojiInfo: { _, _, _ in
|
||||||
}, openJoinLink: { _ in
|
}, openJoinLink: { _ in
|
||||||
}, openWebView: { _, _, _, _ in
|
}, openWebView: { _, _, _, _ in
|
||||||
|
}, activateAdAction: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -154,6 +154,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}, openLargeEmojiInfo: { _, _, _ in
|
}, openLargeEmojiInfo: { _, _, _ in
|
||||||
}, openJoinLink: { _ in
|
}, openJoinLink: { _ in
|
||||||
}, openWebView: { _, _, _, _ in
|
}, openWebView: { _, _, _, _ in
|
||||||
|
}, activateAdAction: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -2599,6 +2599,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate
|
|||||||
}, openLargeEmojiInfo: { _, _, _ in
|
}, openLargeEmojiInfo: { _, _, _ in
|
||||||
}, openJoinLink: { _ in
|
}, openJoinLink: { _ in
|
||||||
}, openWebView: { _, _, _, _ in
|
}, openWebView: { _, _, _, _ in
|
||||||
|
}, activateAdAction: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -1348,6 +1348,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}, openLargeEmojiInfo: { _, _, _ in
|
}, openLargeEmojiInfo: { _, _, _ in
|
||||||
}, openJoinLink: { _ in
|
}, openJoinLink: { _ in
|
||||||
}, openWebView: { _, _, _, _ in
|
}, openWebView: { _, _, _, _ in
|
||||||
|
}, activateAdAction: { _ in
|
||||||
}, requestMessageUpdate: { _, _ in
|
}, requestMessageUpdate: { _, _ in
|
||||||
}, cancelInteractiveKeyboardGestures: {
|
}, cancelInteractiveKeyboardGestures: {
|
||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
|
@ -626,7 +626,7 @@ tgcalls::VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(tgcalls:
|
|||||||
}
|
}
|
||||||
std::shared_ptr<tgcalls::VideoCaptureInterface> interface = strongSelf->_interface;
|
std::shared_ptr<tgcalls::VideoCaptureInterface> interface = strongSelf->_interface;
|
||||||
|
|
||||||
if (false && requestClone) {
|
/*if (false && requestClone) {
|
||||||
VideoSampleBufferView *remoteRenderer = [[VideoSampleBufferView alloc] initWithFrame:CGRectZero];
|
VideoSampleBufferView *remoteRenderer = [[VideoSampleBufferView alloc] initWithFrame:CGRectZero];
|
||||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
||||||
|
|
||||||
@ -643,7 +643,7 @@ tgcalls::VideoCaptureInterfaceObject *GetVideoCaptureAssumingSameThread(tgcalls:
|
|||||||
}
|
}
|
||||||
|
|
||||||
completion(remoteRenderer, cloneRenderer);
|
completion(remoteRenderer, cloneRenderer);
|
||||||
} else if ([VideoMetalView isSupported]) {
|
} else */if ([VideoMetalView isSupported]) {
|
||||||
VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectZero];
|
VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectZero];
|
||||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit c8f6a173253e88fc77ef4ceece919a786023108e
|
Subproject commit 07b225568fb596ba44d472c3fa413da2f8bd3f2e
|
Loading…
x
Reference in New Issue
Block a user