mirror of
https://github.com/TelegramMessenger/Telegram-iOS.git
synced 2026-07-06 03:33:41 +02:00
[WIP] Saved messages
This commit is contained in:
parent
624155ae99
commit
0ad61d8d63
71 changed files with 2079 additions and 1024 deletions
|
|
@ -423,7 +423,7 @@ public final class NavigateToChatControllerParams {
|
|||
case let .peer(peer):
|
||||
return peer.id
|
||||
case let .replyThread(message):
|
||||
return message.messageId.peerId
|
||||
return message.peerId
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -432,7 +432,7 @@ public final class NavigateToChatControllerParams {
|
|||
case .peer:
|
||||
return nil
|
||||
case let .replyThread(message):
|
||||
return Int64(message.messageId.id)
|
||||
return message.threadId
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ public enum PeerMessagesPlaylistLocation: Equatable, SharedMediaPlaylistLocation
|
|||
case let .peer(peerId):
|
||||
return .peer(peerId)
|
||||
case let .replyThread(replyThreaMessage):
|
||||
return .peer(replyThreaMessage.messageId.peerId)
|
||||
return .peer(replyThreaMessage.peerId)
|
||||
case let .feed(id):
|
||||
return .feed(id)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1345,7 +1345,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||
if let threadId = threadId {
|
||||
let source: ContextContentSource
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
messageId: MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
)), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
|
|
@ -1381,7 +1381,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
|
|||
}
|
||||
let source: ContextContentSource
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(context: strongSelf.context, chatLocation: .replyThread(message: ChatReplyThreadMessage(
|
||||
messageId: MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: peer.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
)), subject: nil, botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
source = .controller(ContextControllerContentSourceImpl(controller: chatController, sourceNode: node, navigationController: strongSelf.navigationController as? NavigationController))
|
||||
|
|
|
|||
|
|
@ -1539,9 +1539,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
let searchLocations: [SearchMessagesLocation]
|
||||
if let options = options {
|
||||
if case let .forum(peerId) = location {
|
||||
searchLocations = [.peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: nil, minDate: options.date?.0, maxDate: options.date?.1), .general(tags: tagMask, minDate: options.date?.0, maxDate: options.date?.1)]
|
||||
searchLocations = [.peer(peerId: peerId, fromId: nil, tags: tagMask, threadId: nil, minDate: options.date?.0, maxDate: options.date?.1), .general(tags: tagMask, minDate: options.date?.0, maxDate: options.date?.1)]
|
||||
} else if let (peerId, _, _) = options.peer {
|
||||
searchLocations = [.peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: nil, minDate: options.date?.0, maxDate: options.date?.1)]
|
||||
searchLocations = [.peer(peerId: peerId, fromId: nil, tags: tagMask, threadId: nil, minDate: options.date?.0, maxDate: options.date?.1)]
|
||||
} else {
|
||||
if case let .chatList(groupId) = location, case .archive = groupId {
|
||||
searchLocations = [.group(groupId: groupId._asGroup(), tags: tagMask, minDate: options.date?.0, maxDate: options.date?.1)]
|
||||
|
|
@ -1551,7 +1551,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode {
|
|||
}
|
||||
} else {
|
||||
if case let .forum(peerId) = location {
|
||||
searchLocations = [.peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: nil, minDate: nil, maxDate: nil), .general(tags: tagMask, minDate: nil, maxDate: nil)]
|
||||
searchLocations = [.peer(peerId: peerId, fromId: nil, tags: tagMask, threadId: nil, minDate: nil, maxDate: nil), .general(tags: tagMask, minDate: nil, maxDate: nil)]
|
||||
} else if case let .chatList(groupId) = location, case .archive = groupId {
|
||||
searchLocations = [.group(groupId: groupId._asGroup(), tags: tagMask, minDate: nil, maxDate: nil)]
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -124,13 +124,13 @@ final class ShimmerEffectNode: ASDisplayNode {
|
|||
}
|
||||
}
|
||||
|
||||
final class ChatListShimmerNode: ASDisplayNode {
|
||||
public final class ChatListShimmerNode: ASDisplayNode {
|
||||
private let backgroundColorNode: ASDisplayNode
|
||||
private let effectNode: ShimmerEffectNode
|
||||
private let maskNode: ASImageNode
|
||||
private var currentParams: (size: CGSize, presentationData: PresentationData)?
|
||||
|
||||
override init() {
|
||||
override public init() {
|
||||
self.backgroundColorNode = ASDisplayNode()
|
||||
self.effectNode = ShimmerEffectNode()
|
||||
self.maskNode = ASImageNode()
|
||||
|
|
@ -144,7 +144,7 @@ final class ChatListShimmerNode: ASDisplayNode {
|
|||
self.addSubnode(self.maskNode)
|
||||
}
|
||||
|
||||
func update(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, size: CGSize, isInlineMode: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) {
|
||||
public func update(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, size: CGSize, isInlineMode: Bool, presentationData: PresentationData, transition: ContainedViewLayoutTransition) {
|
||||
if self.currentParams?.size != size || self.currentParams?.presentationData !== presentationData {
|
||||
self.currentParams = (size, presentationData)
|
||||
|
||||
|
|
|
|||
|
|
@ -312,65 +312,35 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
case .savedMessagesChats:
|
||||
var isFirst = true
|
||||
|
||||
return account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 1000, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tagMask: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Set([Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal])), orderStatistics: [])
|
||||
|> map { view, _, _ -> ChatListNodeViewUpdate in
|
||||
let isLoading = view.isLoading
|
||||
if "".isEmpty {
|
||||
let viewKey: PostboxViewKey = .savedMessagesIndex(peerId: account.peerId)
|
||||
|
||||
var items: [EngineChatList.Item] = []
|
||||
|
||||
var topMessageByPeerId: [EnginePeer.Id: Message] = [:]
|
||||
if !isLoading {
|
||||
for entry in view.entries {
|
||||
guard let threadId = entry.message.threadId else {
|
||||
continue
|
||||
}
|
||||
let sourcePeerId = PeerId(threadId)
|
||||
|
||||
if let currentTopMessage = topMessageByPeerId[sourcePeerId] {
|
||||
if currentTopMessage.index < entry.index {
|
||||
topMessageByPeerId[sourcePeerId] = entry.message
|
||||
}
|
||||
} else {
|
||||
topMessageByPeerId[sourcePeerId] = entry.message
|
||||
}
|
||||
var isFirst = true
|
||||
return account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> ChatListNodeViewUpdate in
|
||||
guard let view = views.views[viewKey] as? MessageHistorySavedMessagesIndexView else {
|
||||
preconditionFailure()
|
||||
}
|
||||
for (_, message) in topMessageByPeerId.sorted(by: { $0.value.index > $1.value.index }) {
|
||||
guard let threadId = message.threadId else {
|
||||
|
||||
var items: [EngineChatList.Item] = []
|
||||
for item in view.items {
|
||||
guard let sourcePeer = item.peer else {
|
||||
continue
|
||||
}
|
||||
let sourceId = PeerId(threadId)
|
||||
var sourcePeer = message.peers[sourceId]
|
||||
if sourcePeer == nil, let forwardInfo = message.forwardInfo, let authorSignature = forwardInfo.authorSignature {
|
||||
sourcePeer = TelegramUser(
|
||||
id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(1)),
|
||||
accessHash: nil,
|
||||
firstName: authorSignature,
|
||||
lastName: nil,
|
||||
username: nil,
|
||||
phone: nil,
|
||||
photo: [],
|
||||
botInfo: nil,
|
||||
restrictionInfo: nil,
|
||||
flags: [],
|
||||
emojiStatus: nil,
|
||||
usernames: [],
|
||||
storiesHidden: nil,
|
||||
nameColor: nil,
|
||||
backgroundEmojiId: nil,
|
||||
profileColor: nil,
|
||||
profileBackgroundEmojiId: nil
|
||||
)
|
||||
|
||||
let sourceId = PeerId(item.id)
|
||||
|
||||
var messages: [EngineMessage] = []
|
||||
if let topMessage = item.topMessage {
|
||||
messages.append(EngineMessage(topMessage))
|
||||
}
|
||||
guard let sourcePeer else {
|
||||
continue
|
||||
}
|
||||
let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: message.index.id.namespace, id: message.index.id.id), timestamp: message.index.timestamp)
|
||||
|
||||
let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: item.index.id.namespace, id: item.index.id.id), timestamp: item.index.timestamp)
|
||||
|
||||
items.append(EngineChatList.Item(
|
||||
id: .chatList(sourceId),
|
||||
index: .chatList(ChatListIndex(pinningIndex: nil, messageIndex: mappedMessageIndex)),
|
||||
messages: [EngineMessage(message)],
|
||||
index: .chatList(ChatListIndex(pinningIndex: item.pinnedIndex.flatMap(UInt16.init), messageIndex: mappedMessageIndex)),
|
||||
messages: messages,
|
||||
readCounters: nil,
|
||||
isMuted: false,
|
||||
draft: nil,
|
||||
|
|
@ -387,25 +357,121 @@ func chatListViewForLocation(chatListLocation: ChatListControllerLocation, locat
|
|||
storyStats: nil
|
||||
))
|
||||
}
|
||||
|
||||
let list = EngineChatList(
|
||||
items: items.reversed(),
|
||||
groupItems: [],
|
||||
additionalItems: [],
|
||||
hasEarlier: false,
|
||||
hasLater: false,
|
||||
isLoading: view.isLoading
|
||||
)
|
||||
|
||||
let type: ViewUpdateType
|
||||
if isFirst {
|
||||
type = .Initial
|
||||
} else {
|
||||
type = .Generic
|
||||
}
|
||||
isFirst = false
|
||||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
} else {
|
||||
var isFirst = true
|
||||
|
||||
let list = EngineChatList(
|
||||
items: items.reversed(),
|
||||
groupItems: [],
|
||||
additionalItems: [],
|
||||
hasEarlier: false,
|
||||
hasLater: false,
|
||||
isLoading: isLoading
|
||||
)
|
||||
|
||||
let type: ViewUpdateType
|
||||
if isFirst {
|
||||
type = .Initial
|
||||
} else {
|
||||
type = .Generic
|
||||
return account.postbox.aroundMessageHistoryViewForLocation(.peer(peerId: account.peerId, threadId: nil), anchor: .upperBound, ignoreMessagesInTimestampRange: nil, count: 1000, fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: Set(), tagMask: nil, appendMessagesFromTheSameGroup: false, namespaces: .not(Set([Namespaces.Message.ScheduledCloud, Namespaces.Message.ScheduledLocal])), orderStatistics: [])
|
||||
|> map { view, _, _ -> ChatListNodeViewUpdate in
|
||||
let isLoading = view.isLoading
|
||||
|
||||
var items: [EngineChatList.Item] = []
|
||||
|
||||
var topMessageByPeerId: [EnginePeer.Id: Message] = [:]
|
||||
if !isLoading {
|
||||
for entry in view.entries {
|
||||
guard let threadId = entry.message.threadId else {
|
||||
continue
|
||||
}
|
||||
let sourcePeerId = PeerId(threadId)
|
||||
|
||||
if let currentTopMessage = topMessageByPeerId[sourcePeerId] {
|
||||
if currentTopMessage.index < entry.index {
|
||||
topMessageByPeerId[sourcePeerId] = entry.message
|
||||
}
|
||||
} else {
|
||||
topMessageByPeerId[sourcePeerId] = entry.message
|
||||
}
|
||||
}
|
||||
for (_, message) in topMessageByPeerId.sorted(by: { $0.value.index > $1.value.index }) {
|
||||
guard let threadId = message.threadId else {
|
||||
continue
|
||||
}
|
||||
let sourceId = PeerId(threadId)
|
||||
var sourcePeer = message.peers[sourceId]
|
||||
if sourcePeer == nil, let forwardInfo = message.forwardInfo, let authorSignature = forwardInfo.authorSignature {
|
||||
sourcePeer = TelegramUser(
|
||||
id: PeerId(namespace: Namespaces.Peer.Empty, id: PeerId.Id._internalFromInt64Value(1)),
|
||||
accessHash: nil,
|
||||
firstName: authorSignature,
|
||||
lastName: nil,
|
||||
username: nil,
|
||||
phone: nil,
|
||||
photo: [],
|
||||
botInfo: nil,
|
||||
restrictionInfo: nil,
|
||||
flags: [],
|
||||
emojiStatus: nil,
|
||||
usernames: [],
|
||||
storiesHidden: nil,
|
||||
nameColor: nil,
|
||||
backgroundEmojiId: nil,
|
||||
profileColor: nil,
|
||||
profileBackgroundEmojiId: nil
|
||||
)
|
||||
}
|
||||
guard let sourcePeer else {
|
||||
continue
|
||||
}
|
||||
let mappedMessageIndex = MessageIndex(id: MessageId(peerId: sourceId, namespace: message.index.id.namespace, id: message.index.id.id), timestamp: message.index.timestamp)
|
||||
items.append(EngineChatList.Item(
|
||||
id: .chatList(sourceId),
|
||||
index: .chatList(ChatListIndex(pinningIndex: nil, messageIndex: mappedMessageIndex)),
|
||||
messages: [EngineMessage(message)],
|
||||
readCounters: nil,
|
||||
isMuted: false,
|
||||
draft: nil,
|
||||
threadData: nil,
|
||||
renderedPeer: EngineRenderedPeer(peer: EnginePeer(sourcePeer)),
|
||||
presence: nil,
|
||||
hasUnseenMentions: false,
|
||||
hasUnseenReactions: false,
|
||||
forumTopicData: nil,
|
||||
topForumTopicItems: [],
|
||||
hasFailed: false,
|
||||
isContact: false,
|
||||
autoremoveTimeout: nil,
|
||||
storyStats: nil
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
let list = EngineChatList(
|
||||
items: items.reversed(),
|
||||
groupItems: [],
|
||||
additionalItems: [],
|
||||
hasEarlier: false,
|
||||
hasLater: false,
|
||||
isLoading: isLoading
|
||||
)
|
||||
|
||||
let type: ViewUpdateType
|
||||
if isFirst {
|
||||
type = .Initial
|
||||
} else {
|
||||
type = .Generic
|
||||
}
|
||||
isFirst = false
|
||||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
isFirst = false
|
||||
return ChatListNodeViewUpdate(list: list, type: type, scrollPosition: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public extension ChatLocation {
|
|||
case let .peer(peerId):
|
||||
return peerId
|
||||
case let .replyThread(replyThreadMessage):
|
||||
return replyThreadMessage.messageId.peerId
|
||||
return replyThreadMessage.peerId
|
||||
case .feed:
|
||||
return nil
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ public extension ChatLocation {
|
|||
case .peer:
|
||||
return nil
|
||||
case let .replyThread(replyThreadMessage):
|
||||
return Int64(replyThreadMessage.messageId.id)
|
||||
return replyThreadMessage.threadId
|
||||
case .feed:
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -869,14 +869,14 @@ public enum StoreMessageId {
|
|||
}
|
||||
}
|
||||
|
||||
public func makeMessageThreadId(_ messageId: MessageId) -> Int64 {
|
||||
return (Int64(messageId.namespace) << 32) | Int64(bitPattern: UInt64(UInt32(bitPattern: messageId.id)))
|
||||
}
|
||||
|
||||
public func makeThreadIdMessageId(peerId: PeerId, threadId: Int64) -> MessageId {
|
||||
let namespace = Int32((threadId >> 32) & 0x7fffffff)
|
||||
let id = Int32(bitPattern: UInt32(threadId & 0xffffffff))
|
||||
return MessageId(peerId: peerId, namespace: namespace, id: id)
|
||||
public struct MessageThreadKey: Hashable {
|
||||
public var peerId: PeerId
|
||||
public var threadId: Int64
|
||||
|
||||
public init(peerId: PeerId, threadId: Int64) {
|
||||
self.peerId = peerId
|
||||
self.threadId = threadId
|
||||
}
|
||||
}
|
||||
|
||||
public final class StoreMessage {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,189 @@
|
|||
import Foundation
|
||||
|
||||
final class MutableMessageHistorySavedMessagesIndexView: MutablePostboxView {
|
||||
final class Item {
|
||||
let id: Int64
|
||||
let peer: Peer?
|
||||
let pinnedIndex: Int?
|
||||
let index: MessageIndex
|
||||
let topMessage: Message?
|
||||
|
||||
init(
|
||||
id: Int64,
|
||||
peer: Peer?,
|
||||
pinnedIndex: Int?,
|
||||
index: MessageIndex,
|
||||
topMessage: Message?
|
||||
) {
|
||||
self.id = id
|
||||
self.peer = peer
|
||||
self.pinnedIndex = pinnedIndex
|
||||
self.index = index
|
||||
self.topMessage = topMessage
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate let peerId: PeerId
|
||||
fileprivate var peer: Peer?
|
||||
fileprivate var items: [Item] = []
|
||||
private var hole: ForumTopicListHolesEntry?
|
||||
fileprivate var isLoading: Bool = false
|
||||
|
||||
init(postbox: PostboxImpl, peerId: PeerId) {
|
||||
self.peerId = peerId
|
||||
|
||||
self.reload(postbox: postbox)
|
||||
}
|
||||
|
||||
private func reload(postbox: PostboxImpl) {
|
||||
self.items.removeAll()
|
||||
|
||||
self.peer = postbox.peerTable.get(self.peerId)
|
||||
|
||||
let validIndexBoundary = postbox.peerThreadCombinedStateTable.get(peerId: peerId)?.validIndexBoundary
|
||||
self.isLoading = validIndexBoundary == nil
|
||||
|
||||
if let validIndexBoundary = validIndexBoundary {
|
||||
if validIndexBoundary.messageId != 1 {
|
||||
self.hole = ForumTopicListHolesEntry(peerId: self.peerId, index: validIndexBoundary)
|
||||
} else {
|
||||
self.hole = nil
|
||||
}
|
||||
} else {
|
||||
self.hole = ForumTopicListHolesEntry(peerId: self.peerId, index: nil)
|
||||
}
|
||||
|
||||
if !self.isLoading {
|
||||
let pinnedThreadIds = postbox.messageHistoryThreadPinnedTable.get(peerId: self.peerId)
|
||||
|
||||
for item in postbox.messageHistoryThreadIndexTable.getAll(peerId: self.peerId) {
|
||||
var pinnedIndex: Int?
|
||||
if let index = pinnedThreadIds.firstIndex(of: item.threadId) {
|
||||
pinnedIndex = index
|
||||
}
|
||||
|
||||
self.items.append(Item(
|
||||
id: item.threadId,
|
||||
peer: postbox.peerTable.get(PeerId(item.threadId)),
|
||||
pinnedIndex: pinnedIndex,
|
||||
index: item.index,
|
||||
topMessage: postbox.getMessage(item.index.id)
|
||||
))
|
||||
}
|
||||
|
||||
self.items.sort(by: { lhs, rhs in
|
||||
if let lhsPinnedIndex = lhs.pinnedIndex, let rhsPinnedIndex = rhs.pinnedIndex {
|
||||
return lhsPinnedIndex < rhsPinnedIndex
|
||||
} else if (lhs.pinnedIndex == nil) != (rhs.pinnedIndex == nil) {
|
||||
if lhs.pinnedIndex != nil {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return lhs.index > rhs.index
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func replay(postbox: PostboxImpl, transaction: PostboxTransaction) -> Bool {
|
||||
var updated = false
|
||||
|
||||
if transaction.updatedMessageThreadPeerIds.contains(self.peerId) || transaction.updatedPinnedThreads.contains(self.peerId) || transaction.updatedPeerThreadCombinedStates.contains(self.peerId) || transaction.currentUpdatedMessageTagSummaries.contains(where: { $0.key.peerId == self.peerId }) || transaction.currentUpdatedMessageActionsSummaries.contains(where: { $0.key.peerId == self.peerId }) || transaction.currentUpdatedPeerChatListEmbeddedStates.contains(self.peerId) || transaction.currentUpdatedPeerNotificationSettings[self.peerId] != nil || transaction.updatedPinnedThreads.contains(self.peerId) {
|
||||
self.reload(postbox: postbox)
|
||||
updated = true
|
||||
}
|
||||
|
||||
return updated
|
||||
}
|
||||
|
||||
func topHole() -> ForumTopicListHolesEntry? {
|
||||
return self.hole
|
||||
}
|
||||
|
||||
func refreshDueToExternalTransaction(postbox: PostboxImpl) -> Bool {
|
||||
self.reload(postbox: postbox)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func immutableView() -> PostboxView {
|
||||
return MessageHistorySavedMessagesIndexView(self)
|
||||
}
|
||||
}
|
||||
|
||||
public final class EngineMessageHistorySavedMessagesThread {
|
||||
public final class Item: Equatable {
|
||||
public let id: Int64
|
||||
public let peer: Peer?
|
||||
public let pinnedIndex: Int?
|
||||
public let index: MessageIndex
|
||||
public let topMessage: Message?
|
||||
|
||||
public init(
|
||||
id: Int64,
|
||||
peer: Peer?,
|
||||
pinnedIndex: Int?,
|
||||
index: MessageIndex,
|
||||
topMessage: Message?
|
||||
) {
|
||||
self.id = id
|
||||
self.peer = peer
|
||||
self.pinnedIndex = pinnedIndex
|
||||
self.index = index
|
||||
self.topMessage = topMessage
|
||||
}
|
||||
|
||||
public static func ==(lhs: Item, rhs: Item) -> Bool {
|
||||
if lhs.id != rhs.id {
|
||||
return false
|
||||
}
|
||||
if !arePeersEqual(lhs.peer, rhs.peer) {
|
||||
return false
|
||||
}
|
||||
if lhs.pinnedIndex != rhs.pinnedIndex {
|
||||
return false
|
||||
}
|
||||
if lhs.index != rhs.index {
|
||||
return false
|
||||
}
|
||||
if let lhsMessage = lhs.topMessage, let rhsMessage = rhs.topMessage {
|
||||
if lhsMessage.index != rhsMessage.index {
|
||||
return false
|
||||
}
|
||||
if lhsMessage.stableVersion != rhsMessage.stableVersion {
|
||||
return false
|
||||
}
|
||||
} else if (lhs.topMessage == nil) != (rhs.topMessage == nil) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final class MessageHistorySavedMessagesIndexView: PostboxView {
|
||||
public let peer: Peer?
|
||||
public let items: [EngineMessageHistorySavedMessagesThread.Item]
|
||||
public let isLoading: Bool
|
||||
|
||||
init(_ view: MutableMessageHistorySavedMessagesIndexView) {
|
||||
self.peer = view.peer
|
||||
|
||||
var items: [EngineMessageHistorySavedMessagesThread.Item] = []
|
||||
for item in view.items {
|
||||
items.append(EngineMessageHistorySavedMessagesThread.Item(
|
||||
id: item.id,
|
||||
peer: item.peer,
|
||||
pinnedIndex: item.pinnedIndex,
|
||||
index: item.index,
|
||||
topMessage: item.topMessage
|
||||
))
|
||||
}
|
||||
self.items = items
|
||||
|
||||
self.isLoading = view.isLoading
|
||||
}
|
||||
}
|
||||
|
|
@ -119,13 +119,15 @@ class MessageHistoryThreadIndexTable: Table {
|
|||
}
|
||||
|
||||
private let reverseIndexTable: MessageHistoryThreadReverseIndexTable
|
||||
private let seedConfiguration: SeedConfiguration
|
||||
|
||||
private let sharedKey = ValueBoxKey(length: 8 + 4 + 8 + 4 + 4)
|
||||
|
||||
private var updatedInfoItems: [MessageHistoryThreadsTable.ItemId: UpdatedEntry] = [:]
|
||||
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, reverseIndexTable: MessageHistoryThreadReverseIndexTable, useCaches: Bool) {
|
||||
init(valueBox: ValueBox, table: ValueBoxTable, reverseIndexTable: MessageHistoryThreadReverseIndexTable, seedConfiguration: SeedConfiguration, useCaches: Bool) {
|
||||
self.reverseIndexTable = reverseIndexTable
|
||||
self.seedConfiguration = seedConfiguration
|
||||
|
||||
super.init(valueBox: valueBox, table: table, useCaches: useCaches)
|
||||
}
|
||||
|
|
@ -219,6 +221,13 @@ class MessageHistoryThreadIndexTable: Table {
|
|||
info = nil
|
||||
}
|
||||
}
|
||||
if info == nil {
|
||||
if let value = self.seedConfiguration.automaticThreadIndexInfo(itemId.peerId, itemId.threadId) {
|
||||
let encoder = PostboxEncoder()
|
||||
value.encode(encoder)
|
||||
info = encoder.makeReadBufferAndReset()
|
||||
}
|
||||
}
|
||||
|
||||
if let topIndex = topIndex, let info = info {
|
||||
if let previousIndex = previousIndex {
|
||||
|
|
|
|||
|
|
@ -1746,7 +1746,7 @@ final class PostboxImpl {
|
|||
self.messageHistoryThreadTagsTable = MessageHistoryThreadTagsTable(valueBox: self.valueBox, table: MessageHistoryThreadTagsTable.tableSpec(71), useCaches: useCaches, seedConfiguration: self.seedConfiguration, summaryTable: self.messageHistoryTagsSummaryTable)
|
||||
self.messageHistoryThreadHoleIndexTable = MessageHistoryThreadHoleIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadHoleIndexTable.tableSpec(63), useCaches: useCaches, metadataTable: self.messageHistoryMetadataTable, seedConfiguration: self.seedConfiguration)
|
||||
self.messageHistoryThreadReverseIndexTable = MessageHistoryThreadReverseIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadReverseIndexTable.tableSpec(72), useCaches: useCaches)
|
||||
self.messageHistoryThreadIndexTable = MessageHistoryThreadIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadIndexTable.tableSpec(73), reverseIndexTable: self.messageHistoryThreadReverseIndexTable, useCaches: useCaches)
|
||||
self.messageHistoryThreadIndexTable = MessageHistoryThreadIndexTable(valueBox: self.valueBox, table: MessageHistoryThreadIndexTable.tableSpec(73), reverseIndexTable: self.messageHistoryThreadReverseIndexTable, seedConfiguration: seedConfiguration, useCaches: useCaches)
|
||||
self.messageHistoryThreadPinnedTable = MessageHistoryThreadPinnedTable(valueBox: self.valueBox, table: MessageHistoryThreadPinnedTable.tableSpec(76), useCaches: useCaches)
|
||||
self.globalMessageHistoryTagsTable = GlobalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(39), useCaches: useCaches)
|
||||
self.localMessageHistoryTagsTable = LocalMessageHistoryTagsTable(valueBox: self.valueBox, table: GlobalMessageHistoryTagsTable.tableSpec(52), useCaches: useCaches)
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ public final class SeedConfiguration {
|
|||
public let decodeAutoremoveTimeout: (CachedPeerData) -> Int32?
|
||||
public let decodeDisplayPeerAsRegularChat: (CachedPeerData) -> Bool
|
||||
public let isPeerUpgradeMessage: (Message) -> Bool
|
||||
public let automaticThreadIndexInfo: (PeerId, Int64) -> StoredMessageHistoryThreadInfo?
|
||||
|
||||
public init(
|
||||
globalMessageIdsPeerIdNamespaces: Set<GlobalMessageIdsNamespace>,
|
||||
|
|
@ -105,7 +106,8 @@ public final class SeedConfiguration {
|
|||
decodeMessageThreadInfo: @escaping (CodableEntry) -> Message.AssociatedThreadInfo?,
|
||||
decodeAutoremoveTimeout: @escaping (CachedPeerData) -> Int32?,
|
||||
decodeDisplayPeerAsRegularChat: @escaping (CachedPeerData) -> Bool,
|
||||
isPeerUpgradeMessage: @escaping (Message) -> Bool
|
||||
isPeerUpgradeMessage: @escaping (Message) -> Bool,
|
||||
automaticThreadIndexInfo: @escaping (PeerId, Int64) -> StoredMessageHistoryThreadInfo?
|
||||
) {
|
||||
self.globalMessageIdsPeerIdNamespaces = globalMessageIdsPeerIdNamespaces
|
||||
self.initializeChatListWithHole = initializeChatListWithHole
|
||||
|
|
@ -129,5 +131,6 @@ public final class SeedConfiguration {
|
|||
self.decodeAutoremoveTimeout = decodeAutoremoveTimeout
|
||||
self.decodeDisplayPeerAsRegularChat = decodeDisplayPeerAsRegularChat
|
||||
self.isPeerUpgradeMessage = isPeerUpgradeMessage
|
||||
self.automaticThreadIndexInfo = automaticThreadIndexInfo
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -453,6 +453,10 @@ final class ViewTracker {
|
|||
if let hole = view.topHole() {
|
||||
firstHoles.insert(hole)
|
||||
}
|
||||
} else if case .savedMessagesIndex = key, let view = view as? MutableMessageHistorySavedMessagesIndexView {
|
||||
if let hole = view.topHole() {
|
||||
firstHoles.insert(hole)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ public enum PostboxViewKey: Hashable {
|
|||
case storyExpirationTimeItems
|
||||
case peerStoryStats(peerIds: Set<PeerId>)
|
||||
case story(id: StoryId)
|
||||
case savedMessagesIndex(peerId: PeerId)
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
switch self {
|
||||
|
|
@ -153,6 +154,8 @@ public enum PostboxViewKey: Hashable {
|
|||
hasher.combine(peerIds)
|
||||
case let .story(id):
|
||||
hasher.combine(id)
|
||||
case let .savedMessagesIndex(peerId):
|
||||
hasher.combine(peerId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -428,6 +431,12 @@ public enum PostboxViewKey: Hashable {
|
|||
} else {
|
||||
return false
|
||||
}
|
||||
case let .savedMessagesIndex(peerId):
|
||||
if case .savedMessagesIndex(peerId) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -524,5 +533,7 @@ func postboxViewForKey(postbox: PostboxImpl, key: PostboxViewKey) -> MutablePost
|
|||
return MutablePeerStoryStatsView(postbox: postbox, peerIds: peerIds)
|
||||
case let .story(id):
|
||||
return MutableStoryView(postbox: postbox, id: id)
|
||||
case let .savedMessagesIndex(peerId):
|
||||
return MutableMessageHistorySavedMessagesIndexView(postbox: postbox, peerId: peerId)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ public func searchPeerMembers(context: AccountContext, peerId: EnginePeer.Id, ch
|
|||
disposable.dispose()
|
||||
}
|
||||
case let .replyThread(replyThreadMessage):
|
||||
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: replyThreadMessage.messageId, searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in
|
||||
let (disposable, _) = context.peerChannelMemberCategoriesContextsManager.mentions(engine: context.engine, postbox: context.account.postbox, network: context.account.network, accountPeerId: context.account.peerId, peerId: peerId, threadMessageId: EngineMessage.Id(peerId: replyThreadMessage.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: replyThreadMessage.threadId)), searchQuery: normalizedQuery.isEmpty ? nil : normalizedQuery, updated: { state in
|
||||
if case .ready = state.loadingState {
|
||||
subscriber.putNext((state.list.compactMap { participant in
|
||||
if participant.peer.isDeleted {
|
||||
|
|
|
|||
|
|
@ -472,7 +472,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[340088945] = { return Api.MediaArea.parse_mediaAreaSuggestedReaction($0) }
|
||||
dict[-1098720356] = { return Api.MediaArea.parse_mediaAreaVenue($0) }
|
||||
dict[64088654] = { return Api.MediaAreaCoordinates.parse_mediaAreaCoordinates($0) }
|
||||
dict[940666592] = { return Api.Message.parse_message($0) }
|
||||
dict[1992213009] = { return Api.Message.parse_message($0) }
|
||||
dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) }
|
||||
dict[721967202] = { return Api.Message.parse_messageService($0) }
|
||||
dict[-988359047] = { return Api.MessageAction.parse_messageActionBotAllowed($0) }
|
||||
|
|
@ -748,6 +748,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-1054465340] = { return Api.RichText.parse_textUnderline($0) }
|
||||
dict[1009288385] = { return Api.RichText.parse_textUrl($0) }
|
||||
dict[289586518] = { return Api.SavedContact.parse_savedPhoneContact($0) }
|
||||
dict[-1115174036] = { return Api.SavedDialog.parse_savedDialog($0) }
|
||||
dict[-911191137] = { return Api.SearchResultsCalendarPeriod.parse_searchResultsCalendarPeriod($0) }
|
||||
dict[2137295719] = { return Api.SearchResultsPosition.parse_searchResultPosition($0) }
|
||||
dict[871426631] = { return Api.SecureCredentialsEncrypted.parse_secureCredentialsEncrypted($0) }
|
||||
|
|
@ -939,6 +940,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[1538885128] = { return Api.Update.parse_updatePinnedChannelMessages($0) }
|
||||
dict[-99664734] = { return Api.Update.parse_updatePinnedDialogs($0) }
|
||||
dict[-309990731] = { return Api.Update.parse_updatePinnedMessages($0) }
|
||||
dict[1751942566] = { return Api.Update.parse_updatePinnedSavedDialogs($0) }
|
||||
dict[-298113238] = { return Api.Update.parse_updatePrivacy($0) }
|
||||
dict[861169551] = { return Api.Update.parse_updatePtsChanged($0) }
|
||||
dict[-693004986] = { return Api.Update.parse_updateReadChannelDiscussionInbox($0) }
|
||||
|
|
@ -954,6 +956,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[821314523] = { return Api.Update.parse_updateRecentEmojiStatuses($0) }
|
||||
dict[1870160884] = { return Api.Update.parse_updateRecentReactions($0) }
|
||||
dict[-1706939360] = { return Api.Update.parse_updateRecentStickers($0) }
|
||||
dict[-1364222348] = { return Api.Update.parse_updateSavedDialogPinned($0) }
|
||||
dict[-1821035490] = { return Api.Update.parse_updateSavedGifs($0) }
|
||||
dict[1960361625] = { return Api.Update.parse_updateSavedRingtones($0) }
|
||||
dict[2103604867] = { return Api.Update.parse_updateSentStoryReaction($0) }
|
||||
|
|
@ -1166,6 +1169,9 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
|||
dict[-1334846497] = { return Api.messages.Reactions.parse_reactionsNotModified($0) }
|
||||
dict[-1999405994] = { return Api.messages.RecentStickers.parse_recentStickers($0) }
|
||||
dict[186120336] = { return Api.messages.RecentStickers.parse_recentStickersNotModified($0) }
|
||||
dict[-130358751] = { return Api.messages.SavedDialogs.parse_savedDialogs($0) }
|
||||
dict[-1071681560] = { return Api.messages.SavedDialogs.parse_savedDialogsNotModified($0) }
|
||||
dict[1153080793] = { return Api.messages.SavedDialogs.parse_savedDialogsSlice($0) }
|
||||
dict[-2069878259] = { return Api.messages.SavedGifs.parse_savedGifs($0) }
|
||||
dict[-402498398] = { return Api.messages.SavedGifs.parse_savedGifsNotModified($0) }
|
||||
dict[-398136321] = { return Api.messages.SearchCounter.parse_searchCounter($0) }
|
||||
|
|
@ -1263,7 +1269,7 @@ public extension Api {
|
|||
return parser(reader)
|
||||
}
|
||||
else {
|
||||
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
|
||||
telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -1745,6 +1751,8 @@ public extension Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SavedContact:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SavedDialog:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SearchResultsCalendarPeriod:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.SearchResultsPosition:
|
||||
|
|
@ -2061,6 +2069,8 @@ public extension Api {
|
|||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.RecentStickers:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.SavedDialogs:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.SavedGifs:
|
||||
_1.serialize(buffer, boxed)
|
||||
case let _1 as Api.messages.SearchCounter:
|
||||
|
|
|
|||
|
|
@ -424,20 +424,21 @@ public extension Api {
|
|||
}
|
||||
public extension Api {
|
||||
indirect enum Message: TypeConstructorDescription {
|
||||
case message(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?)
|
||||
case message(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, savedPeerId: Api.Peer?, fwdFrom: Api.MessageFwdHeader?, viaBotId: Int64?, replyTo: Api.MessageReplyHeader?, date: Int32, message: String, media: Api.MessageMedia?, replyMarkup: Api.ReplyMarkup?, entities: [Api.MessageEntity]?, views: Int32?, forwards: Int32?, replies: Api.MessageReplies?, editDate: Int32?, postAuthor: String?, groupedId: Int64?, reactions: Api.MessageReactions?, restrictionReason: [Api.RestrictionReason]?, ttlPeriod: Int32?)
|
||||
case messageEmpty(flags: Int32, id: Int32, peerId: Api.Peer?)
|
||||
case messageService(flags: Int32, id: Int32, fromId: Api.Peer?, peerId: Api.Peer, replyTo: Api.MessageReplyHeader?, date: Int32, action: Api.MessageAction, ttlPeriod: Int32?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .message(let flags, let id, let fromId, let peerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod):
|
||||
case .message(let flags, let id, let fromId, let peerId, let savedPeerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod):
|
||||
if boxed {
|
||||
buffer.appendInt32(940666592)
|
||||
buffer.appendInt32(1992213009)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(id, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 8) != 0 {fromId!.serialize(buffer, true)}
|
||||
peerId.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 28) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {fwdFrom!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 11) != 0 {serializeInt64(viaBotId!, buffer: buffer, boxed: false)}
|
||||
if Int(flags) & Int(1 << 3) != 0 {replyTo!.serialize(buffer, true)}
|
||||
|
|
@ -490,8 +491,8 @@ public extension Api {
|
|||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .message(let flags, let id, let fromId, let peerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod):
|
||||
return ("message", [("flags", flags as Any), ("id", id as Any), ("fromId", fromId as Any), ("peerId", peerId as Any), ("fwdFrom", fwdFrom as Any), ("viaBotId", viaBotId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("message", message as Any), ("media", media as Any), ("replyMarkup", replyMarkup as Any), ("entities", entities as Any), ("views", views as Any), ("forwards", forwards as Any), ("replies", replies as Any), ("editDate", editDate as Any), ("postAuthor", postAuthor as Any), ("groupedId", groupedId as Any), ("reactions", reactions as Any), ("restrictionReason", restrictionReason as Any), ("ttlPeriod", ttlPeriod as Any)])
|
||||
case .message(let flags, let id, let fromId, let peerId, let savedPeerId, let fwdFrom, let viaBotId, let replyTo, let date, let message, let media, let replyMarkup, let entities, let views, let forwards, let replies, let editDate, let postAuthor, let groupedId, let reactions, let restrictionReason, let ttlPeriod):
|
||||
return ("message", [("flags", flags as Any), ("id", id as Any), ("fromId", fromId as Any), ("peerId", peerId as Any), ("savedPeerId", savedPeerId as Any), ("fwdFrom", fwdFrom as Any), ("viaBotId", viaBotId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("message", message as Any), ("media", media as Any), ("replyMarkup", replyMarkup as Any), ("entities", entities as Any), ("views", views as Any), ("forwards", forwards as Any), ("replies", replies as Any), ("editDate", editDate as Any), ("postAuthor", postAuthor as Any), ("groupedId", groupedId as Any), ("reactions", reactions as Any), ("restrictionReason", restrictionReason as Any), ("ttlPeriod", ttlPeriod as Any)])
|
||||
case .messageEmpty(let flags, let id, let peerId):
|
||||
return ("messageEmpty", [("flags", flags as Any), ("id", id as Any), ("peerId", peerId as Any)])
|
||||
case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let ttlPeriod):
|
||||
|
|
@ -512,79 +513,84 @@ public extension Api {
|
|||
if let signature = reader.readInt32() {
|
||||
_4 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _5: Api.MessageFwdHeader?
|
||||
var _5: Api.Peer?
|
||||
if Int(_1!) & Int(1 << 28) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
} }
|
||||
var _6: Api.MessageFwdHeader?
|
||||
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
|
||||
_5 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader
|
||||
_6 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader
|
||||
} }
|
||||
var _6: Int64?
|
||||
if Int(_1!) & Int(1 << 11) != 0 {_6 = reader.readInt64() }
|
||||
var _7: Api.MessageReplyHeader?
|
||||
var _7: Int64?
|
||||
if Int(_1!) & Int(1 << 11) != 0 {_7 = reader.readInt64() }
|
||||
var _8: Api.MessageReplyHeader?
|
||||
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
|
||||
_7 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader
|
||||
_8 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader
|
||||
} }
|
||||
var _8: Int32?
|
||||
_8 = reader.readInt32()
|
||||
var _9: String?
|
||||
_9 = parseString(reader)
|
||||
var _10: Api.MessageMedia?
|
||||
var _9: Int32?
|
||||
_9 = reader.readInt32()
|
||||
var _10: String?
|
||||
_10 = parseString(reader)
|
||||
var _11: Api.MessageMedia?
|
||||
if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() {
|
||||
_10 = Api.parse(reader, signature: signature) as? Api.MessageMedia
|
||||
_11 = Api.parse(reader, signature: signature) as? Api.MessageMedia
|
||||
} }
|
||||
var _11: Api.ReplyMarkup?
|
||||
var _12: Api.ReplyMarkup?
|
||||
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
|
||||
_11 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup
|
||||
_12 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup
|
||||
} }
|
||||
var _12: [Api.MessageEntity]?
|
||||
var _13: [Api.MessageEntity]?
|
||||
if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() {
|
||||
_12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
|
||||
_13 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
|
||||
} }
|
||||
var _13: Int32?
|
||||
if Int(_1!) & Int(1 << 10) != 0 {_13 = reader.readInt32() }
|
||||
var _14: Int32?
|
||||
if Int(_1!) & Int(1 << 10) != 0 {_14 = reader.readInt32() }
|
||||
var _15: Api.MessageReplies?
|
||||
var _15: Int32?
|
||||
if Int(_1!) & Int(1 << 10) != 0 {_15 = reader.readInt32() }
|
||||
var _16: Api.MessageReplies?
|
||||
if Int(_1!) & Int(1 << 23) != 0 {if let signature = reader.readInt32() {
|
||||
_15 = Api.parse(reader, signature: signature) as? Api.MessageReplies
|
||||
_16 = Api.parse(reader, signature: signature) as? Api.MessageReplies
|
||||
} }
|
||||
var _16: Int32?
|
||||
if Int(_1!) & Int(1 << 15) != 0 {_16 = reader.readInt32() }
|
||||
var _17: String?
|
||||
if Int(_1!) & Int(1 << 16) != 0 {_17 = parseString(reader) }
|
||||
var _18: Int64?
|
||||
if Int(_1!) & Int(1 << 17) != 0 {_18 = reader.readInt64() }
|
||||
var _19: Api.MessageReactions?
|
||||
var _17: Int32?
|
||||
if Int(_1!) & Int(1 << 15) != 0 {_17 = reader.readInt32() }
|
||||
var _18: String?
|
||||
if Int(_1!) & Int(1 << 16) != 0 {_18 = parseString(reader) }
|
||||
var _19: Int64?
|
||||
if Int(_1!) & Int(1 << 17) != 0 {_19 = reader.readInt64() }
|
||||
var _20: Api.MessageReactions?
|
||||
if Int(_1!) & Int(1 << 20) != 0 {if let signature = reader.readInt32() {
|
||||
_19 = Api.parse(reader, signature: signature) as? Api.MessageReactions
|
||||
_20 = Api.parse(reader, signature: signature) as? Api.MessageReactions
|
||||
} }
|
||||
var _20: [Api.RestrictionReason]?
|
||||
var _21: [Api.RestrictionReason]?
|
||||
if Int(_1!) & Int(1 << 22) != 0 {if let _ = reader.readInt32() {
|
||||
_20 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self)
|
||||
_21 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self)
|
||||
} }
|
||||
var _21: Int32?
|
||||
if Int(_1!) & Int(1 << 25) != 0 {_21 = reader.readInt32() }
|
||||
var _22: Int32?
|
||||
if Int(_1!) & Int(1 << 25) != 0 {_22 = reader.readInt32() }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = (Int(_1!) & Int(1 << 8) == 0) || _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 11) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c5 = (Int(_1!) & Int(1 << 28) == 0) || _5 != nil
|
||||
let _c6 = (Int(_1!) & Int(1 << 2) == 0) || _6 != nil
|
||||
let _c7 = (Int(_1!) & Int(1 << 11) == 0) || _7 != nil
|
||||
let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil
|
||||
let _c9 = _9 != nil
|
||||
let _c10 = (Int(_1!) & Int(1 << 9) == 0) || _10 != nil
|
||||
let _c11 = (Int(_1!) & Int(1 << 6) == 0) || _11 != nil
|
||||
let _c12 = (Int(_1!) & Int(1 << 7) == 0) || _12 != nil
|
||||
let _c13 = (Int(_1!) & Int(1 << 10) == 0) || _13 != nil
|
||||
let _c10 = _10 != nil
|
||||
let _c11 = (Int(_1!) & Int(1 << 9) == 0) || _11 != nil
|
||||
let _c12 = (Int(_1!) & Int(1 << 6) == 0) || _12 != nil
|
||||
let _c13 = (Int(_1!) & Int(1 << 7) == 0) || _13 != nil
|
||||
let _c14 = (Int(_1!) & Int(1 << 10) == 0) || _14 != nil
|
||||
let _c15 = (Int(_1!) & Int(1 << 23) == 0) || _15 != nil
|
||||
let _c16 = (Int(_1!) & Int(1 << 15) == 0) || _16 != nil
|
||||
let _c17 = (Int(_1!) & Int(1 << 16) == 0) || _17 != nil
|
||||
let _c18 = (Int(_1!) & Int(1 << 17) == 0) || _18 != nil
|
||||
let _c19 = (Int(_1!) & Int(1 << 20) == 0) || _19 != nil
|
||||
let _c20 = (Int(_1!) & Int(1 << 22) == 0) || _20 != nil
|
||||
let _c21 = (Int(_1!) & Int(1 << 25) == 0) || _21 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 {
|
||||
return Api.Message.message(flags: _1!, id: _2!, fromId: _3, peerId: _4!, fwdFrom: _5, viaBotId: _6, replyTo: _7, date: _8!, message: _9!, media: _10, replyMarkup: _11, entities: _12, views: _13, forwards: _14, replies: _15, editDate: _16, postAuthor: _17, groupedId: _18, reactions: _19, restrictionReason: _20, ttlPeriod: _21)
|
||||
let _c15 = (Int(_1!) & Int(1 << 10) == 0) || _15 != nil
|
||||
let _c16 = (Int(_1!) & Int(1 << 23) == 0) || _16 != nil
|
||||
let _c17 = (Int(_1!) & Int(1 << 15) == 0) || _17 != nil
|
||||
let _c18 = (Int(_1!) & Int(1 << 16) == 0) || _18 != nil
|
||||
let _c19 = (Int(_1!) & Int(1 << 17) == 0) || _19 != nil
|
||||
let _c20 = (Int(_1!) & Int(1 << 20) == 0) || _20 != nil
|
||||
let _c21 = (Int(_1!) & Int(1 << 22) == 0) || _21 != nil
|
||||
let _c22 = (Int(_1!) & Int(1 << 25) == 0) || _22 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 {
|
||||
return Api.Message.message(flags: _1!, id: _2!, fromId: _3, peerId: _4!, savedPeerId: _5, fwdFrom: _6, viaBotId: _7, replyTo: _8, date: _9!, message: _10!, media: _11, replyMarkup: _12, entities: _13, views: _14, forwards: _15, replies: _16, editDate: _17, postAuthor: _18, groupedId: _19, reactions: _20, restrictionReason: _21, ttlPeriod: _22)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -606,6 +606,52 @@ public extension Api {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum SavedDialog: TypeConstructorDescription {
|
||||
case savedDialog(flags: Int32, peer: Api.Peer, topMessage: Int32)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .savedDialog(let flags, let peer, let topMessage):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1115174036)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(topMessage, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .savedDialog(let flags, let peer, let topMessage):
|
||||
return ("savedDialog", [("flags", flags as Any), ("peer", peer as Any), ("topMessage", topMessage as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_savedDialog(_ reader: BufferReader) -> SavedDialog? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.Peer?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.Peer
|
||||
}
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
if _c1 && _c2 && _c3 {
|
||||
return Api.SavedDialog.savedDialog(flags: _1!, peer: _2!, topMessage: _3!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api {
|
||||
enum SearchResultsCalendarPeriod: TypeConstructorDescription {
|
||||
case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32)
|
||||
|
|
|
|||
|
|
@ -550,6 +550,7 @@ public extension Api {
|
|||
case updatePinnedChannelMessages(flags: Int32, channelId: Int64, messages: [Int32], pts: Int32, ptsCount: Int32)
|
||||
case updatePinnedDialogs(flags: Int32, folderId: Int32?, order: [Api.DialogPeer]?)
|
||||
case updatePinnedMessages(flags: Int32, peer: Api.Peer, messages: [Int32], pts: Int32, ptsCount: Int32)
|
||||
case updatePinnedSavedDialogs(flags: Int32, order: [Api.DialogPeer]?)
|
||||
case updatePrivacy(key: Api.PrivacyKey, rules: [Api.PrivacyRule])
|
||||
case updatePtsChanged
|
||||
case updateReadChannelDiscussionInbox(flags: Int32, channelId: Int64, topMsgId: Int32, readMaxId: Int32, broadcastId: Int64?, broadcastPost: Int32?)
|
||||
|
|
@ -565,6 +566,7 @@ public extension Api {
|
|||
case updateRecentEmojiStatuses
|
||||
case updateRecentReactions
|
||||
case updateRecentStickers
|
||||
case updateSavedDialogPinned(flags: Int32, peer: Api.DialogPeer)
|
||||
case updateSavedGifs
|
||||
case updateSavedRingtones
|
||||
case updateSentStoryReaction(peer: Api.Peer, storyId: Int32, reaction: Api.Reaction)
|
||||
|
|
@ -1372,6 +1374,17 @@ public extension Api {
|
|||
serializeInt32(pts, buffer: buffer, boxed: false)
|
||||
serializeInt32(ptsCount, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .updatePinnedSavedDialogs(let flags, let order):
|
||||
if boxed {
|
||||
buffer.appendInt32(1751942566)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(order!.count))
|
||||
for item in order! {
|
||||
item.serialize(buffer, true)
|
||||
}}
|
||||
break
|
||||
case .updatePrivacy(let key, let rules):
|
||||
if boxed {
|
||||
buffer.appendInt32(-298113238)
|
||||
|
|
@ -1497,6 +1510,13 @@ public extension Api {
|
|||
buffer.appendInt32(-1706939360)
|
||||
}
|
||||
|
||||
break
|
||||
case .updateSavedDialogPinned(let flags, let peer):
|
||||
if boxed {
|
||||
buffer.appendInt32(-1364222348)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
break
|
||||
case .updateSavedGifs:
|
||||
if boxed {
|
||||
|
|
@ -1828,6 +1848,8 @@ public extension Api {
|
|||
return ("updatePinnedDialogs", [("flags", flags as Any), ("folderId", folderId as Any), ("order", order as Any)])
|
||||
case .updatePinnedMessages(let flags, let peer, let messages, let pts, let ptsCount):
|
||||
return ("updatePinnedMessages", [("flags", flags as Any), ("peer", peer as Any), ("messages", messages as Any), ("pts", pts as Any), ("ptsCount", ptsCount as Any)])
|
||||
case .updatePinnedSavedDialogs(let flags, let order):
|
||||
return ("updatePinnedSavedDialogs", [("flags", flags as Any), ("order", order as Any)])
|
||||
case .updatePrivacy(let key, let rules):
|
||||
return ("updatePrivacy", [("key", key as Any), ("rules", rules as Any)])
|
||||
case .updatePtsChanged:
|
||||
|
|
@ -1858,6 +1880,8 @@ public extension Api {
|
|||
return ("updateRecentReactions", [])
|
||||
case .updateRecentStickers:
|
||||
return ("updateRecentStickers", [])
|
||||
case .updateSavedDialogPinned(let flags, let peer):
|
||||
return ("updateSavedDialogPinned", [("flags", flags as Any), ("peer", peer as Any)])
|
||||
case .updateSavedGifs:
|
||||
return ("updateSavedGifs", [])
|
||||
case .updateSavedRingtones:
|
||||
|
|
@ -3538,6 +3562,22 @@ public extension Api {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_updatePinnedSavedDialogs(_ reader: BufferReader) -> Update? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: [Api.DialogPeer]?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogPeer.self)
|
||||
} }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.Update.updatePinnedSavedDialogs(flags: _1!, order: _2)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_updatePrivacy(_ reader: BufferReader) -> Update? {
|
||||
var _1: Api.PrivacyKey?
|
||||
if let signature = reader.readInt32() {
|
||||
|
|
@ -3751,6 +3791,22 @@ public extension Api {
|
|||
public static func parse_updateRecentStickers(_ reader: BufferReader) -> Update? {
|
||||
return Api.Update.updateRecentStickers
|
||||
}
|
||||
public static func parse_updateSavedDialogPinned(_ reader: BufferReader) -> Update? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Api.DialogPeer?
|
||||
if let signature = reader.readInt32() {
|
||||
_2 = Api.parse(reader, signature: signature) as? Api.DialogPeer
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.Update.updateSavedDialogPinned(flags: _1!, peer: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_updateSavedGifs(_ reader: BufferReader) -> Update? {
|
||||
return Api.Update.updateSavedGifs
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1425,59 +1425,153 @@ public extension Api.messages {
|
|||
}
|
||||
}
|
||||
public extension Api.messages {
|
||||
enum SavedGifs: TypeConstructorDescription {
|
||||
case savedGifs(hash: Int64, gifs: [Api.Document])
|
||||
case savedGifsNotModified
|
||||
enum SavedDialogs: TypeConstructorDescription {
|
||||
case savedDialogs(dialogs: [Api.SavedDialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
|
||||
case savedDialogsNotModified(count: Int32)
|
||||
case savedDialogsSlice(count: Int32, dialogs: [Api.SavedDialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .savedGifs(let hash, let gifs):
|
||||
case .savedDialogs(let dialogs, let messages, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2069878259)
|
||||
buffer.appendInt32(-130358751)
|
||||
}
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(gifs.count))
|
||||
for item in gifs {
|
||||
buffer.appendInt32(Int32(dialogs.count))
|
||||
for item in dialogs {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(messages.count))
|
||||
for item in messages {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .savedGifsNotModified:
|
||||
case .savedDialogsNotModified(let count):
|
||||
if boxed {
|
||||
buffer.appendInt32(-402498398)
|
||||
buffer.appendInt32(-1071681560)
|
||||
}
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
break
|
||||
case .savedDialogsSlice(let count, let dialogs, let messages, let chats, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(1153080793)
|
||||
}
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(dialogs.count))
|
||||
for item in dialogs {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(messages.count))
|
||||
for item in messages {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .savedGifs(let hash, let gifs):
|
||||
return ("savedGifs", [("hash", hash as Any), ("gifs", gifs as Any)])
|
||||
case .savedGifsNotModified:
|
||||
return ("savedGifsNotModified", [])
|
||||
case .savedDialogs(let dialogs, let messages, let chats, let users):
|
||||
return ("savedDialogs", [("dialogs", dialogs as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
case .savedDialogsNotModified(let count):
|
||||
return ("savedDialogsNotModified", [("count", count as Any)])
|
||||
case .savedDialogsSlice(let count, let dialogs, let messages, let chats, let users):
|
||||
return ("savedDialogsSlice", [("count", count as Any), ("dialogs", dialogs as Any), ("messages", messages as Any), ("chats", chats as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_savedGifs(_ reader: BufferReader) -> SavedGifs? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: [Api.Document]?
|
||||
public static func parse_savedDialogs(_ reader: BufferReader) -> SavedDialogs? {
|
||||
var _1: [Api.SavedDialog]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self)
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SavedDialog.self)
|
||||
}
|
||||
var _2: [Api.Message]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
}
|
||||
var _3: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _4: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.messages.SavedGifs.savedGifs(hash: _1!, gifs: _2!)
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 {
|
||||
return Api.messages.SavedDialogs.savedDialogs(dialogs: _1!, messages: _2!, chats: _3!, users: _4!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_savedGifsNotModified(_ reader: BufferReader) -> SavedGifs? {
|
||||
return Api.messages.SavedGifs.savedGifsNotModified
|
||||
public static func parse_savedDialogsNotModified(_ reader: BufferReader) -> SavedDialogs? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.messages.SavedDialogs.savedDialogsNotModified(count: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_savedDialogsSlice(_ reader: BufferReader) -> SavedDialogs? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: [Api.SavedDialog]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.SavedDialog.self)
|
||||
}
|
||||
var _3: [Api.Message]?
|
||||
if let _ = reader.readInt32() {
|
||||
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Message.self)
|
||||
}
|
||||
var _4: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_4 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _5: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 {
|
||||
return Api.messages.SavedDialogs.savedDialogsSlice(count: _1!, dialogs: _2!, messages: _3!, chats: _4!, users: _5!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,61 @@
|
|||
public extension Api.messages {
|
||||
enum SavedGifs: TypeConstructorDescription {
|
||||
case savedGifs(hash: Int64, gifs: [Api.Document])
|
||||
case savedGifsNotModified
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .savedGifs(let hash, let gifs):
|
||||
if boxed {
|
||||
buffer.appendInt32(-2069878259)
|
||||
}
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(gifs.count))
|
||||
for item in gifs {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
case .savedGifsNotModified:
|
||||
if boxed {
|
||||
buffer.appendInt32(-402498398)
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .savedGifs(let hash, let gifs):
|
||||
return ("savedGifs", [("hash", hash as Any), ("gifs", gifs as Any)])
|
||||
case .savedGifsNotModified:
|
||||
return ("savedGifsNotModified", [])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_savedGifs(_ reader: BufferReader) -> SavedGifs? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: [Api.Document]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Document.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.messages.SavedGifs.savedGifs(hash: _1!, gifs: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
public static func parse_savedGifsNotModified(_ reader: BufferReader) -> SavedGifs? {
|
||||
return Api.messages.SavedGifs.savedGifsNotModified
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.messages {
|
||||
enum SearchCounter: TypeConstructorDescription {
|
||||
case searchCounter(flags: Int32, filter: Api.MessagesFilter, count: Int32)
|
||||
|
|
@ -1482,85 +1540,3 @@ public extension Api.phone {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api.phone {
|
||||
enum GroupCallStreamChannels: TypeConstructorDescription {
|
||||
case groupCallStreamChannels(channels: [Api.GroupCallStreamChannel])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallStreamChannels(let channels):
|
||||
if boxed {
|
||||
buffer.appendInt32(-790330702)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(channels.count))
|
||||
for item in channels {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallStreamChannels(let channels):
|
||||
return ("groupCallStreamChannels", [("channels", channels as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallStreamChannels(_ reader: BufferReader) -> GroupCallStreamChannels? {
|
||||
var _1: [Api.GroupCallStreamChannel]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallStreamChannel.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.phone.GroupCallStreamChannels.groupCallStreamChannels(channels: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.phone {
|
||||
enum GroupCallStreamRtmpUrl: TypeConstructorDescription {
|
||||
case groupCallStreamRtmpUrl(url: String, key: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallStreamRtmpUrl(let url, let key):
|
||||
if boxed {
|
||||
buffer.appendInt32(767505458)
|
||||
}
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallStreamRtmpUrl(let url, let key):
|
||||
return ("groupCallStreamRtmpUrl", [("url", url as Any), ("key", key as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallStreamRtmpUrl(_ reader: BufferReader) -> GroupCallStreamRtmpUrl? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.phone.GroupCallStreamRtmpUrl.groupCallStreamRtmpUrl(url: _1!, key: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,85 @@
|
|||
public extension Api.phone {
|
||||
enum GroupCallStreamChannels: TypeConstructorDescription {
|
||||
case groupCallStreamChannels(channels: [Api.GroupCallStreamChannel])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallStreamChannels(let channels):
|
||||
if boxed {
|
||||
buffer.appendInt32(-790330702)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(channels.count))
|
||||
for item in channels {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallStreamChannels(let channels):
|
||||
return ("groupCallStreamChannels", [("channels", channels as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallStreamChannels(_ reader: BufferReader) -> GroupCallStreamChannels? {
|
||||
var _1: [Api.GroupCallStreamChannel]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.GroupCallStreamChannel.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
if _c1 {
|
||||
return Api.phone.GroupCallStreamChannels.groupCallStreamChannels(channels: _1!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.phone {
|
||||
enum GroupCallStreamRtmpUrl: TypeConstructorDescription {
|
||||
case groupCallStreamRtmpUrl(url: String, key: String)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .groupCallStreamRtmpUrl(let url, let key):
|
||||
if boxed {
|
||||
buffer.appendInt32(767505458)
|
||||
}
|
||||
serializeString(url, buffer: buffer, boxed: false)
|
||||
serializeString(key, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .groupCallStreamRtmpUrl(let url, let key):
|
||||
return ("groupCallStreamRtmpUrl", [("url", url as Any), ("key", key as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_groupCallStreamRtmpUrl(_ reader: BufferReader) -> GroupCallStreamRtmpUrl? {
|
||||
var _1: String?
|
||||
_1 = parseString(reader)
|
||||
var _2: String?
|
||||
_2 = parseString(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.phone.GroupCallStreamRtmpUrl.groupCallStreamRtmpUrl(url: _1!, key: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.phone {
|
||||
enum GroupParticipants: TypeConstructorDescription {
|
||||
case groupParticipants(count: Int32, participants: [Api.GroupCallParticipant], nextOffset: String, chats: [Api.Chat], users: [Api.User], version: Int32)
|
||||
|
|
@ -1494,141 +1576,3 @@ public extension Api.stories {
|
|||
|
||||
}
|
||||
}
|
||||
public extension Api.stories {
|
||||
enum StoryViews: TypeConstructorDescription {
|
||||
case storyViews(views: [Api.StoryViews], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .storyViews(let views, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-560009955)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(views.count))
|
||||
for item in views {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .storyViews(let views, let users):
|
||||
return ("storyViews", [("views", views as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_storyViews(_ reader: BufferReader) -> StoryViews? {
|
||||
var _1: [Api.StoryViews]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryViews.self)
|
||||
}
|
||||
var _2: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.stories.StoryViews.storyViews(views: _1!, users: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.stories {
|
||||
enum StoryViewsList: TypeConstructorDescription {
|
||||
case storyViewsList(flags: Int32, count: Int32, viewsCount: Int32, forwardsCount: Int32, reactionsCount: Int32, views: [Api.StoryView], chats: [Api.Chat], users: [Api.User], nextOffset: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
|
||||
if boxed {
|
||||
buffer.appendInt32(1507299269)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
serializeInt32(viewsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(forwardsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(reactionsCount, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(views.count))
|
||||
for item in views {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
|
||||
return ("storyViewsList", [("flags", flags as Any), ("count", count as Any), ("viewsCount", viewsCount as Any), ("forwardsCount", forwardsCount as Any), ("reactionsCount", reactionsCount as Any), ("views", views as Any), ("chats", chats as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_storyViewsList(_ reader: BufferReader) -> StoryViewsList? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: [Api.StoryView]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryView.self)
|
||||
}
|
||||
var _7: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _8: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
var _9: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_9 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 0) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.stories.StoryViewsList.storyViewsList(flags: _1!, count: _2!, viewsCount: _3!, forwardsCount: _4!, reactionsCount: _5!, views: _6!, chats: _7!, users: _8!, nextOffset: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,141 @@
|
|||
public extension Api.stories {
|
||||
enum StoryViews: TypeConstructorDescription {
|
||||
case storyViews(views: [Api.StoryViews], users: [Api.User])
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .storyViews(let views, let users):
|
||||
if boxed {
|
||||
buffer.appendInt32(-560009955)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(views.count))
|
||||
for item in views {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .storyViews(let views, let users):
|
||||
return ("storyViews", [("views", views as Any), ("users", users as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_storyViews(_ reader: BufferReader) -> StoryViews? {
|
||||
var _1: [Api.StoryViews]?
|
||||
if let _ = reader.readInt32() {
|
||||
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryViews.self)
|
||||
}
|
||||
var _2: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.stories.StoryViews.storyViews(views: _1!, users: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.stories {
|
||||
enum StoryViewsList: TypeConstructorDescription {
|
||||
case storyViewsList(flags: Int32, count: Int32, viewsCount: Int32, forwardsCount: Int32, reactionsCount: Int32, views: [Api.StoryView], chats: [Api.Chat], users: [Api.User], nextOffset: String?)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
|
||||
if boxed {
|
||||
buffer.appendInt32(1507299269)
|
||||
}
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(count, buffer: buffer, boxed: false)
|
||||
serializeInt32(viewsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(forwardsCount, buffer: buffer, boxed: false)
|
||||
serializeInt32(reactionsCount, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(views.count))
|
||||
for item in views {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(chats.count))
|
||||
for item in chats {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(users.count))
|
||||
for item in users {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeString(nextOffset!, buffer: buffer, boxed: false)}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
public func descriptionFields() -> (String, [(String, Any)]) {
|
||||
switch self {
|
||||
case .storyViewsList(let flags, let count, let viewsCount, let forwardsCount, let reactionsCount, let views, let chats, let users, let nextOffset):
|
||||
return ("storyViewsList", [("flags", flags as Any), ("count", count as Any), ("viewsCount", viewsCount as Any), ("forwardsCount", forwardsCount as Any), ("reactionsCount", reactionsCount as Any), ("views", views as Any), ("chats", chats as Any), ("users", users as Any), ("nextOffset", nextOffset as Any)])
|
||||
}
|
||||
}
|
||||
|
||||
public static func parse_storyViewsList(_ reader: BufferReader) -> StoryViewsList? {
|
||||
var _1: Int32?
|
||||
_1 = reader.readInt32()
|
||||
var _2: Int32?
|
||||
_2 = reader.readInt32()
|
||||
var _3: Int32?
|
||||
_3 = reader.readInt32()
|
||||
var _4: Int32?
|
||||
_4 = reader.readInt32()
|
||||
var _5: Int32?
|
||||
_5 = reader.readInt32()
|
||||
var _6: [Api.StoryView]?
|
||||
if let _ = reader.readInt32() {
|
||||
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.StoryView.self)
|
||||
}
|
||||
var _7: [Api.Chat]?
|
||||
if let _ = reader.readInt32() {
|
||||
_7 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Chat.self)
|
||||
}
|
||||
var _8: [Api.User]?
|
||||
if let _ = reader.readInt32() {
|
||||
_8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self)
|
||||
}
|
||||
var _9: String?
|
||||
if Int(_1!) & Int(1 << 0) != 0 {_9 = parseString(reader) }
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
let _c3 = _3 != nil
|
||||
let _c4 = _4 != nil
|
||||
let _c5 = _5 != nil
|
||||
let _c6 = _6 != nil
|
||||
let _c7 = _7 != nil
|
||||
let _c8 = _8 != nil
|
||||
let _c9 = (Int(_1!) & Int(1 << 0) == 0) || _9 != nil
|
||||
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 {
|
||||
return Api.stories.StoryViewsList.storyViewsList(flags: _1!, count: _2!, viewsCount: _3!, forwardsCount: _4!, reactionsCount: _5!, views: _6!, chats: _7!, users: _8!, nextOffset: _9)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public extension Api.updates {
|
||||
indirect enum ChannelDifference: TypeConstructorDescription {
|
||||
case channelDifference(flags: Int32, pts: Int32, timeout: Int32?, newMessages: [Api.Message], otherUpdates: [Api.Update], chats: [Api.Chat], users: [Api.User])
|
||||
|
|
|
|||
|
|
@ -5670,6 +5670,21 @@ public extension Api.functions.messages {
|
|||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getPinnedSavedDialogs() -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SavedDialogs>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-700607264)
|
||||
|
||||
return (FunctionDescription(name: "messages.getPinnedSavedDialogs", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedDialogs? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.SavedDialogs?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.messages.SavedDialogs
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getPollResults(peer: Api.InputPeer, msgId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Updates>) {
|
||||
let buffer = Buffer()
|
||||
|
|
@ -5778,6 +5793,26 @@ public extension Api.functions.messages {
|
|||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSavedDialogs(flags: Int32, offsetDate: Int32, offsetId: Int32, offsetPeer: Api.InputPeer, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SavedDialogs>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1401016858)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
serializeInt32(offsetDate, buffer: buffer, boxed: false)
|
||||
serializeInt32(offsetId, buffer: buffer, boxed: false)
|
||||
offsetPeer.serialize(buffer, true)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getSavedDialogs", parameters: [("flags", String(describing: flags)), ("offsetDate", String(describing: offsetDate)), ("offsetId", String(describing: offsetId)), ("offsetPeer", String(describing: offsetPeer)), ("limit", String(describing: limit)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SavedDialogs? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.SavedDialogs?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.messages.SavedDialogs
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSavedGifs(hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SavedGifs>) {
|
||||
let buffer = Buffer()
|
||||
|
|
@ -5793,6 +5828,28 @@ public extension Api.functions.messages {
|
|||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSavedHistory(peer: Api.InputPeer, offsetId: Int32, offsetDate: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1033519437)
|
||||
peer.serialize(buffer, true)
|
||||
serializeInt32(offsetId, buffer: buffer, boxed: false)
|
||||
serializeInt32(offsetDate, buffer: buffer, boxed: false)
|
||||
serializeInt32(addOffset, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
serializeInt32(maxId, buffer: buffer, boxed: false)
|
||||
serializeInt32(minId, buffer: buffer, boxed: false)
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getSavedHistory", parameters: [("peer", String(describing: peer)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.Messages?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.messages.Messages
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getScheduledHistory(peer: Api.InputPeer, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
|
||||
let buffer = Buffer()
|
||||
|
|
@ -5830,18 +5887,19 @@ public extension Api.functions.messages {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSearchCounters(flags: Int32, peer: Api.InputPeer, topMsgId: Int32?, filters: [Api.MessagesFilter]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.messages.SearchCounter]>) {
|
||||
static func getSearchCounters(flags: Int32, peer: Api.InputPeer, savedPeerId: Api.InputPeer?, topMsgId: Int32?, filters: [Api.MessagesFilter]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<[Api.messages.SearchCounter]>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(11435201)
|
||||
buffer.appendInt32(465367808)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 2) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)}
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(filters.count))
|
||||
for item in filters {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
return (FunctionDescription(name: "messages.getSearchCounters", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("topMsgId", String(describing: topMsgId)), ("filters", String(describing: filters))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.messages.SearchCounter]? in
|
||||
return (FunctionDescription(name: "messages.getSearchCounters", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("savedPeerId", String(describing: savedPeerId)), ("topMsgId", String(describing: topMsgId)), ("filters", String(describing: filters))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> [Api.messages.SearchCounter]? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: [Api.messages.SearchCounter]?
|
||||
if let _ = reader.readInt32() {
|
||||
|
|
@ -5852,14 +5910,16 @@ public extension Api.functions.messages {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSearchResultsCalendar(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, offsetDate: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SearchResultsCalendar>) {
|
||||
static func getSearchResultsCalendar(flags: Int32, peer: Api.InputPeer, savedPeerId: Api.InputPeer?, filter: Api.MessagesFilter, offsetId: Int32, offsetDate: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SearchResultsCalendar>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1240514025)
|
||||
buffer.appendInt32(1789130429)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 2) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||
filter.serialize(buffer, true)
|
||||
serializeInt32(offsetId, buffer: buffer, boxed: false)
|
||||
serializeInt32(offsetDate, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getSearchResultsCalendar", parameters: [("peer", String(describing: peer)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsCalendar? in
|
||||
return (FunctionDescription(name: "messages.getSearchResultsCalendar", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("savedPeerId", String(describing: savedPeerId)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("offsetDate", String(describing: offsetDate))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsCalendar? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.SearchResultsCalendar?
|
||||
if let signature = reader.readInt32() {
|
||||
|
|
@ -5870,14 +5930,16 @@ public extension Api.functions.messages {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func getSearchResultsPositions(peer: Api.InputPeer, filter: Api.MessagesFilter, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SearchResultsPositions>) {
|
||||
static func getSearchResultsPositions(flags: Int32, peer: Api.InputPeer, savedPeerId: Api.InputPeer?, filter: Api.MessagesFilter, offsetId: Int32, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.SearchResultsPositions>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(1855292323)
|
||||
buffer.appendInt32(-1669386480)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
if Int(flags) & Int(1 << 2) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||
filter.serialize(buffer, true)
|
||||
serializeInt32(offsetId, buffer: buffer, boxed: false)
|
||||
serializeInt32(limit, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.getSearchResultsPositions", parameters: [("peer", String(describing: peer)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsPositions? in
|
||||
return (FunctionDescription(name: "messages.getSearchResultsPositions", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("savedPeerId", String(describing: savedPeerId)), ("filter", String(describing: filter)), ("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.SearchResultsPositions? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.SearchResultsPositions?
|
||||
if let signature = reader.readInt32() {
|
||||
|
|
@ -6384,6 +6446,26 @@ public extension Api.functions.messages {
|
|||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func reorderPinnedSavedDialogs(flags: Int32, order: [Api.InputDialogPeer]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1955502713)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
buffer.appendInt32(481674261)
|
||||
buffer.appendInt32(Int32(order.count))
|
||||
for item in order {
|
||||
item.serialize(buffer, true)
|
||||
}
|
||||
return (FunctionDescription(name: "messages.reorderPinnedSavedDialogs", parameters: [("flags", String(describing: flags)), ("order", String(describing: order))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func reorderStickerSets(flags: Int32, order: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
|
|
@ -6646,13 +6728,14 @@ public extension Api.functions.messages {
|
|||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func search(flags: Int32, peer: Api.InputPeer, q: String, fromId: Api.InputPeer?, topMsgId: Int32?, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
|
||||
static func search(flags: Int32, peer: Api.InputPeer, q: String, fromId: Api.InputPeer?, savedPeerId: Api.InputPeer?, topMsgId: Int32?, filter: Api.MessagesFilter, minDate: Int32, maxDate: Int32, offsetId: Int32, addOffset: Int32, limit: Int32, maxId: Int32, minId: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.messages.Messages>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1593989278)
|
||||
buffer.appendInt32(-1481316055)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
serializeString(q, buffer: buffer, boxed: false)
|
||||
if Int(flags) & Int(1 << 0) != 0 {fromId!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 2) != 0 {savedPeerId!.serialize(buffer, true)}
|
||||
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(topMsgId!, buffer: buffer, boxed: false)}
|
||||
filter.serialize(buffer, true)
|
||||
serializeInt32(minDate, buffer: buffer, boxed: false)
|
||||
|
|
@ -6663,7 +6746,7 @@ public extension Api.functions.messages {
|
|||
serializeInt32(maxId, buffer: buffer, boxed: false)
|
||||
serializeInt32(minId, buffer: buffer, boxed: false)
|
||||
serializeInt64(hash, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "messages.search", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("q", String(describing: q)), ("fromId", String(describing: fromId)), ("topMsgId", String(describing: topMsgId)), ("filter", String(describing: filter)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
|
||||
return (FunctionDescription(name: "messages.search", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer)), ("q", String(describing: q)), ("fromId", String(describing: fromId)), ("savedPeerId", String(describing: savedPeerId)), ("topMsgId", String(describing: topMsgId)), ("filter", String(describing: filter)), ("minDate", String(describing: minDate)), ("maxDate", String(describing: maxDate)), ("offsetId", String(describing: offsetId)), ("addOffset", String(describing: addOffset)), ("limit", String(describing: limit)), ("maxId", String(describing: maxId)), ("minId", String(describing: minId)), ("hash", String(describing: hash))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.Messages? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.messages.Messages?
|
||||
if let signature = reader.readInt32() {
|
||||
|
|
@ -7405,6 +7488,22 @@ public extension Api.functions.messages {
|
|||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func toggleSavedDialogPin(flags: Int32, peer: Api.InputDialogPeer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-1400783906)
|
||||
serializeInt32(flags, buffer: buffer, boxed: false)
|
||||
peer.serialize(buffer, true)
|
||||
return (FunctionDescription(name: "messages.toggleSavedDialogPin", parameters: [("flags", String(describing: flags)), ("peer", String(describing: peer))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
public extension Api.functions.messages {
|
||||
static func toggleStickerSets(flags: Int32, stickersets: [Api.InputStickerSet]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute],
|
|||
|
||||
func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
|
||||
switch messsage {
|
||||
case let .message(_, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
let chatPeerId = messagePeerId
|
||||
return chatPeerId.peerId
|
||||
case let .messageEmpty(_, _, peerId):
|
||||
|
|
@ -142,7 +142,7 @@ func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? {
|
|||
|
||||
func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
||||
switch message {
|
||||
case let .message(_, _, fromId, chatPeerId, fwdHeader, viaBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, fromId, chatPeerId, savedPeerId, fwdHeader, viaBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _):
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
|
||||
var result = [peerId]
|
||||
|
|
@ -168,6 +168,10 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
|||
if let viaBotId = viaBotId {
|
||||
result.append(PeerId(namespace: Namespaces.Peer.CloudUser, id: PeerId.Id._internalFromInt64Value(viaBotId)))
|
||||
}
|
||||
|
||||
if let savedPeerId = savedPeerId {
|
||||
result.append(savedPeerId.peerId)
|
||||
}
|
||||
|
||||
if let media = media {
|
||||
switch media {
|
||||
|
|
@ -256,7 +260,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
|
|||
|
||||
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? {
|
||||
switch message {
|
||||
case let .message(_, id, _, chatPeerId, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, id, _, chatPeerId, _, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
if let replyTo = replyTo {
|
||||
let peerId: PeerId = chatPeerId.peerId
|
||||
|
||||
|
|
@ -582,7 +586,7 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes
|
|||
extension StoreMessage {
|
||||
convenience init?(apiMessage: Api.Message, accountPeerId: PeerId, peerIsForum: Bool, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
|
||||
switch apiMessage {
|
||||
case let .message(flags, id, fromId, chatPeerId, fwdFrom, viaBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod):
|
||||
case let .message(flags, id, fromId, chatPeerId, savedPeerId, fwdFrom, viaBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod):
|
||||
let resolvedFromId = fromId?.peerId ?? chatPeerId.peerId
|
||||
|
||||
let peerId: PeerId
|
||||
|
|
@ -622,17 +626,17 @@ extension StoreMessage {
|
|||
if isForumTopic {
|
||||
let threadIdValue = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToTopId)
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
threadId = Int64(threadIdValue.id)
|
||||
}
|
||||
} else {
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let threadIdValue = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: replyToTopId)
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
threadId = Int64(threadIdValue.id)
|
||||
} else {
|
||||
let threadIdValue = MessageId(peerId: replyToPeerId?.peerId ?? peerId, namespace: Namespaces.Message.Cloud, id: replyToTopId)
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
threadId = Int64(threadIdValue.id)
|
||||
}
|
||||
}
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
|
|
@ -641,11 +645,11 @@ extension StoreMessage {
|
|||
if peerIsForum {
|
||||
if isForumTopic {
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
threadId = Int64(threadIdValue.id)
|
||||
}
|
||||
} else {
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
threadId = Int64(threadIdValue.id)
|
||||
}
|
||||
}
|
||||
attributes.append(ReplyMessageAttribute(messageId: MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId), threadMessageId: threadMessageId, quote: quote, isQuote: isQuote))
|
||||
|
|
@ -663,7 +667,6 @@ extension StoreMessage {
|
|||
}
|
||||
|
||||
var forwardInfo: StoreMessageForwardInfo?
|
||||
var savedFromPeerId: PeerId?
|
||||
if let fwdFrom = fwdFrom {
|
||||
switch fwdFrom {
|
||||
case let .messageFwdHeader(flags, fromId, fromName, date, channelPost, postAuthor, savedFromPeer, savedFromMsgId, psaType):
|
||||
|
|
@ -693,7 +696,6 @@ extension StoreMessage {
|
|||
|
||||
if let savedFromPeer = savedFromPeer, let savedFromMsgId = savedFromMsgId {
|
||||
let peerId: PeerId = savedFromPeer.peerId
|
||||
savedFromPeerId = peerId
|
||||
let messageId: MessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: savedFromMsgId)
|
||||
attributes.append(SourceReferenceMessageAttribute(messageId: messageId))
|
||||
}
|
||||
|
|
@ -708,8 +710,8 @@ extension StoreMessage {
|
|||
}
|
||||
}
|
||||
|
||||
if peerId == accountPeerId, let savedFromPeerId = savedFromPeerId {
|
||||
threadId = savedFromPeerId.toInt64()
|
||||
if peerId == accountPeerId, let savedPeerId = savedPeerId {
|
||||
threadId = savedPeerId.peerId.toInt64()
|
||||
}
|
||||
|
||||
let messageText = message
|
||||
|
|
@ -911,12 +913,12 @@ extension StoreMessage {
|
|||
let threadIdValue = MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToTopId)
|
||||
threadMessageId = threadIdValue
|
||||
if replyPeerId == peerId {
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
threadId = Int64(threadIdValue.id)
|
||||
}
|
||||
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let threadIdValue = MessageId(peerId: replyPeerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
|
||||
threadMessageId = threadIdValue
|
||||
threadId = makeMessageThreadId(threadIdValue)
|
||||
threadId = Int64(threadIdValue.id)
|
||||
}
|
||||
switch action {
|
||||
case .messageActionTopicEdit:
|
||||
|
|
|
|||
|
|
@ -516,7 +516,7 @@ func _internal_setChannelForumMode(postbox: Postbox, network: Network, stateMana
|
|||
struct LoadMessageHistoryThreadsResult {
|
||||
struct Item {
|
||||
var threadId: Int64
|
||||
var data: MessageHistoryThreadData
|
||||
var data: MessageHistoryThreadData?
|
||||
var topMessage: Int32
|
||||
var unreadMentionsCount: Int32
|
||||
var unreadReactionsCount: Int32
|
||||
|
|
@ -524,7 +524,7 @@ struct LoadMessageHistoryThreadsResult {
|
|||
|
||||
init(
|
||||
threadId: Int64,
|
||||
data: MessageHistoryThreadData,
|
||||
data: MessageHistoryThreadData?,
|
||||
topMessage: Int32,
|
||||
unreadMentionsCount: Int32,
|
||||
unreadReactionsCount: Int32,
|
||||
|
|
@ -570,95 +570,172 @@ enum LoadMessageHistoryThreadsError {
|
|||
case generic
|
||||
}
|
||||
|
||||
func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, query: String?, offsetIndex: StoredPeerThreadCombinedState.Index?, limit: Int) -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> {
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = postbox.transaction { transaction -> Api.InputChannel? in
|
||||
guard let channel = transaction.getPeer(peerId) as? TelegramChannel else {
|
||||
return nil
|
||||
}
|
||||
if !channel.flags.contains(.isForum) {
|
||||
return nil
|
||||
}
|
||||
return apiInputChannel(channel)
|
||||
func _internal_fillSavedMessageHistory(accountPeerId: PeerId, postbox: Postbox, network: Network) -> Signal<Never, NoError> {
|
||||
enum PassResult {
|
||||
case restart
|
||||
}
|
||||
|> castError(LoadMessageHistoryThreadsError.self)
|
||||
|> mapToSignal { inputChannel -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
guard let inputChannel = inputChannel else {
|
||||
return .fail(.generic)
|
||||
return (postbox.transaction { transaction -> Range<Int>? in
|
||||
let holes = transaction.getHoles(peerId: accountPeerId, namespace: Namespaces.Message.Cloud)
|
||||
return holes.rangeView.last
|
||||
}
|
||||
|> castError(PassResult.self)
|
||||
|> mapToSignal { range -> Signal<Never, PassResult> in
|
||||
if let range {
|
||||
return fetchMessageHistoryHole(
|
||||
accountPeerId: accountPeerId,
|
||||
source: .network(network),
|
||||
postbox: postbox,
|
||||
peerInput: .direct(peerId: accountPeerId, threadId: nil),
|
||||
namespace: Namespaces.Message.Cloud,
|
||||
direction: .range(
|
||||
start: MessageId(peerId: accountPeerId, namespace: Namespaces.Message.Cloud, id: Int32(range.upperBound) - 1),
|
||||
end: MessageId(peerId: accountPeerId, namespace: Namespaces.Message.Cloud, id: Int32(range.lowerBound) - 1)
|
||||
),
|
||||
space: .everywhere,
|
||||
count: 100
|
||||
)
|
||||
|> ignoreValues
|
||||
|> castError(PassResult.self)
|
||||
|> then(.fail(.restart))
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
})
|
||||
|> restartIfError
|
||||
}
|
||||
|
||||
func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Postbox, network: Network, peerId: PeerId, query: String?, offsetIndex: StoredPeerThreadCombinedState.Index?, limit: Int) -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> {
|
||||
if peerId == accountPeerId {
|
||||
if !"".isEmpty {
|
||||
return _internal_fillSavedMessageHistory(accountPeerId: accountPeerId, postbox: postbox, network: network)
|
||||
|> castError(LoadMessageHistoryThreadsError.self)
|
||||
|> map { _ -> LoadMessageHistoryThreadsResult in
|
||||
}
|
||||
|> then(postbox.transaction { transaction -> LoadMessageHistoryThreadsResult in
|
||||
var topMessages: [Int64: Message] = [:]
|
||||
transaction.scanTopMessages(peerId: accountPeerId, namespace: Namespaces.Message.Cloud, limit: 100000, { message in
|
||||
if let threadId = message.threadId {
|
||||
if let current = topMessages[threadId] {
|
||||
if current.id < message.id {
|
||||
topMessages[threadId] = message
|
||||
}
|
||||
} else {
|
||||
topMessages[threadId] = message
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
|
||||
var items: [LoadMessageHistoryThreadsResult.Item] = []
|
||||
for message in topMessages.values.sorted(by: { $0.id > $1.id }) {
|
||||
guard let threadId = message.threadId else {
|
||||
continue
|
||||
}
|
||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||
threadId: threadId,
|
||||
data: MessageHistoryThreadData(
|
||||
creationDate: 0,
|
||||
isOwnedByMe: true,
|
||||
author: accountPeerId,
|
||||
info: EngineMessageHistoryThread.Info(title: "", icon: nil, iconColor: 0),
|
||||
incomingUnreadCount: 0,
|
||||
maxIncomingReadId: 0,
|
||||
maxKnownMessageId: 0,
|
||||
maxOutgoingReadId: 0,
|
||||
isClosed: false,
|
||||
isHidden: false,
|
||||
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||
),
|
||||
topMessage: message.id.id,
|
||||
unreadMentionsCount: 0,
|
||||
unreadReactionsCount: 0,
|
||||
index: StoredPeerThreadCombinedState.Index(timestamp: message.timestamp, threadId: threadId, messageId: message.id.id)
|
||||
))
|
||||
}
|
||||
|
||||
return LoadMessageHistoryThreadsResult(
|
||||
peerId: accountPeerId,
|
||||
items: items,
|
||||
messages: [],
|
||||
pinnedThreadIds: nil,
|
||||
combinedState: PeerThreadCombinedState(validIndexBoundary: StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)),
|
||||
users: [],
|
||||
chats: []
|
||||
)
|
||||
}
|
||||
|> castError(LoadMessageHistoryThreadsError.self))
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
|
||||
if query != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
flags = 0
|
||||
|
||||
var offsetDate: Int32 = 0
|
||||
var offsetId: Int32 = 0
|
||||
var offsetTopic: Int32 = 0
|
||||
var offsetPeer: Api.InputPeer = .inputPeerEmpty
|
||||
if let offsetIndex = offsetIndex {
|
||||
offsetDate = offsetIndex.timestamp
|
||||
offsetId = offsetIndex.messageId
|
||||
offsetTopic = Int32(clamping: offsetIndex.threadId)
|
||||
//TODO:api
|
||||
offsetPeer = .inputPeerEmpty
|
||||
}
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = network.request(Api.functions.channels.getForumTopics(
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = network.request(Api.functions.messages.getSavedDialogs(
|
||||
flags: flags,
|
||||
channel: inputChannel,
|
||||
q: query,
|
||||
offsetDate: offsetDate,
|
||||
offsetId: offsetId,
|
||||
offsetTopic: offsetTopic,
|
||||
limit: Int32(limit)
|
||||
offsetPeer: offsetPeer,
|
||||
limit: Int32(limit),
|
||||
hash: 0
|
||||
))
|
||||
|> mapError { _ -> LoadMessageHistoryThreadsError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, chats, users, pts):
|
||||
case .savedDialogs(let dialogs, let messages, let chats, let users), .savedDialogsSlice(_, let dialogs, let messages, let chats, let users):
|
||||
var items: [LoadMessageHistoryThreadsResult.Item] = []
|
||||
var pinnedIds: [Int64] = []
|
||||
|
||||
let addedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: true)
|
||||
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: false)
|
||||
}
|
||||
|
||||
let _ = pts
|
||||
var minIndex: StoredPeerThreadCombinedState.Index?
|
||||
|
||||
for topic in topics {
|
||||
switch topic {
|
||||
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
||||
let _ = draft
|
||||
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
pinnedIds.append(Int64(id))
|
||||
for dialog in dialogs {
|
||||
switch dialog {
|
||||
case let .savedDialog(flags, peer, topMessage):
|
||||
if (flags & (1 << 2)) != 0 {
|
||||
pinnedIds.append(peer.peerId.toInt64())
|
||||
}
|
||||
|
||||
let data = MessageHistoryThreadData(
|
||||
creationDate: date,
|
||||
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||
author: fromId.peerId,
|
||||
creationDate: 0,
|
||||
isOwnedByMe: true,
|
||||
author: peer.peerId,
|
||||
info: EngineMessageHistoryThread.Info(
|
||||
title: title,
|
||||
icon: iconEmojiId == 0 ? nil : iconEmojiId,
|
||||
iconColor: iconColor
|
||||
title: "",
|
||||
icon: nil,
|
||||
iconColor: 0
|
||||
),
|
||||
incomingUnreadCount: unreadCount,
|
||||
maxIncomingReadId: readInboxMaxId,
|
||||
incomingUnreadCount: 0,
|
||||
maxIncomingReadId: 0,
|
||||
maxKnownMessageId: topMessage,
|
||||
maxOutgoingReadId: readOutboxMaxId,
|
||||
isClosed: (flags & (1 << 2)) != 0,
|
||||
isHidden: (flags & (1 << 6)) != 0,
|
||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||
maxOutgoingReadId: 0,
|
||||
isClosed: false,
|
||||
isHidden: false,
|
||||
notificationSettings: TelegramPeerNotificationSettings.defaultSettings
|
||||
)
|
||||
|
||||
var topTimestamp = date
|
||||
var topTimestamp: Int32 = 1
|
||||
for message in addedMessages {
|
||||
if message.id.peerId == peerId && message.threadId == Int64(id) {
|
||||
if message.id.peerId == peerId && message.threadId == peer.peerId.toInt64() {
|
||||
topTimestamp = max(topTimestamp, message.timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: Int64(id), messageId: topMessage)
|
||||
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: peer.peerId.toInt64(), messageId: topMessage)
|
||||
if let minIndexValue = minIndex {
|
||||
if topicIndex < minIndexValue {
|
||||
minIndex = topicIndex
|
||||
|
|
@ -668,15 +745,13 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||
}
|
||||
|
||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||
threadId: Int64(id),
|
||||
threadId: peer.peerId.toInt64(),
|
||||
data: data,
|
||||
topMessage: topMessage,
|
||||
unreadMentionsCount: unreadMentionsCount,
|
||||
unreadReactionsCount: unreadReactionsCount,
|
||||
unreadMentionsCount: 0,
|
||||
unreadReactionsCount: 0,
|
||||
index: topicIndex
|
||||
))
|
||||
case .forumTopicDeleted:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -686,7 +761,7 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||
}
|
||||
|
||||
var nextIndex: StoredPeerThreadCombinedState.Index
|
||||
if topics.count != 0 {
|
||||
if dialogs.count != 0 {
|
||||
nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
} else {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
|
|
@ -706,12 +781,154 @@ func _internal_requestMessageHistoryThreads(accountPeerId: PeerId, postbox: Post
|
|||
users: users,
|
||||
chats: chats
|
||||
))
|
||||
case .savedDialogsNotModified:
|
||||
return .complete()
|
||||
}
|
||||
}
|
||||
return signal
|
||||
} else {
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = postbox.transaction { transaction -> Api.InputChannel? in
|
||||
guard let channel = transaction.getPeer(peerId) as? TelegramChannel else {
|
||||
return nil
|
||||
}
|
||||
if !channel.flags.contains(.isForum) {
|
||||
return nil
|
||||
}
|
||||
return apiInputChannel(channel)
|
||||
}
|
||||
|> castError(LoadMessageHistoryThreadsError.self)
|
||||
|> mapToSignal { inputChannel -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
guard let inputChannel = inputChannel else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
var flags: Int32 = 0
|
||||
|
||||
if query != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
|
||||
var offsetDate: Int32 = 0
|
||||
var offsetId: Int32 = 0
|
||||
var offsetTopic: Int32 = 0
|
||||
if let offsetIndex = offsetIndex {
|
||||
offsetDate = offsetIndex.timestamp
|
||||
offsetId = offsetIndex.messageId
|
||||
offsetTopic = Int32(clamping: offsetIndex.threadId)
|
||||
}
|
||||
let signal: Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> = network.request(Api.functions.channels.getForumTopics(
|
||||
flags: flags,
|
||||
channel: inputChannel,
|
||||
q: query,
|
||||
offsetDate: offsetDate,
|
||||
offsetId: offsetId,
|
||||
offsetTopic: offsetTopic,
|
||||
limit: Int32(limit)
|
||||
))
|
||||
|> mapError { _ -> LoadMessageHistoryThreadsError in
|
||||
return .generic
|
||||
}
|
||||
|> mapToSignal { result -> Signal<LoadMessageHistoryThreadsResult, LoadMessageHistoryThreadsError> in
|
||||
switch result {
|
||||
case let .forumTopics(_, _, topics, messages, chats, users, pts):
|
||||
var items: [LoadMessageHistoryThreadsResult.Item] = []
|
||||
var pinnedIds: [Int64] = []
|
||||
|
||||
let addedMessages = messages.compactMap { message -> StoreMessage? in
|
||||
return StoreMessage(apiMessage: message, accountPeerId: accountPeerId, peerIsForum: true)
|
||||
}
|
||||
|
||||
let _ = pts
|
||||
var minIndex: StoredPeerThreadCombinedState.Index?
|
||||
|
||||
for topic in topics {
|
||||
switch topic {
|
||||
case let .forumTopic(flags, id, date, title, iconColor, iconEmojiId, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, unreadReactionsCount, fromId, notifySettings, draft):
|
||||
let _ = draft
|
||||
|
||||
if (flags & (1 << 3)) != 0 {
|
||||
pinnedIds.append(Int64(id))
|
||||
}
|
||||
|
||||
let data = MessageHistoryThreadData(
|
||||
creationDate: date,
|
||||
isOwnedByMe: (flags & (1 << 1)) != 0,
|
||||
author: fromId.peerId,
|
||||
info: EngineMessageHistoryThread.Info(
|
||||
title: title,
|
||||
icon: iconEmojiId == 0 ? nil : iconEmojiId,
|
||||
iconColor: iconColor
|
||||
),
|
||||
incomingUnreadCount: unreadCount,
|
||||
maxIncomingReadId: readInboxMaxId,
|
||||
maxKnownMessageId: topMessage,
|
||||
maxOutgoingReadId: readOutboxMaxId,
|
||||
isClosed: (flags & (1 << 2)) != 0,
|
||||
isHidden: (flags & (1 << 6)) != 0,
|
||||
notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)
|
||||
)
|
||||
|
||||
var topTimestamp = date
|
||||
for message in addedMessages {
|
||||
if message.id.peerId == peerId && message.threadId == Int64(id) {
|
||||
topTimestamp = max(topTimestamp, message.timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
let topicIndex = StoredPeerThreadCombinedState.Index(timestamp: topTimestamp, threadId: Int64(id), messageId: topMessage)
|
||||
if let minIndexValue = minIndex {
|
||||
if topicIndex < minIndexValue {
|
||||
minIndex = topicIndex
|
||||
}
|
||||
} else {
|
||||
minIndex = topicIndex
|
||||
}
|
||||
|
||||
items.append(LoadMessageHistoryThreadsResult.Item(
|
||||
threadId: Int64(id),
|
||||
data: data,
|
||||
topMessage: topMessage,
|
||||
unreadMentionsCount: unreadMentionsCount,
|
||||
unreadReactionsCount: unreadReactionsCount,
|
||||
index: topicIndex
|
||||
))
|
||||
case .forumTopicDeleted:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var pinnedThreadIds: [Int64]?
|
||||
if offsetIndex == nil {
|
||||
pinnedThreadIds = pinnedIds
|
||||
}
|
||||
|
||||
var nextIndex: StoredPeerThreadCombinedState.Index
|
||||
if topics.count != 0 {
|
||||
nextIndex = minIndex ?? StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
} else {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
}
|
||||
if let offsetIndex = offsetIndex, nextIndex == offsetIndex {
|
||||
nextIndex = StoredPeerThreadCombinedState.Index(timestamp: 0, threadId: 0, messageId: 1)
|
||||
}
|
||||
|
||||
let combinedState = PeerThreadCombinedState(validIndexBoundary: nextIndex)
|
||||
|
||||
return .single(LoadMessageHistoryThreadsResult(
|
||||
peerId: peerId,
|
||||
items: items,
|
||||
messages: addedMessages,
|
||||
pinnedThreadIds: pinnedThreadIds,
|
||||
combinedState: combinedState,
|
||||
users: users,
|
||||
chats: chats
|
||||
))
|
||||
}
|
||||
}
|
||||
return signal
|
||||
}
|
||||
|
||||
return signal
|
||||
}
|
||||
|
||||
return signal
|
||||
}
|
||||
|
||||
func applyLoadMessageHistoryThreadsResults(accountPeerId: PeerId, transaction: Transaction, results: [LoadMessageHistoryThreadsResult]) {
|
||||
|
|
@ -722,9 +939,16 @@ func applyLoadMessageHistoryThreadsResults(accountPeerId: PeerId, transaction: T
|
|||
let _ = InternalAccountState.addMessages(transaction: transaction, messages: result.messages, location: .Random)
|
||||
|
||||
for item in result.items {
|
||||
guard let info = StoredMessageHistoryThreadInfo(item.data) else {
|
||||
let info: StoredMessageHistoryThreadInfo?
|
||||
if let data = item.data {
|
||||
info = StoredMessageHistoryThreadInfo(data)
|
||||
} else {
|
||||
info = telegramPostboxSeedConfiguration.automaticThreadIndexInfo(result.peerId, item.threadId)
|
||||
}
|
||||
guard let info else {
|
||||
continue
|
||||
}
|
||||
|
||||
transaction.setMessageHistoryThreadInfo(peerId: result.peerId, threadId: item.threadId, info: info)
|
||||
|
||||
transaction.replaceMessageTagSummary(peerId: result.peerId, threadId: item.threadId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: item.unreadMentionsCount, maxId: item.topMessage)
|
||||
|
|
@ -864,6 +1088,9 @@ public func _internal_searchForumTopics(account: Account, peerId: EnginePeer.Id,
|
|||
guard let index = item.index else {
|
||||
continue
|
||||
}
|
||||
guard let itemData = item.data else {
|
||||
continue
|
||||
}
|
||||
items.append(EngineChatList.Item(
|
||||
id: .forum(item.threadId),
|
||||
index: .forum(pinnedIndex: .none, timestamp: index.timestamp, threadId: index.threadId, namespace: Namespaces.Message.Cloud, id: index.messageId),
|
||||
|
|
@ -878,10 +1105,10 @@ public func _internal_searchForumTopics(account: Account, peerId: EnginePeer.Id,
|
|||
hasUnseenReactions: false,
|
||||
forumTopicData: EngineChatList.ForumTopicData(
|
||||
id: item.threadId,
|
||||
title: item.data.info.title,
|
||||
iconFileId: item.data.info.icon,
|
||||
iconColor: item.data.info.iconColor,
|
||||
maxOutgoingReadMessageId: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Cloud, id: item.data.maxOutgoingReadId),
|
||||
title: itemData.info.title,
|
||||
iconFileId: itemData.info.icon,
|
||||
iconColor: itemData.info.iconColor,
|
||||
maxOutgoingReadMessageId: EngineMessage.Id(peerId: peerId, namespace: Namespaces.Message.Cloud, id: itemData.maxOutgoingReadId),
|
||||
isUnread: false
|
||||
),
|
||||
topForumTopicItems: [],
|
||||
|
|
|
|||
|
|
@ -573,7 +573,9 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
|||
var quote = replyToMessageId.quote
|
||||
let isQuote = quote != nil
|
||||
if let replyMessage = transaction.getMessage(replyToMessageId.messageId) {
|
||||
threadMessageId = replyMessage.effectiveReplyThreadMessageId
|
||||
if replyMessage.id.namespace == Namespaces.Message.Cloud, let threadId = replyMessage.threadId {
|
||||
threadMessageId = MessageId(peerId: replyMessage.id.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))
|
||||
}
|
||||
if quote == nil, replyToMessageId.messageId.peerId != peerId {
|
||||
let nsText = replyMessage.text as NSString
|
||||
var replyMedia: Media?
|
||||
|
|
@ -712,14 +714,14 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
|||
threadId = threadIdValue
|
||||
} else {
|
||||
if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .group = channel.info {
|
||||
threadId = makeMessageThreadId(replyToMessageId.messageId)
|
||||
threadId = Int64(replyToMessageId.messageId.id)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
threadId = threadIdValue
|
||||
}
|
||||
} else if let channel = message.peers[message.id.peerId] as? TelegramChannel, case .group = channel.info {
|
||||
threadId = makeMessageThreadId(replyToMessageId.messageId)
|
||||
threadId = Int64(replyToMessageId.messageId.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -902,7 +904,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId,
|
|||
}
|
||||
} else if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if let threadMessageId = attribute.threadMessageId {
|
||||
threadId = makeMessageThreadId(threadMessageId)
|
||||
threadId = Int64(threadMessageId.id)
|
||||
}
|
||||
} else if let attribute = attribute as? SendAsMessageAttribute {
|
||||
if let peer = transaction.getPeer(attribute.peerId) {
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ private func sendUploadedMessageContent(
|
|||
var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
|
||||
var messageEntities: [Api.MessageEntity]?
|
||||
var replyMessageId: Int32? = threadId.flatMap { threadId in
|
||||
makeThreadIdMessageId(peerId: peerId, threadId: threadId).id
|
||||
return Int32(clamping: threadId)
|
||||
}
|
||||
var replyToStoryId: StoryId?
|
||||
var scheduleTime: Int32?
|
||||
|
|
|
|||
|
|
@ -1444,7 +1444,7 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
|
|||
case let .updateChannelUserTyping(_, channelId, topMsgId, userId, type):
|
||||
if let date = updatesDate, date + 60 > serverTime {
|
||||
let channelPeerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: PeerId.Id._internalFromInt64Value(channelId))
|
||||
let threadId = topMsgId.flatMap { makeMessageThreadId(MessageId(peerId: channelPeerId, namespace: Namespaces.Message.Cloud, id: $0)) }
|
||||
let threadId = topMsgId.flatMap { Int64($0) }
|
||||
|
||||
let activity = PeerInputActivity(apiType: type, peerId: nil, timestamp: date)
|
||||
var category: PeerActivitySpace.Category = .global
|
||||
|
|
@ -3480,16 +3480,16 @@ func replayFinalState(
|
|||
var removedCount: Int = 0
|
||||
var peers: [ReplyThreadUserMessage] = []
|
||||
}
|
||||
var messageThreadStatsDifferences: [MessageId: MessageThreadStatsRecord] = [:]
|
||||
func addMessageThreadStatsDifference(threadMessageId: MessageId, remove: Int, addedMessagePeer: PeerId?, addedMessageId: MessageId?, isOutgoing: Bool) {
|
||||
if let value = messageThreadStatsDifferences[threadMessageId] {
|
||||
var messageThreadStatsDifferences: [MessageThreadKey: MessageThreadStatsRecord] = [:]
|
||||
func addMessageThreadStatsDifference(threadKey: MessageThreadKey, remove: Int, addedMessagePeer: PeerId?, addedMessageId: MessageId?, isOutgoing: Bool) {
|
||||
if let value = messageThreadStatsDifferences[threadKey] {
|
||||
value.removedCount += remove
|
||||
if let addedMessagePeer = addedMessagePeer, let addedMessageId = addedMessageId {
|
||||
value.peers.append(ReplyThreadUserMessage(id: addedMessagePeer, messageId: addedMessageId, isOutgoing: isOutgoing))
|
||||
}
|
||||
} else {
|
||||
let value = MessageThreadStatsRecord()
|
||||
messageThreadStatsDifferences[threadMessageId] = value
|
||||
messageThreadStatsDifferences[threadKey] = value
|
||||
value.removedCount = remove
|
||||
if let addedMessagePeer = addedMessagePeer, let addedMessageId = addedMessageId {
|
||||
value.peers.append(ReplyThreadUserMessage(id: addedMessagePeer, messageId: addedMessageId, isOutgoing: isOutgoing))
|
||||
|
|
@ -3540,10 +3540,9 @@ func replayFinalState(
|
|||
}
|
||||
}
|
||||
|
||||
let messageThreadId = makeThreadIdMessageId(peerId: message.id.peerId, threadId: threadId)
|
||||
if id.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
if !transaction.messageExists(id: id) {
|
||||
addMessageThreadStatsDifference(threadMessageId: messageThreadId, remove: 0, addedMessagePeer: message.authorId, addedMessageId: id, isOutgoing: !message.flags.contains(.Incoming))
|
||||
addMessageThreadStatsDifference(threadKey: MessageThreadKey(peerId: message.id.peerId, threadId: threadId), remove: 0, addedMessagePeer: message.authorId, addedMessageId: id, isOutgoing: !message.flags.contains(.Incoming))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3736,7 +3735,7 @@ func replayFinalState(
|
|||
deletedMessageIds.append(contentsOf: ids.map { .global($0) })
|
||||
case let .DeleteMessages(ids):
|
||||
_internal_deleteMessages(transaction: transaction, mediaBox: mediaBox, ids: ids, manualAddMessageThreadStatsDifference: { id, add, remove in
|
||||
addMessageThreadStatsDifference(threadMessageId: id, remove: remove, addedMessagePeer: nil, addedMessageId: nil, isOutgoing: false)
|
||||
addMessageThreadStatsDifference(threadKey: id, remove: remove, addedMessagePeer: nil, addedMessageId: nil, isOutgoing: false)
|
||||
})
|
||||
deletedMessageIds.append(contentsOf: ids.map { .messageId($0) })
|
||||
case let .UpdateMinAvailableMessage(id):
|
||||
|
|
@ -4784,8 +4783,8 @@ func replayFinalState(
|
|||
// }
|
||||
// }
|
||||
|
||||
for (threadMessageId, difference) in messageThreadStatsDifferences {
|
||||
updateMessageThreadStats(transaction: transaction, threadMessageId: threadMessageId, removedCount: difference.removedCount, addedMessagePeers: difference.peers)
|
||||
for (threadKey, difference) in messageThreadStatsDifferences {
|
||||
updateMessageThreadStats(transaction: transaction, threadKey: threadKey, removedCount: difference.removedCount, addedMessagePeers: difference.peers)
|
||||
}
|
||||
|
||||
if !peerActivityTimestamps.isEmpty {
|
||||
|
|
|
|||
|
|
@ -1088,7 +1088,7 @@ public final class AccountStateManager {
|
|||
for attr in first.attributes {
|
||||
if let attribute = attr as? ReplyMessageAttribute {
|
||||
if let threadId = attribute.threadMessageId {
|
||||
threadData = transaction.getMessageHistoryThreadInfo(peerId: first.id.peerId, threadId: makeMessageThreadId(threadId))?.data.get(MessageHistoryThreadData.self)
|
||||
threadData = transaction.getMessageHistoryThreadInfo(peerId: first.id.peerId, threadId: Int64(threadId.id))?.data.get(MessageHistoryThreadData.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1999,7 +1999,7 @@ public func messagesForNotification(transaction: Transaction, id: MessageId, alw
|
|||
}
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if let threadId = attribute.threadMessageId {
|
||||
threadData = transaction.getMessageHistoryThreadInfo(peerId: message.id.peerId, threadId: makeMessageThreadId(threadId))?.data.get(MessageHistoryThreadData.self)
|
||||
threadData = transaction.getMessageHistoryThreadInfo(peerId: message.id.peerId, threadId: Int64(threadId.id))?.data.get(MessageHistoryThreadData.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
|
|||
var updatedTimestamp: Int32?
|
||||
if let apiMessage = apiMessage {
|
||||
switch apiMessage {
|
||||
case let .message(_, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
updatedTimestamp = date
|
||||
case .messageEmpty:
|
||||
break
|
||||
|
|
@ -287,9 +287,8 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes
|
|||
if let updatedMessage = updatedMessage, case let .Id(updatedId) = updatedMessage.id {
|
||||
if message.id.namespace == Namespaces.Message.Local && updatedId.namespace == Namespaces.Message.Cloud && updatedId.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
if let threadId = updatedMessage.threadId {
|
||||
let messageThreadId = makeThreadIdMessageId(peerId: updatedMessage.id.peerId, threadId: threadId)
|
||||
if let authorId = updatedMessage.authorId {
|
||||
updateMessageThreadStats(transaction: transaction, threadMessageId: messageThreadId, removedCount: 0, addedMessagePeers: [ReplyThreadUserMessage(id: authorId, messageId: updatedId, isOutgoing: true)])
|
||||
updateMessageThreadStats(transaction: transaction, threadKey: MessageThreadKey(peerId: updatedMessage.id.peerId, threadId: threadId), removedCount: 0, addedMessagePeers: [ReplyThreadUserMessage(id: authorId, messageId: updatedId, isOutgoing: true)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ final class HistoryViewStateValidationContexts {
|
|||
context.batchReferences[messageId] = batch
|
||||
}
|
||||
|
||||
disposable.set((validateReplyThreadMessagesBatch(postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: peerId, threadMessageId: makeThreadIdMessageId(peerId: peerId, threadId: threadId).id, tag: view.tagMask, messageIds: messages)
|
||||
disposable.set((validateReplyThreadMessagesBatch(postbox: self.postbox, network: self.network, accountPeerId: self.accountPeerId, peerId: peerId, threadMessageId: Int32(clamping: threadId), tag: view.tagMask, messageIds: messages)
|
||||
|> deliverOn(self.queue)).start(completed: { [weak self, weak batch] in
|
||||
if let strongSelf = self, let context = strongSelf.contexts[id], let batch = batch {
|
||||
var completedMessageIds: [MessageId] = []
|
||||
|
|
@ -512,7 +512,7 @@ private func validateChannelMessagesBatch(postbox: Postbox, network: Network, ac
|
|||
} else if tag == MessageTags.unseenReaction {
|
||||
requestSignal = network.request(Api.functions.messages.getUnreadReactions(flags: 0, peer: inputPeer, topMsgId: nil, offsetId: messageIds[messageIds.count - 1].id + 1, addOffset: 0, limit: Int32(messageIds.count), maxId: messageIds[messageIds.count - 1].id + 1, minId: messageIds[0].id - 1))
|
||||
} else if let filter = messageFilterForTagMask(tag) {
|
||||
requestSignal = network.request(Api.functions.messages.search(flags: 0, peer: inputPeer, q: "", fromId: nil, topMsgId: nil, filter: filter, minDate: 0, maxDate: 0, offsetId: messageIds[messageIds.count - 1].id + 1, addOffset: 0, limit: Int32(messageIds.count), maxId: messageIds[messageIds.count - 1].id + 1, minId: messageIds[0].id - 1, hash: hash))
|
||||
requestSignal = network.request(Api.functions.messages.search(flags: 0, peer: inputPeer, q: "", fromId: nil, savedPeerId: nil, topMsgId: nil, filter: filter, minDate: 0, maxDate: 0, offsetId: messageIds[messageIds.count - 1].id + 1, addOffset: 0, limit: Int32(messageIds.count), maxId: messageIds[messageIds.count - 1].id + 1, minId: messageIds[0].id - 1, hash: hash))
|
||||
} else {
|
||||
assertionFailure()
|
||||
requestSignal = .complete()
|
||||
|
|
@ -582,7 +582,7 @@ private func validateReplyThreadMessagesBatch(postbox: Postbox, network: Network
|
|||
var flags: Int32 = 0
|
||||
flags |= (1 << 1)
|
||||
|
||||
requestSignal = network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: "", fromId: nil, topMsgId: threadMessageId, filter: filter, minDate: 0, maxDate: 0, offsetId: messageIds[messageIds.count - 1].id + 1, addOffset: 0, limit: Int32(messageIds.count), maxId: messageIds[messageIds.count - 1].id + 1, minId: messageIds[0].id - 1, hash: hash))
|
||||
requestSignal = network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: "", fromId: nil, savedPeerId: nil, topMsgId: threadMessageId, filter: filter, minDate: 0, maxDate: 0, offsetId: messageIds[messageIds.count - 1].id + 1, addOffset: 0, limit: Int32(messageIds.count), maxId: messageIds[messageIds.count - 1].id + 1, minId: messageIds[0].id - 1, hash: hash))
|
||||
} else {
|
||||
return .complete()
|
||||
}
|
||||
|
|
@ -621,7 +621,7 @@ private func validateReplyThreadMessagesBatch(postbox: Postbox, network: Network
|
|||
return .complete()
|
||||
}
|
||||
|
||||
return validateReplyThreadBatch(postbox: postbox, network: network, transaction: transaction, accountPeerId: accountPeerId, peerId: peerId, threadId: makeMessageThreadId(MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: threadMessageId)), signal: signal, previous: previous, messageNamespace: Namespaces.Message.Cloud)
|
||||
return validateReplyThreadBatch(postbox: postbox, network: network, transaction: transaction, accountPeerId: accountPeerId, peerId: peerId, threadId: Int64(threadMessageId), signal: signal, previous: previous, messageNamespace: Namespaces.Message.Cloud)
|
||||
}
|
||||
|> switchToLatest
|
||||
}
|
||||
|
|
|
|||
|
|
@ -335,16 +335,29 @@ enum FetchMessageHistoryHoleThreadInput: CustomStringConvertible {
|
|||
}
|
||||
}
|
||||
|
||||
var requestThreadId: MessageId? {
|
||||
func requestThreadId(accountPeerId: PeerId) -> Int64? {
|
||||
switch self {
|
||||
case let .direct(peerId, threadId):
|
||||
if let threadId = threadId {
|
||||
return makeThreadIdMessageId(peerId: peerId, threadId: threadId)
|
||||
if let threadId = threadId, peerId != accountPeerId {
|
||||
return threadId
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case let .threadFromChannel(channelMessageId):
|
||||
return channelMessageId
|
||||
return Int64(channelMessageId.id)
|
||||
}
|
||||
}
|
||||
|
||||
func requestSubPeerId(accountPeerId: PeerId) -> PeerId? {
|
||||
switch self {
|
||||
case let .direct(peerId, threadId):
|
||||
if let threadId = threadId, peerId == accountPeerId {
|
||||
return PeerId(threadId)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case .threadFromChannel:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -360,10 +373,6 @@ struct FetchMessageHistoryHoleResult: Equatable {
|
|||
func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryHoleSource, postbox: Postbox, peerInput: FetchMessageHistoryHoleThreadInput, namespace: MessageId.Namespace, direction: MessageHistoryViewRelativeHoleDirection, space: MessageHistoryHoleSpace, count rawCount: Int) -> Signal<FetchMessageHistoryHoleResult?, NoError> {
|
||||
let count = min(100, rawCount)
|
||||
|
||||
if peerInput.requestThreadId != nil, case .everywhere = space, case .aroundId = direction {
|
||||
assert(true)
|
||||
}
|
||||
|
||||
return postbox.stateView()
|
||||
|> mapToSignal { view -> Signal<AuthorizedAccountState, NoError> in
|
||||
if let state = view.state as? AuthorizedAccountState {
|
||||
|
|
@ -374,15 +383,15 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||
}
|
||||
|> take(1)
|
||||
|> mapToSignal { _ -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||
return postbox.transaction { transaction -> (Peer?, Int64) in
|
||||
return postbox.transaction { transaction -> (Peer?, Int64, Peer?) in
|
||||
switch peerInput {
|
||||
case let .direct(peerId, _):
|
||||
return (transaction.getPeer(peerId), 0)
|
||||
return (transaction.getPeer(peerId), 0, peerInput.requestSubPeerId(accountPeerId: accountPeerId).flatMap(transaction.getPeer))
|
||||
case let .threadFromChannel(channelMessageId):
|
||||
return (transaction.getPeer(channelMessageId.peerId), 0)
|
||||
return (transaction.getPeer(channelMessageId.peerId), 0, nil)
|
||||
}
|
||||
}
|
||||
|> mapToSignal { (peer, hash) -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||
|> mapToSignal { (peer, hash, subPeer) -> Signal<FetchMessageHistoryHoleResult?, NoError> in
|
||||
guard let peer = peer else {
|
||||
return .single(FetchMessageHistoryHoleResult(removedIndices: IndexSet(), strictRemovedIndices: IndexSet(), actualPeerId: nil, actualThreadId: nil, ids: []))
|
||||
}
|
||||
|
|
@ -397,284 +406,345 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||
let minMaxRange: ClosedRange<MessageId.Id>
|
||||
|
||||
switch space {
|
||||
case .everywhere:
|
||||
if let requestThreadId = peerInput.requestThreadId {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
case .everywhere:
|
||||
if let requestThreadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
minMaxRange = 1 ... (Int32.max - 1)
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getReplies(peer: inputPeer, msgId: requestThreadId.id, offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: hash))
|
||||
} else {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id == 1 ? 0 : end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
minMaxRange = 1 ... Int32.max - 1
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: 0))
|
||||
}
|
||||
case let .tag(tag):
|
||||
assert(tag.containsSingleElement)
|
||||
if tag == .unseenPersonalMessage {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
minMaxRange = 1 ... Int32.max - 1
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = threadId.id
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getUnreadMentions(flags: flags, peer: inputPeer, topMsgId: topMsgId, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId))
|
||||
} else if tag == .unseenReaction {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
|
||||
minMaxRange = 1 ... Int32.max - 1
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId {
|
||||
flags |= (1 << 0)
|
||||
topMsgId = threadId.id
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getUnreadReactions(flags: flags, peer: inputPeer, topMsgId: topMsgId, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId))
|
||||
} else if tag == .liveLocation {
|
||||
let selectedLimit = count
|
||||
|
||||
switch direction {
|
||||
case .aroundId, .range:
|
||||
implicitelyFillHole = true
|
||||
}
|
||||
minMaxRange = 1 ... (Int32.max - 1)
|
||||
request = source.request(Api.functions.messages.getRecentLocations(peer: inputPeer, limit: Int32(selectedLimit), hash: 0))
|
||||
} else if let filter = messageFilterForTagMask(tag) {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
|
||||
minMaxRange = 1 ... (Int32.max - 1)
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = threadId.id
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: "", fromId: nil, topMsgId: topMsgId, filter: filter, minDate: 0, maxDate: 0, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: 0))
|
||||
} else {
|
||||
assertionFailure()
|
||||
minMaxRange = 1 ... 1
|
||||
request = .never()
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getReplies(peer: inputPeer, msgId: Int32(clamping: requestThreadId), offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: hash))
|
||||
} else if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId) {
|
||||
guard let subPeer, subPeer.id == subPeerId, let inputSubPeer = apiInputPeer(subPeer) else {
|
||||
Logger.shared.log("fetchMessageHistoryHole", "subPeer not available")
|
||||
return .never()
|
||||
}
|
||||
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
|
||||
minMaxRange = 1 ... (Int32.max - 1)
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getSavedHistory(peer: inputSubPeer, offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: hash))
|
||||
} else {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id == 1 ? 0 : end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
minMaxRange = 1 ... Int32.max - 1
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: offsetId, offsetDate: 0, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: 0))
|
||||
}
|
||||
case let .tag(tag):
|
||||
assert(tag.containsSingleElement)
|
||||
if tag == .unseenPersonalMessage {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
|
||||
minMaxRange = 1 ... Int32.max - 1
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getUnreadMentions(flags: flags, peer: inputPeer, topMsgId: topMsgId, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId))
|
||||
} else if tag == .unseenReaction {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
|
||||
minMaxRange = 1 ... Int32.max - 1
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
flags |= (1 << 0)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.getUnreadReactions(flags: flags, peer: inputPeer, topMsgId: topMsgId, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId))
|
||||
} else if tag == .liveLocation {
|
||||
let selectedLimit = count
|
||||
|
||||
switch direction {
|
||||
case .aroundId, .range:
|
||||
implicitelyFillHole = true
|
||||
}
|
||||
minMaxRange = 1 ... (Int32.max - 1)
|
||||
request = source.request(Api.functions.messages.getRecentLocations(peer: inputPeer, limit: Int32(selectedLimit), hash: 0))
|
||||
} else if let filter = messageFilterForTagMask(tag) {
|
||||
let offsetId: Int32
|
||||
let addOffset: Int32
|
||||
let selectedLimit = count
|
||||
let maxId: Int32
|
||||
let minId: Int32
|
||||
|
||||
switch direction {
|
||||
case let .range(start, end):
|
||||
if start.id <= end.id {
|
||||
offsetId = start.id <= 1 ? 1 : (start.id - 1)
|
||||
addOffset = Int32(-selectedLimit)
|
||||
maxId = end.id
|
||||
minId = start.id - 1
|
||||
|
||||
let rangeStartId = start.id
|
||||
let rangeEndId = min(end.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
} else {
|
||||
offsetId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
addOffset = 0
|
||||
maxId = start.id == Int32.max ? start.id : (start.id + 1)
|
||||
minId = end.id
|
||||
|
||||
let rangeStartId = end.id
|
||||
let rangeEndId = min(start.id, Int32.max - 1)
|
||||
if rangeStartId <= rangeEndId {
|
||||
minMaxRange = rangeStartId ... rangeEndId
|
||||
} else {
|
||||
minMaxRange = rangeStartId ... rangeStartId
|
||||
assertionFailure()
|
||||
}
|
||||
}
|
||||
case let .aroundId(id):
|
||||
offsetId = id.id
|
||||
addOffset = Int32(-selectedLimit / 2)
|
||||
maxId = Int32.max
|
||||
minId = 1
|
||||
|
||||
minMaxRange = 1 ... (Int32.max - 1)
|
||||
}
|
||||
|
||||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = peerInput.requestThreadId(accountPeerId: accountPeerId) {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
|
||||
var savedPeerId: Api.InputPeer?
|
||||
if let subPeerId = peerInput.requestSubPeerId(accountPeerId: accountPeerId), let subPeer = subPeer, subPeer.id == subPeerId {
|
||||
if let inputPeer = apiInputPeer(subPeer) {
|
||||
flags |= 1 << 2
|
||||
savedPeerId = inputPeer
|
||||
}
|
||||
}
|
||||
|
||||
request = source.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: "", fromId: nil, savedPeerId: savedPeerId, topMsgId: topMsgId, filter: filter, minDate: 0, maxDate: 0, offsetId: offsetId, addOffset: addOffset, limit: Int32(selectedLimit), maxId: maxId, minId: minId, hash: 0))
|
||||
} else {
|
||||
assertionFailure()
|
||||
minMaxRange = 1 ... 1
|
||||
request = .never()
|
||||
}
|
||||
}
|
||||
|
||||
return request
|
||||
|
|
@ -784,7 +854,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||
}
|
||||
|
||||
print("fetchMessageHistoryHole for \(peerInput) space \(space) done")
|
||||
if peerInput.requestThreadId != nil, case .everywhere = space, case .aroundId = direction {
|
||||
if peerInput.requestThreadId(accountPeerId: accountPeerId) != nil, case .everywhere = space, case .aroundId = direction {
|
||||
assert(true)
|
||||
}
|
||||
|
||||
|
|
@ -797,7 +867,7 @@ func fetchMessageHistoryHole(accountPeerId: PeerId, source: FetchMessageHistoryH
|
|||
case let .aroundId(aroundId):
|
||||
filledRange = min(aroundId.id, messageRange.lowerBound) ... max(aroundId.id, messageRange.upperBound)
|
||||
strictFilledIndices = IndexSet(integersIn: Int(min(aroundId.id, messageRange.lowerBound)) ... Int(max(aroundId.id, messageRange.upperBound)))
|
||||
if peerInput.requestThreadId != nil {
|
||||
if peerInput.requestThreadId(accountPeerId: accountPeerId) != nil {
|
||||
if ids.count <= count / 2 - 1 {
|
||||
filledRange = minMaxRange
|
||||
}
|
||||
|
|
@ -973,7 +1043,7 @@ func fetchCallListHole(network: Network, postbox: Postbox, accountPeerId: PeerId
|
|||
offset = single((holeIndex.timestamp, min(holeIndex.id.id, Int32.max - 1) + 1, Api.InputPeer.inputPeerEmpty), NoError.self)
|
||||
return offset
|
||||
|> mapToSignal { (timestamp, id, peer) -> Signal<Void, NoError> in
|
||||
let searchResult = network.request(Api.functions.messages.search(flags: 0, peer: .inputPeerEmpty, q: "", fromId: nil, topMsgId: nil, filter: .inputMessagesFilterPhoneCalls(flags: 0), minDate: 0, maxDate: holeIndex.timestamp, offsetId: 0, addOffset: 0, limit: limit, maxId: holeIndex.id.id, minId: 0, hash: 0))
|
||||
let searchResult = network.request(Api.functions.messages.search(flags: 0, peer: .inputPeerEmpty, q: "", fromId: nil, savedPeerId: nil, topMsgId: nil, filter: .inputMessagesFilterPhoneCalls(flags: 0), minDate: 0, maxDate: holeIndex.timestamp, offsetId: 0, addOffset: 0, limit: limit, maxId: holeIndex.id.id, minId: 0, hash: 0))
|
||||
|> retryRequest
|
||||
|> mapToSignal { result -> Signal<Void, NoError> in
|
||||
let messages: [Api.Message]
|
||||
|
|
|
|||
|
|
@ -177,11 +177,11 @@ private func requestActivity(postbox: Postbox, network: Network, accountPeerId:
|
|||
|
||||
if let inputPeer = apiInputPeer(peer) {
|
||||
var flags: Int32 = 0
|
||||
let topMessageId = threadId.flatMap { makeThreadIdMessageId(peerId: peerId, threadId: $0) }
|
||||
let topMessageId = threadId.flatMap { Int32(clamping: $0) }
|
||||
if topMessageId != nil {
|
||||
flags |= 1 << 0
|
||||
}
|
||||
return network.request(Api.functions.messages.setTyping(flags: flags, peer: inputPeer, topMsgId: topMessageId?.id, action: actionFromActivity(activity)))
|
||||
return network.request(Api.functions.messages.setTyping(flags: flags, peer: inputPeer, topMsgId: topMessageId, action: actionFromActivity(activity)))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(.boolFalse)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 169
|
||||
return 170
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
|||
self.putNext(groups)
|
||||
}
|
||||
case let .updateShortChatMessage(flags, id, fromId, chatId, message, pts, ptsCount, date, fwdFrom, viaBotId, replyHeader, entities, ttlPeriod):
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: .peerUser(userId: fromId), peerId: Api.Peer.peerChat(chatId: chatId), fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod)
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: .peerUser(userId: fromId), peerId: Api.Peer.peerChat(chatId: chatId), savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
|
|
@ -74,7 +74,7 @@ class UpdateMessageService: NSObject, MTMessageService {
|
|||
|
||||
let generatedPeerId = Api.Peer.peerUser(userId: userId)
|
||||
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: generatedFromId, peerId: generatedPeerId, fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod)
|
||||
let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: generatedFromId, peerId: generatedPeerId, savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod)
|
||||
let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount)
|
||||
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
|
||||
if groups.count != 0 {
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ extension Api.MessageMedia {
|
|||
extension Api.Message {
|
||||
var rawId: Int32 {
|
||||
switch self {
|
||||
case let .message(_, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return id
|
||||
case let .messageEmpty(_, id, _):
|
||||
return id
|
||||
|
|
@ -115,7 +115,7 @@ extension Api.Message {
|
|||
|
||||
func id(namespace: MessageId.Namespace = Namespaces.Message.Cloud) -> MessageId? {
|
||||
switch self {
|
||||
case let .message(_, id, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, id, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
let peerId: PeerId = messagePeerId.peerId
|
||||
return MessageId(peerId: peerId, namespace: namespace, id: id)
|
||||
case let .messageEmpty(_, id, peerId):
|
||||
|
|
@ -132,7 +132,7 @@ extension Api.Message {
|
|||
|
||||
var peerId: PeerId? {
|
||||
switch self {
|
||||
case let .message(_, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
let peerId: PeerId = messagePeerId.peerId
|
||||
return peerId
|
||||
case let .messageEmpty(_, _, peerId):
|
||||
|
|
@ -145,7 +145,7 @@ extension Api.Message {
|
|||
|
||||
var timestamp: Int32? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return date
|
||||
case let .messageService(_, _, _, _, _, date, _, _):
|
||||
return date
|
||||
|
|
@ -156,7 +156,7 @@ extension Api.Message {
|
|||
|
||||
var preCachedResources: [(MediaResource, Data)]? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return media?.preCachedResources
|
||||
default:
|
||||
return nil
|
||||
|
|
@ -165,7 +165,7 @@ extension Api.Message {
|
|||
|
||||
var preCachedStories: [StoryId: Api.StoryItem]? {
|
||||
switch self {
|
||||
case let .message(_, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _):
|
||||
case let .message(_, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _):
|
||||
return media?.preCachedStories
|
||||
default:
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -138,12 +138,3 @@ public class ReplyStoryAttribute: MessageAttribute {
|
|||
encoder.encode(self.storyId, forKey: "i")
|
||||
}
|
||||
}
|
||||
|
||||
public extension Message {
|
||||
var effectiveReplyThreadMessageId: MessageId? {
|
||||
if let threadId = self.threadId {
|
||||
return makeThreadIdMessageId(peerId: self.id.peerId, threadId: threadId)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,6 +190,13 @@ public let telegramPostboxSeedConfiguration: SeedConfiguration = {
|
|||
}
|
||||
}
|
||||
return false
|
||||
},
|
||||
automaticThreadIndexInfo: { peerId, _ in
|
||||
if peerId.namespace == Namespaces.Peer.CloudUser {
|
||||
return StoredMessageHistoryThreadInfo(data: CodableEntry(data: Data()), summary: StoredMessageHistoryThreadInfo.Summary(totalUnreadCount: 0, mutedUntil: nil))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
)
|
||||
}()
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ func addMessageMediaResourceIdsToRemove(message: Message, resourceIds: inout [Me
|
|||
}
|
||||
}
|
||||
|
||||
public func _internal_deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [MessageId], deleteMedia: Bool = true, manualAddMessageThreadStatsDifference: ((MessageId, Int, Int) -> Void)? = nil) {
|
||||
public func _internal_deleteMessages(transaction: Transaction, mediaBox: MediaBox, ids: [MessageId], deleteMedia: Bool = true, manualAddMessageThreadStatsDifference: ((MessageThreadKey, Int, Int) -> Void)? = nil) {
|
||||
var resourceIds: [MediaResourceId] = []
|
||||
if deleteMedia {
|
||||
for id in ids {
|
||||
|
|
@ -40,12 +40,12 @@ public func _internal_deleteMessages(transaction: Transaction, mediaBox: MediaBo
|
|||
if id.peerId.namespace == Namespaces.Peer.CloudChannel && id.namespace == Namespaces.Message.Cloud {
|
||||
if let message = transaction.getMessage(id) {
|
||||
if let threadId = message.threadId {
|
||||
let messageThreadId = makeThreadIdMessageId(peerId: message.id.peerId, threadId: threadId)
|
||||
let messageThreadKey = MessageThreadKey(peerId: message.id.peerId, threadId: threadId)
|
||||
if id.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
if let manualAddMessageThreadStatsDifference = manualAddMessageThreadStatsDifference {
|
||||
manualAddMessageThreadStatsDifference(messageThreadId, 0, 1)
|
||||
manualAddMessageThreadStatsDifference(messageThreadKey, 0, 1)
|
||||
} else {
|
||||
updateMessageThreadStats(transaction: transaction, threadMessageId: messageThreadId, removedCount: 1, addedMessagePeers: [])
|
||||
updateMessageThreadStats(transaction: transaction, threadKey: messageThreadKey, removedCount: 1, addedMessagePeers: [])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ private struct DiscussionMessage {
|
|||
private class ReplyThreadHistoryContextImpl {
|
||||
private let queue: Queue
|
||||
private let account: Account
|
||||
private let messageId: MessageId
|
||||
private let peerId: PeerId
|
||||
private let threadId: Int64
|
||||
|
||||
private var currentHole: (MessageHistoryHolesViewEntry, Disposable)?
|
||||
|
||||
|
|
@ -68,7 +69,10 @@ private class ReplyThreadHistoryContextImpl {
|
|||
init(queue: Queue, account: Account, data: ChatReplyThreadMessage) {
|
||||
self.queue = queue
|
||||
self.account = account
|
||||
self.messageId = data.messageId
|
||||
self.peerId = data.peerId
|
||||
self.threadId = data.threadId
|
||||
|
||||
let referencedMessageId = MessageId(peerId: data.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: data.threadId))
|
||||
|
||||
self.maxReadOutgoingMessageIdValue = data.maxReadOutgoingMessageId
|
||||
self.maxReadOutgoingMessageId.set(.single(self.maxReadOutgoingMessageIdValue))
|
||||
|
|
@ -79,7 +83,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||
self.unreadCount.set(.single(self.unreadCountValue))
|
||||
|
||||
self.initialStateDisposable = (account.postbox.transaction { transaction -> State in
|
||||
var indices = transaction.getThreadIndexHoles(peerId: data.messageId.peerId, threadId: makeMessageThreadId(data.messageId), namespace: Namespaces.Message.Cloud)
|
||||
var indices = transaction.getThreadIndexHoles(peerId: data.peerId, threadId: data.threadId, namespace: Namespaces.Message.Cloud)
|
||||
indices.subtract(data.initialFilledHoles)
|
||||
|
||||
/*let isParticipant = transaction.getPeerChatListIndex(data.messageId.peerId) != nil
|
||||
|
|
@ -96,7 +100,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||
indices.removeAll()
|
||||
}
|
||||
|
||||
return State(messageId: data.messageId, holeIndices: [Namespaces.Message.Cloud: indices], maxReadIncomingMessageId: data.maxReadIncomingMessageId, maxReadOutgoingMessageId: data.maxReadOutgoingMessageId)
|
||||
return State(messageId: referencedMessageId, holeIndices: [Namespaces.Message.Cloud: indices], maxReadIncomingMessageId: data.maxReadIncomingMessageId, maxReadOutgoingMessageId: data.maxReadOutgoingMessageId)
|
||||
}
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] state in
|
||||
guard let strongSelf = self else {
|
||||
|
|
@ -106,7 +110,7 @@ private class ReplyThreadHistoryContextImpl {
|
|||
strongSelf.state.set(.single(state))
|
||||
})
|
||||
|
||||
let threadId = makeMessageThreadId(messageId)
|
||||
let threadId = self.threadId
|
||||
|
||||
self.holesDisposable = (account.postbox.messageHistoryHolesView()
|
||||
|> map { view -> MessageHistoryHolesViewEntry? in
|
||||
|
|
@ -133,15 +137,15 @@ private class ReplyThreadHistoryContextImpl {
|
|||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
if let value = outgoing[data.messageId] {
|
||||
strongSelf.maxReadOutgoingMessageIdValue = MessageId(peerId: data.messageId.peerId, namespace: Namespaces.Message.Cloud, id: value)
|
||||
if let value = outgoing[referencedMessageId] {
|
||||
strongSelf.maxReadOutgoingMessageIdValue = MessageId(peerId: data.peerId, namespace: Namespaces.Message.Cloud, id: value)
|
||||
}
|
||||
})
|
||||
|
||||
let accountPeerId = account.peerId
|
||||
|
||||
let updateInitialState: Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> = account.postbox.transaction { transaction -> Peer? in
|
||||
return transaction.getPeer(data.messageId.peerId)
|
||||
return transaction.getPeer(data.peerId)
|
||||
}
|
||||
|> castError(FetchChannelReplyThreadMessageError.self)
|
||||
|> mapToSignal { peer -> Signal<DiscussionMessage, FetchChannelReplyThreadMessageError> in
|
||||
|
|
@ -151,8 +155,8 @@ private class ReplyThreadHistoryContextImpl {
|
|||
guard let inputPeer = apiInputPeer(peer) else {
|
||||
return .fail(.generic)
|
||||
}
|
||||
|
||||
return account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: data.messageId.id))
|
||||
|
||||
return account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: Int32(clamping: data.threadId)))
|
||||
|> mapError { _ -> FetchChannelReplyThreadMessageError in
|
||||
return .generic
|
||||
}
|
||||
|
|
@ -308,9 +312,10 @@ private class ReplyThreadHistoryContextImpl {
|
|||
}
|
||||
|
||||
func applyMaxReadIndex(messageIndex: MessageIndex) {
|
||||
let messageId = self.messageId
|
||||
let peerId = self.peerId
|
||||
let threadId = self.threadId
|
||||
|
||||
if messageIndex.id.namespace != messageId.namespace {
|
||||
if messageIndex.id.namespace != Namespaces.Message.Cloud {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -326,16 +331,16 @@ private class ReplyThreadHistoryContextImpl {
|
|||
let account = self.account
|
||||
|
||||
let _ = (self.account.postbox.transaction { transaction -> (Api.InputPeer?, MessageId?, Int?) in
|
||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id))?.data.get(MessageHistoryThreadData.self) {
|
||||
if var data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||
if messageIndex.id.id >= data.maxIncomingReadId {
|
||||
if let count = transaction.getThreadMessageCount(peerId: messageId.peerId, threadId: Int64(messageId.id), namespace: messageId.namespace, fromIdExclusive: data.maxIncomingReadId, toIndex: messageIndex) {
|
||||
if let count = transaction.getThreadMessageCount(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, fromIdExclusive: data.maxIncomingReadId, toIndex: messageIndex) {
|
||||
data.incomingUnreadCount = max(0, data.incomingUnreadCount - Int32(count))
|
||||
data.maxIncomingReadId = messageIndex.id.id
|
||||
}
|
||||
|
||||
if let topMessageIndex = transaction.getMessageHistoryThreadTopMessage(peerId: messageId.peerId, threadId: Int64(messageId.id), namespaces: Set([Namespaces.Message.Cloud])) {
|
||||
if let topMessageIndex = transaction.getMessageHistoryThreadTopMessage(peerId: peerId, threadId: threadId, namespaces: Set([Namespaces.Message.Cloud])) {
|
||||
if messageIndex.id.id >= topMessageIndex.id.id {
|
||||
let containingHole = transaction.getThreadIndexHole(peerId: messageId.peerId, threadId: Int64(messageId.id), namespace: topMessageIndex.id.namespace, containing: topMessageIndex.id.id)
|
||||
let containingHole = transaction.getThreadIndexHole(peerId: peerId, threadId: threadId, namespace: topMessageIndex.id.namespace, containing: topMessageIndex.id.id)
|
||||
if let _ = containingHole[.everywhere] {
|
||||
} else {
|
||||
data.incomingUnreadCount = 0
|
||||
|
|
@ -346,12 +351,13 @@ private class ReplyThreadHistoryContextImpl {
|
|||
data.maxKnownMessageId = max(data.maxKnownMessageId, messageIndex.id.id)
|
||||
|
||||
if let entry = StoredMessageHistoryThreadInfo(data) {
|
||||
transaction.setMessageHistoryThreadInfo(peerId: messageId.peerId, threadId: Int64(messageId.id), info: entry)
|
||||
transaction.setMessageHistoryThreadInfo(peerId: peerId, threadId: threadId, info: entry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let message = transaction.getMessage(messageId) {
|
||||
let referencedMessageId = MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId))
|
||||
if let message = transaction.getMessage(referencedMessageId) {
|
||||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||
if let sourceMessage = transaction.getMessage(attribute.messageId) {
|
||||
|
|
@ -388,8 +394,8 @@ private class ReplyThreadHistoryContextImpl {
|
|||
}
|
||||
|
||||
let inputPeer = transaction.getPeer(messageIndex.id.peerId).flatMap(apiInputPeer)
|
||||
let readCount = transaction.getThreadMessageCount(peerId: messageId.peerId, threadId: makeMessageThreadId(messageId), namespace: messageId.namespace, fromIdExclusive: fromIdExclusive, toIndex: toIndex)
|
||||
let topMessageId = transaction.getMessagesWithThreadId(peerId: messageId.peerId, namespace: messageId.namespace, threadId: makeMessageThreadId(messageId), from: MessageIndex.upperBound(peerId: messageId.peerId, namespace: messageId.namespace), includeFrom: false, to: MessageIndex.lowerBound(peerId: messageId.peerId, namespace: messageId.namespace), limit: 1).first?.id
|
||||
let readCount = transaction.getThreadMessageCount(peerId: peerId, threadId: threadId, namespace: Namespaces.Message.Cloud, fromIdExclusive: fromIdExclusive, toIndex: toIndex)
|
||||
let topMessageId = transaction.getMessagesWithThreadId(peerId: peerId, namespace: Namespaces.Message.Cloud, threadId: threadId, from: MessageIndex.upperBound(peerId: peerId, namespace: Namespaces.Message.Cloud), includeFrom: false, to: MessageIndex.lowerBound(peerId: peerId, namespace: Namespaces.Message.Cloud), limit: 1).first?.id
|
||||
|
||||
return (inputPeer, topMessageId, readCount)
|
||||
}
|
||||
|
|
@ -434,17 +440,17 @@ private class ReplyThreadHistoryContextImpl {
|
|||
}
|
||||
}
|
||||
|
||||
var signal = strongSelf.account.network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: messageId.id, readMaxId: messageIndex.id.id))
|
||||
var signal = strongSelf.account.network.request(Api.functions.messages.readDiscussion(peer: inputPeer, msgId: Int32(clamping: threadId), readMaxId: messageIndex.id.id))
|
||||
|> `catch` { _ -> Signal<Api.Bool, NoError> in
|
||||
return .single(.boolFalse)
|
||||
}
|
||||
|> ignoreValues
|
||||
if revalidate {
|
||||
let validateSignal = strongSelf.account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: messageId.id))
|
||||
let validateSignal = strongSelf.account.network.request(Api.functions.messages.getDiscussionMessage(peer: inputPeer, msgId: Int32(clamping: threadId)))
|
||||
|> map { result -> (MessageId?, Int) in
|
||||
switch result {
|
||||
case let .discussionMessage(_, _, _, readInboxMaxId, _, unreadCount, _, _):
|
||||
return (readInboxMaxId.flatMap({ MessageId(peerId: messageId.peerId, namespace: messageId.namespace, id: $0) }), Int(unreadCount))
|
||||
return (readInboxMaxId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }), Int(unreadCount))
|
||||
}
|
||||
}
|
||||
|> `catch` { _ -> Signal<(MessageId?, Int)?, NoError> in
|
||||
|
|
@ -494,7 +500,7 @@ public class ReplyThreadHistoryContext {
|
|||
self.impl.with { impl in
|
||||
let stateDisposable = impl.state.get().start(next: { state in
|
||||
subscriber.putNext(MessageHistoryViewExternalInput(
|
||||
content: .thread(peerId: state.messageId.peerId, id: makeMessageThreadId(state.messageId), holes: state.holeIndices),
|
||||
content: .thread(peerId: state.messageId.peerId, id: Int64(state.messageId.id), holes: state.holeIndices),
|
||||
maxReadIncomingMessageId: state.maxReadIncomingMessageId,
|
||||
maxReadOutgoingMessageId: state.maxReadOutgoingMessageId
|
||||
))
|
||||
|
|
@ -554,7 +560,7 @@ public struct ChatReplyThreadMessage: Equatable {
|
|||
case lowerBoundMessage(MessageIndex)
|
||||
}
|
||||
|
||||
public var messageId: MessageId
|
||||
public var peerId: PeerId
|
||||
public var threadId: Int64
|
||||
public var channelMessageId: MessageId?
|
||||
public var isChannelPost: Bool
|
||||
|
|
@ -567,8 +573,16 @@ public struct ChatReplyThreadMessage: Equatable {
|
|||
public var initialAnchor: Anchor
|
||||
public var isNotAvailable: Bool
|
||||
|
||||
public init(messageId: MessageId, threadId: Int64, channelMessageId: MessageId?, isChannelPost: Bool, isForumPost: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, unreadCount: Int, initialFilledHoles: IndexSet, initialAnchor: Anchor, isNotAvailable: Bool) {
|
||||
self.messageId = messageId
|
||||
public var effectiveMessageId: MessageId? {
|
||||
if self.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
return MessageId(peerId: self.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: self.threadId))
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public init(peerId: PeerId, threadId: Int64, channelMessageId: MessageId?, isChannelPost: Bool, isForumPost: Bool, maxMessage: MessageId?, maxReadIncomingMessageId: MessageId?, maxReadOutgoingMessageId: MessageId?, unreadCount: Int, initialFilledHoles: IndexSet, initialAnchor: Anchor, isNotAvailable: Bool) {
|
||||
self.peerId = peerId
|
||||
self.threadId = threadId
|
||||
self.channelMessageId = channelMessageId
|
||||
self.isChannelPost = isChannelPost
|
||||
|
|
@ -584,7 +598,7 @@ public struct ChatReplyThreadMessage: Equatable {
|
|||
|
||||
public var normalized: ChatReplyThreadMessage {
|
||||
if self.isForumPost {
|
||||
return ChatReplyThreadMessage(messageId: self.messageId, threadId: self.threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)
|
||||
return ChatReplyThreadMessage(peerId: self.peerId, threadId: self.threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)
|
||||
} else {
|
||||
return self
|
||||
}
|
||||
|
|
@ -760,32 +774,6 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
|||
|> mapToSignal { threadData -> Signal<(FetchMessageHistoryHoleThreadInput, PeerId, MessageId?, Anchor, MessageId?), FetchChannelReplyThreadMessageError> in
|
||||
if let _ = threadData, !"".isEmpty {
|
||||
return .fail(.generic)
|
||||
/*return account.postbox.transaction { transaction -> (FetchMessageHistoryHoleThreadInput, PeerId, MessageId?, Anchor, MessageId?) in
|
||||
var threadInput: FetchMessageHistoryHoleThreadInput = .threadFromChannel(channelMessageId: messageId)
|
||||
var threadMessageId: MessageId?
|
||||
transaction.scanMessageAttributes(peerId: messageId.peerId, namespace: Namespaces.Message.Cloud, limit: 1000, { id, attributes in
|
||||
for attribute in attributes {
|
||||
if let attribute = attribute as? SourceReferenceMessageAttribute {
|
||||
if attribute.messageId == messageId {
|
||||
threadMessageId = id
|
||||
threadInput = .direct(peerId: id.peerId, threadId: makeMessageThreadId(id))
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
let anchor: Anchor
|
||||
if let atMessageId = atMessageId {
|
||||
anchor = .message(atMessageId)
|
||||
} else if let maxReadIncomingMessageId = replyInfo.maxReadIncomingMessageId {
|
||||
anchor = .message(maxReadIncomingMessageId)
|
||||
} else {
|
||||
anchor = .lowerBound
|
||||
}
|
||||
return (threadInput, replyInfo.commentsPeerId, threadMessageId, anchor, replyInfo.maxMessageId)
|
||||
}
|
||||
|> castError(FetchChannelReplyThreadMessageError.self)*/
|
||||
} else {
|
||||
return discussionMessage.get()
|
||||
|> take(1)
|
||||
|
|
@ -805,7 +793,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
|||
} else {
|
||||
anchor = .lowerBound
|
||||
}
|
||||
return .single((.direct(peerId: commentsPeerId, threadId: makeMessageThreadId(topMessageId)), commentsPeerId, discussionMessage.messageId, anchor, discussionMessage.maxMessage))
|
||||
return .single((.direct(peerId: commentsPeerId, threadId: Int64(topMessageId.id)), commentsPeerId, discussionMessage.messageId, anchor, discussionMessage.maxMessage))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -820,7 +808,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
|||
}
|
||||
return account.postbox.transaction { transaction -> Signal<(FetchMessageHistoryHoleResult?, ChatReplyThreadMessage.Anchor), FetchChannelReplyThreadMessageError> in
|
||||
if let threadMessageId = threadMessageId {
|
||||
var holes = transaction.getThreadIndexHoles(peerId: threadMessageId.peerId, threadId: makeMessageThreadId(threadMessageId), namespace: Namespaces.Message.Cloud)
|
||||
var holes = transaction.getThreadIndexHoles(peerId: threadMessageId.peerId, threadId: Int64(threadMessageId.id), namespace: Namespaces.Message.Cloud)
|
||||
holes.remove(integersIn: Int(maxMessageId.id + 1) ..< Int(Int32.max))
|
||||
|
||||
let isParticipant = transaction.getPeerChatListIndex(commentsPeerId) != nil
|
||||
|
|
@ -843,7 +831,7 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
|||
input: .external(MessageHistoryViewExternalInput(
|
||||
content: .thread(
|
||||
peerId: commentsPeerId,
|
||||
id: makeMessageThreadId(threadMessageId),
|
||||
id: Int64(threadMessageId.id),
|
||||
holes: [
|
||||
Namespaces.Message.Cloud: holes
|
||||
]
|
||||
|
|
@ -932,12 +920,12 @@ func _internal_fetchChannelReplyThreadMessage(account: Account, messageId: Messa
|
|||
return account.postbox.transaction { transaction -> Signal<ChatReplyThreadMessage, FetchChannelReplyThreadMessageError> in
|
||||
if let initialFilledHoles = initialFilledHoles {
|
||||
for range in initialFilledHoles.strictRemovedIndices.rangeView {
|
||||
transaction.removeHole(peerId: discussionMessage.messageId.peerId, threadId: makeMessageThreadId(discussionMessage.messageId), namespace: Namespaces.Message.Cloud, space: .everywhere, range: Int32(range.lowerBound) ... Int32(range.upperBound))
|
||||
transaction.removeHole(peerId: discussionMessage.messageId.peerId, threadId: Int64(discussionMessage.messageId.id), namespace: Namespaces.Message.Cloud, space: .everywhere, range: Int32(range.lowerBound) ... Int32(range.upperBound))
|
||||
}
|
||||
}
|
||||
|
||||
return .single(ChatReplyThreadMessage(
|
||||
messageId: discussionMessage.messageId,
|
||||
peerId: discussionMessage.messageId.peerId,
|
||||
threadId: Int64(discussionMessage.messageId.id),
|
||||
channelMessageId: discussionMessage.channelMessageId,
|
||||
isChannelPost: discussionMessage.isChannelPost,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import MtProtoKit
|
|||
public enum SearchMessagesLocation: Equatable {
|
||||
case general(tags: MessageTags?, minDate: Int32?, maxDate: Int32?)
|
||||
case group(groupId: PeerGroupId, tags: MessageTags?, minDate: Int32?, maxDate: Int32?)
|
||||
case peer(peerId: PeerId, fromId: PeerId?, tags: MessageTags?, topMsgId: MessageId?, minDate: Int32?, maxDate: Int32?)
|
||||
case peer(peerId: PeerId, fromId: PeerId?, tags: MessageTags?, threadId: Int64?, minDate: Int32?, maxDate: Int32?)
|
||||
case sentMedia(tags: MessageTags?)
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ private func mergedState(transaction: Transaction, seedConfiguration: SeedConfig
|
|||
for attribute in renderedMessage.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if let threadMessageId = attribute.threadMessageId {
|
||||
let threadId = makeMessageThreadId(threadMessageId)
|
||||
let threadId = Int64(threadMessageId.id)
|
||||
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||
threadInfo[renderedMessage.id] = data
|
||||
break
|
||||
|
|
@ -224,7 +224,7 @@ private func mergedResult(_ state: SearchMessagesState) -> SearchMessagesResult
|
|||
func _internal_searchMessages(account: Account, location: SearchMessagesLocation, query: String, state: SearchMessagesState?, limit: Int32 = 100) -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> {
|
||||
let remoteSearchResult: Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError>
|
||||
switch location {
|
||||
case let .peer(peerId, fromId, tags, topMsgId, minDate, maxDate):
|
||||
case let .peer(peerId, fromId, tags, threadId, minDate, maxDate):
|
||||
if peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in
|
||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||
|
|
@ -238,7 +238,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if let threadMessageId = attribute.threadMessageId {
|
||||
let threadId = makeMessageThreadId(threadMessageId)
|
||||
let threadId = Int64(threadMessageId.id)
|
||||
if let data = transaction.getMessageHistoryThreadInfo(peerId: peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||
threadInfo[message.id] = data
|
||||
break
|
||||
|
|
@ -253,7 +253,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||
}
|
||||
|
||||
let filter: Api.MessagesFilter = tags.flatMap { messageFilterForTagMask($0) } ?? .inputMessagesFilterEmpty
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> (peer: Peer, additionalPeer: Peer?, from: Peer?)? in
|
||||
remoteSearchResult = account.postbox.transaction { transaction -> (peer: Peer, additionalPeer: Peer?, from: Peer?, subPeer: Peer?)? in
|
||||
guard let peer = transaction.getPeer(peerId) else {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -261,10 +261,12 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||
if let _ = peer as? TelegramChannel, let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference {
|
||||
additionalPeer = transaction.getPeer(migrationReference.maxMessageId.peerId)
|
||||
}
|
||||
if let fromId = fromId {
|
||||
return (peer: peer, additionalPeer: additionalPeer, from: transaction.getPeer(fromId))
|
||||
var subPeer: Peer?
|
||||
if peerId == account.peerId, let threadId = threadId {
|
||||
subPeer = transaction.getPeer(PeerId(threadId))
|
||||
}
|
||||
return (peer: peer, additionalPeer: additionalPeer, from: nil)
|
||||
|
||||
return (peer: peer, additionalPeer: additionalPeer, from: fromId.flatMap(transaction.getPeer), subPeer)
|
||||
}
|
||||
|> mapToSignal { values -> Signal<(Api.messages.Messages?, Api.messages.Messages?), NoError> in
|
||||
guard let values = values else {
|
||||
|
|
@ -282,8 +284,18 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||
flags |= (1 << 0)
|
||||
}
|
||||
}
|
||||
if let _ = topMsgId {
|
||||
var inputSavedPeer: Api.InputPeer? = nil
|
||||
if let subPeer = values.subPeer {
|
||||
if let inputPeer = apiInputPeer(subPeer) {
|
||||
inputSavedPeer = inputPeer
|
||||
flags |= (1 << 2)
|
||||
}
|
||||
}
|
||||
var topMsgId: Int32?
|
||||
if peerId == account.peerId {
|
||||
} else if let threadId = threadId {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
let peerMessages: Signal<Api.messages.Messages?, NoError>
|
||||
if let completed = state?.main.completed, completed {
|
||||
|
|
@ -294,7 +306,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||
if peer.id.namespace == Namespaces.Peer.CloudChannel && query.isEmpty && fromId == nil && tags == nil && minDate == nil && maxDate == nil {
|
||||
signal = account.network.request(Api.functions.messages.getHistory(peer: inputPeer, offsetId: lowerBound?.id.id ?? 0, offsetDate: 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
} else {
|
||||
signal = account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: query, fromId: fromInputPeer, topMsgId: topMsgId?.id, filter: filter, minDate: minDate ?? 0, maxDate: maxDate ?? (Int32.max - 1), offsetId: lowerBound?.id.id ?? 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
signal = account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: query, fromId: fromInputPeer, savedPeerId: inputSavedPeer, topMsgId: topMsgId, filter: filter, minDate: minDate ?? 0, maxDate: maxDate ?? (Int32.max - 1), offsetId: lowerBound?.id.id ?? 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
}
|
||||
peerMessages = signal
|
||||
|> map(Optional.init)
|
||||
|
|
@ -310,7 +322,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||
additionalPeerMessages = .single(nil)
|
||||
} else if mainCompleted || !hasAdditional {
|
||||
let lowerBound = state?.additional?.messages.last.flatMap({ $0.index })
|
||||
additionalPeerMessages = account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: query, fromId: fromInputPeer, topMsgId: topMsgId?.id, filter: filter, minDate: minDate ?? 0, maxDate: maxDate ?? (Int32.max - 1), offsetId: lowerBound?.id.id ?? 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
additionalPeerMessages = account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: query, fromId: fromInputPeer, savedPeerId: inputSavedPeer, topMsgId: topMsgId, filter: filter, minDate: minDate ?? 0, maxDate: maxDate ?? (Int32.max - 1), offsetId: lowerBound?.id.id ?? 0, addOffset: 0, limit: limit, maxId: Int32.max - 1, minId: 0, hash: 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||
return .single(nil)
|
||||
|
|
@ -397,7 +409,7 @@ func _internal_searchMessages(account: Account, location: SearchMessagesLocation
|
|||
for attribute in message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if let threadMessageId = attribute.threadMessageId {
|
||||
let threadId = makeMessageThreadId(threadMessageId)
|
||||
let threadId = Int64(threadMessageId.id)
|
||||
if let data = transaction.getMessageHistoryThreadInfo(peerId: message.id.peerId, threadId: threadId)?.data.get(MessageHistoryThreadData.self) {
|
||||
threadInfo[message.id] = data
|
||||
break
|
||||
|
|
@ -603,10 +615,11 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
|
|||
return .single(transaction.findClosestMessageIdByTimestamp(peerId: peerId, timestamp: timestamp))
|
||||
} else if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) {
|
||||
if let threadId = threadId {
|
||||
let primaryIndex = account.network.request(Api.functions.messages.getReplies(peer: inputPeer, msgId: makeThreadIdMessageId(peerId: peerId, threadId: threadId).id, offsetId: 0, offsetDate: timestamp, addOffset: -1, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
|> map { result -> MessageIndex? in
|
||||
let messages: [Api.Message]
|
||||
switch result {
|
||||
if peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let primaryIndex = account.network.request(Api.functions.messages.getReplies(peer: inputPeer, msgId: Int32(clamping: threadId), offsetId: 0, offsetDate: timestamp, addOffset: -1, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
|> map { result -> MessageIndex? in
|
||||
let messages: [Api.Message]
|
||||
switch result {
|
||||
case let .messages(apiMessages, _, _):
|
||||
messages = apiMessages
|
||||
case let .channelMessages(_, _, _, _, apiMessages, _, _, _):
|
||||
|
|
@ -615,21 +628,55 @@ func _internal_searchMessageIdByTimestamp(account: Account, peerId: PeerId, thre
|
|||
messages = apiMessages
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
}
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: peer.isForum) {
|
||||
return message.index
|
||||
}
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: peer.isForum) {
|
||||
return message.index
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|> `catch` { _ -> Signal<MessageIndex?, NoError> in
|
||||
|> `catch` { _ -> Signal<MessageIndex?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
return primaryIndex
|
||||
|> map { primaryIndex -> MessageId? in
|
||||
return primaryIndex?.id
|
||||
}
|
||||
} else if peerId == account.peerId {
|
||||
guard let subPeer = transaction.getPeer(PeerId(threadId)), let inputSubPeer = apiInputPeer(subPeer) else {
|
||||
return .single(nil)
|
||||
}
|
||||
let primaryIndex = account.network.request(Api.functions.messages.getSavedHistory(peer: inputSubPeer, offsetId: 0, offsetDate: timestamp, addOffset: -1, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
|> map { result -> MessageIndex? in
|
||||
let messages: [Api.Message]
|
||||
switch result {
|
||||
case let .messages(apiMessages, _, _):
|
||||
messages = apiMessages
|
||||
case let .channelMessages(_, _, _, _, apiMessages, _, _, _):
|
||||
messages = apiMessages
|
||||
case let .messagesSlice(_, _, _, _, apiMessages, _, _):
|
||||
messages = apiMessages
|
||||
case .messagesNotModified:
|
||||
messages = []
|
||||
}
|
||||
for message in messages {
|
||||
if let message = StoreMessage(apiMessage: message, accountPeerId: account.peerId, peerIsForum: peer.isForum) {
|
||||
return message.index
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|> `catch` { _ -> Signal<MessageIndex?, NoError> in
|
||||
return .single(nil)
|
||||
}
|
||||
return primaryIndex
|
||||
|> map { primaryIndex -> MessageId? in
|
||||
return primaryIndex?.id
|
||||
}
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
return primaryIndex
|
||||
|> map { primaryIndex -> MessageId? in
|
||||
return primaryIndex?.id
|
||||
}
|
||||
} else {
|
||||
var secondaryIndex: Signal<MessageIndex?, NoError> = .single(nil)
|
||||
if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference, let secondaryPeer = transaction.getPeer(migrationReference.maxMessageId.peerId), let inputSecondaryPeer = apiInputPeer(secondaryPeer) {
|
||||
|
|
|
|||
|
|
@ -105,14 +105,15 @@ public final class SparseMessageList {
|
|||
self.sparseItemsDisposable = (self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<SparseItems, NoError> in
|
||||
|> mapToSignal { inputPeer -> Signal<SparseItems, NoError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .single(SparseItems(items: []))
|
||||
}
|
||||
guard let messageFilter = messageFilterForTagMask(messageTag) else {
|
||||
return .single(SparseItems(items: []))
|
||||
}
|
||||
return account.network.request(Api.functions.messages.getSearchResultsPositions(peer: inputPeer, filter: messageFilter, offsetId: 0, limit: 1000))
|
||||
//TODO:api
|
||||
return account.network.request(Api.functions.messages.getSearchResultsPositions(flags: 0, peer: inputPeer, savedPeerId: nil, filter: messageFilter, offsetId: 0, limit: 1000))
|
||||
|> map { result -> SparseItems in
|
||||
switch result {
|
||||
case let .searchResultsPositions(totalCount, positions):
|
||||
|
|
@ -817,7 +818,8 @@ public final class SparseMessageCalendar {
|
|||
guard let messageFilter = messageFilterForTagMask(messageTag) else {
|
||||
return .single(LoadResult(messagesByDay: [:], nextOffset: nil, minMessageId: nil, minTimestamp: nil))
|
||||
}
|
||||
return self.account.network.request(Api.functions.messages.getSearchResultsCalendar(peer: inputPeer, filter: messageFilter, offsetId: nextRequestOffset, offsetDate: 0))
|
||||
//TODO:api
|
||||
return self.account.network.request(Api.functions.messages.getSearchResultsCalendar(flags: 0, peer: inputPeer, savedPeerId: nil, filter: messageFilter, offsetId: nextRequestOffset, offsetDate: 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.SearchResultsCalendar?, NoError> in
|
||||
return .single(nil)
|
||||
|
|
|
|||
|
|
@ -415,10 +415,16 @@ public extension TelegramEngine {
|
|||
|
||||
public func refreshMessageTagStats(peerId: EnginePeer.Id, threadId: Int64?, tags: [EngineMessage.Tags]) -> Signal<Never, NoError> {
|
||||
let account = self.account
|
||||
return self.account.postbox.transaction { transaction -> Api.InputPeer? in
|
||||
return transaction.getPeer(peerId).flatMap(apiInputPeer)
|
||||
return self.account.postbox.transaction { transaction -> (Api.InputPeer?, Api.InputPeer?) in
|
||||
var inputSavedPeer: Api.InputPeer?
|
||||
if let threadId = threadId {
|
||||
if peerId == account.peerId {
|
||||
inputSavedPeer = transaction.getPeer(PeerId(threadId)).flatMap(apiInputPeer)
|
||||
}
|
||||
}
|
||||
return (transaction.getPeer(peerId).flatMap(apiInputPeer), inputSavedPeer)
|
||||
}
|
||||
|> mapToSignal { inputPeer -> Signal<Never, NoError> in
|
||||
|> mapToSignal { inputPeer, inputSavedPeer -> Signal<Never, NoError> in
|
||||
guard let inputPeer = inputPeer else {
|
||||
return .complete()
|
||||
}
|
||||
|
|
@ -432,11 +438,17 @@ public extension TelegramEngine {
|
|||
var flags: Int32 = 0
|
||||
var topMsgId: Int32?
|
||||
if let threadId = threadId {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
if peerId == account.peerId {
|
||||
if inputSavedPeer != nil {
|
||||
flags |= (1 << 2)
|
||||
}
|
||||
} else {
|
||||
flags |= (1 << 1)
|
||||
topMsgId = Int32(clamping: threadId)
|
||||
}
|
||||
}
|
||||
|
||||
signals.append(self.account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: "", fromId: nil, topMsgId: topMsgId, filter: filter, minDate: 0, maxDate: 0, offsetId: 0, addOffset: 0, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
signals.append(self.account.network.request(Api.functions.messages.search(flags: flags, peer: inputPeer, q: "", fromId: nil, savedPeerId: inputSavedPeer, topMsgId: topMsgId, filter: filter, minDate: 0, maxDate: 0, offsetId: 0, addOffset: 0, limit: 1, maxId: 0, minId: 0, hash: 0))
|
||||
|> map { result -> (count: Int32?, topId: Int32?) in
|
||||
switch result {
|
||||
case let .messagesSlice(_, count, _, _, messages, _, _):
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ func _internal_requestPeerPhotos(accountPeerId: PeerId, postbox: Postbox, networ
|
|||
}
|
||||
}
|
||||
} else if let peer = peer, let inputPeer = apiInputPeer(peer) {
|
||||
return network.request(Api.functions.messages.search(flags: 0, peer: inputPeer, q: "", fromId: nil, topMsgId: nil, filter: .inputMessagesFilterChatPhotos, minDate: 0, maxDate: 0, offsetId: 0, addOffset: 0, limit: 1000, maxId: 0, minId: 0, hash: 0))
|
||||
return network.request(Api.functions.messages.search(flags: 0, peer: inputPeer, q: "", fromId: nil, savedPeerId: nil, topMsgId: nil, filter: .inputMessagesFilterChatPhotos, minDate: 0, maxDate: 0, offsetId: 0, addOffset: 0, limit: 1000, maxId: 0, minId: 0, hash: 0))
|
||||
|> map(Optional.init)
|
||||
|> `catch` { _ -> Signal<Api.messages.Messages?, NoError> in
|
||||
return .single(nil)
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ struct ReplyThreadUserMessage {
|
|||
var isOutgoing: Bool
|
||||
}
|
||||
|
||||
func updateMessageThreadStats(transaction: Transaction, threadMessageId: MessageId, removedCount: Int, addedMessagePeers: [ReplyThreadUserMessage]) {
|
||||
updateMessageThreadStatsInternal(transaction: transaction, threadMessageId: threadMessageId, removedCount: removedCount, addedMessagePeers: addedMessagePeers, allowChannel: false)
|
||||
func updateMessageThreadStats(transaction: Transaction, threadKey: MessageThreadKey, removedCount: Int, addedMessagePeers: [ReplyThreadUserMessage]) {
|
||||
updateMessageThreadStatsInternal(transaction: transaction, threadKey: threadKey, removedCount: removedCount, addedMessagePeers: addedMessagePeers, allowChannel: false)
|
||||
}
|
||||
|
||||
private func updateMessageThreadStatsInternal(transaction: Transaction, threadMessageId: MessageId, removedCount: Int, addedMessagePeers: [ReplyThreadUserMessage], allowChannel: Bool) {
|
||||
guard let channel = transaction.getPeer(threadMessageId.peerId) as? TelegramChannel else {
|
||||
private func updateMessageThreadStatsInternal(transaction: Transaction, threadKey: MessageThreadKey, removedCount: Int, addedMessagePeers: [ReplyThreadUserMessage], allowChannel: Bool) {
|
||||
guard let channel = transaction.getPeer(threadKey.peerId) as? TelegramChannel else {
|
||||
return
|
||||
}
|
||||
var isGroup = true
|
||||
|
|
@ -75,7 +75,7 @@ private func updateMessageThreadStatsInternal(transaction: Transaction, threadMe
|
|||
return current
|
||||
}
|
||||
|
||||
transaction.updateMessage(threadMessageId, update: { currentMessage in
|
||||
transaction.updateMessage(MessageId(peerId: threadKey.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadKey.threadId)), update: { currentMessage in
|
||||
var attributes = currentMessage.attributes
|
||||
loop: for j in 0 ..< attributes.count {
|
||||
if let attribute = attributes[j] as? ReplyThreadMessageAttribute {
|
||||
|
|
@ -117,6 +117,6 @@ private func updateMessageThreadStatsInternal(transaction: Transaction, threadMe
|
|||
})
|
||||
|
||||
if let channelThreadMessageId = channelThreadMessageId {
|
||||
updateMessageThreadStatsInternal(transaction: transaction, threadMessageId: channelThreadMessageId, removedCount: removedCount, addedMessagePeers: addedMessagePeers, allowChannel: true)
|
||||
updateMessageThreadStatsInternal(transaction: transaction, threadKey: MessageThreadKey(peerId: channelThreadMessageId.peerId, threadId: Int64(channelThreadMessageId.id)), removedCount: removedCount, addedMessagePeers: addedMessagePeers, allowChannel: true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ private func titleAndColorForAction(_ action: SubscriberAction, theme: Presentat
|
|||
}
|
||||
|
||||
private func actionForPeer(context: AccountContext, peer: Peer, interfaceState: ChatPresentationInterfaceState, isJoining: Bool, isMuted: Bool) -> SubscriberAction? {
|
||||
if case let .replyThread(message) = interfaceState.chatLocation, message.messageId.peerId == context.account.peerId {
|
||||
if case let .replyThread(message) = interfaceState.chatLocation, message.peerId == context.account.peerId {
|
||||
if let peer = interfaceState.savedMessagesTopicPeer {
|
||||
if case let .channel(channel) = peer {
|
||||
if case .broadcast = channel.info {
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ public final class ChatHistorySearchContainerNode: SearchDisplayControllerConten
|
|||
if let strongSelf = self {
|
||||
let signal: Signal<([ChatHistorySearchEntry], [MessageId: Message])?, NoError>
|
||||
if let query = query, !query.isEmpty {
|
||||
let foundRemoteMessages: Signal<[Message], NoError> = context.engine.messages.searchMessages(location: .peer(peerId: peerId, fromId: nil, tags: tagMask, topMsgId: threadId.flatMap { makeThreadIdMessageId(peerId: peerId, threadId: $0) }, minDate: nil, maxDate: nil), query: query, state: nil)
|
||||
let foundRemoteMessages: Signal<[Message], NoError> = context.engine.messages.searchMessages(location: .peer(peerId: peerId, fromId: nil, tags: tagMask, threadId: threadId, minDate: nil, maxDate: nil), query: query, state: nil)
|
||||
|> map { $0.0.messages }
|
||||
|> delay(0.2, queue: Queue.concurrentDefaultQueue())
|
||||
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||
return false
|
||||
}
|
||||
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.messageId.peerId != item.content.firstMessage.id.peerId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.peerId != item.content.firstMessage.id.peerId {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -826,8 +826,8 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||
hasAvatar = true
|
||||
}
|
||||
case let .replyThread(replyThreadMessage):
|
||||
if replyThreadMessage.messageId.peerId != item.context.account.peerId {
|
||||
if replyThreadMessage.messageId.peerId.isGroupOrChannel && item.message.author != nil {
|
||||
if replyThreadMessage.peerId != item.context.account.peerId {
|
||||
if replyThreadMessage.peerId.isGroupOrChannel && item.message.author != nil {
|
||||
var isBroadcastChannel = false
|
||||
if let peer = item.message.peers[item.message.id.peerId] as? TelegramChannel, case .broadcast = peer.info {
|
||||
isBroadcastChannel = true
|
||||
|
|
@ -1102,7 +1102,7 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||
}
|
||||
|
||||
if let replyAttribute = attribute as? ReplyMessageAttribute {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, Int32(clamping: replyThreadMessage.threadId) == replyAttribute.messageId.id {
|
||||
} else {
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1215,7 +1215,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||
}
|
||||
}
|
||||
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.messageId.peerId != item.content.firstMessage.id.peerId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.peerId != item.content.firstMessage.id.peerId {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -1664,7 +1664,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||
inlineBotNameString = attribute.title
|
||||
}
|
||||
} else if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == attribute.messageId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, Int32(clamping: replyThreadMessage.threadId) == attribute.messageId.id {
|
||||
} else {
|
||||
replyMessage = firstMessage.associatedMessages[attribute.messageId]
|
||||
}
|
||||
|
|
@ -4185,7 +4185,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||
if let item = self.item {
|
||||
for attribute in item.message.attributes {
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if let threadId = item.message.threadId, makeThreadIdMessageId(peerId: item.message.id.peerId, threadId: threadId) == attribute.messageId, let quotedReply = item.message.attributes.first(where: { $0 is QuotedReplyMessageAttribute }) as? QuotedReplyMessageAttribute {
|
||||
if let threadId = item.message.threadId, Int32(clamping: threadId) == attribute.messageId.id, let quotedReply = item.message.attributes.first(where: { $0 is QuotedReplyMessageAttribute }) as? QuotedReplyMessageAttribute {
|
||||
return .action(InternalBubbleTapAction.Action({ [weak self, weak replyInfoNode] in
|
||||
guard let self, let item = self.item, let replyInfoNode else {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco
|
|||
return false
|
||||
}
|
||||
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.messageId.peerId != item.content.firstMessage.id.peerId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.peerId != item.content.firstMessage.id.peerId {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -495,7 +495,7 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco
|
|||
}
|
||||
|
||||
if let replyAttribute = attribute as? ReplyMessageAttribute {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, Int32(clamping: replyThreadMessage.threadId) == replyAttribute.messageId.id {
|
||||
} else {
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -363,7 +363,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
if let replyAttribute = attribute as? ReplyMessageAttribute {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, Int32(clamping: replyThreadMessage.threadId) == replyAttribute.messageId.id {
|
||||
} else {
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
|
|
@ -376,7 +376,7 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||
}
|
||||
|
||||
if replyMessage != nil || replyForward != nil || replyStory != nil {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyMessage?.id {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, Int32(clamping: replyThreadMessage.threadId) == replyMessage?.id.id {
|
||||
} else {
|
||||
replyInfoApply = makeReplyInfoLayout(ChatMessageReplyInfoNode.Arguments(
|
||||
presentationData: item.presentationData,
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ public func isPollEffectivelyClosed(message: Message, poll: TelegramMediaPoll) -
|
|||
|
||||
public extension ChatReplyThreadMessage {
|
||||
var effectiveTopId: MessageId {
|
||||
return self.channelMessageId ?? self.messageId
|
||||
return self.channelMessageId ?? MessageId(peerId: self.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: self.threadId))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||
return false
|
||||
}
|
||||
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.messageId.peerId != item.content.firstMessage.id.peerId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.isChannelPost, replyThreadMessage.peerId != item.content.firstMessage.id.peerId {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -466,8 +466,8 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||
hasAvatar = true
|
||||
}
|
||||
case let .replyThread(replyThreadMessage):
|
||||
if replyThreadMessage.messageId.peerId != item.context.account.peerId {
|
||||
if replyThreadMessage.messageId.peerId.isGroupOrChannel && item.message.author != nil {
|
||||
if replyThreadMessage.peerId != item.context.account.peerId {
|
||||
if replyThreadMessage.peerId.isGroupOrChannel && item.message.author != nil {
|
||||
var isBroadcastChannel = false
|
||||
if let peer = item.message.peers[item.message.id.peerId] as? TelegramChannel, case .broadcast = peer.info {
|
||||
isBroadcastChannel = true
|
||||
|
|
@ -689,7 +689,7 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||
|
||||
|
||||
if let replyAttribute = attribute as? ReplyMessageAttribute {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.messageId == replyAttribute.messageId {
|
||||
if case let .replyThread(replyThreadMessage) = item.chatLocation, Int32(clamping: replyThreadMessage.threadId) == replyAttribute.messageId.id {
|
||||
} else {
|
||||
replyMessage = item.message.associatedMessages[replyAttribute.messageId]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,10 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
|||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
private let chatListNode: ChatListNode
|
||||
|
||||
private var emptyShimmerEffectNode: ChatListShimmerNode?
|
||||
private var shimmerNodeOffset: CGFloat = 0.0
|
||||
private var floatingHeaderOffset: CGFloat?
|
||||
|
||||
public init(context: AccountContext, navigationController: @escaping () -> NavigationController?) {
|
||||
self.context = context
|
||||
|
|
@ -94,10 +98,7 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
|||
navigationController: navigationController,
|
||||
context: self.context,
|
||||
chatLocation: .replyThread(ChatReplyThreadMessage(
|
||||
messageId: makeThreadIdMessageId(
|
||||
peerId: self.context.account.peerId,
|
||||
threadId: peer.id.toInt64()
|
||||
),
|
||||
peerId: self.context.account.peerId,
|
||||
threadId: peer.id.toInt64(),
|
||||
channelMessageId: nil,
|
||||
isChannelPost: false,
|
||||
|
|
@ -115,6 +116,53 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
|||
))
|
||||
self.chatListNode.clearHighlightAnimated(true)
|
||||
}
|
||||
|
||||
self.chatListNode.isEmptyUpdated = { [weak self] isEmptyState, _, transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
var needsShimmerNode = false
|
||||
let shimmerNodeOffset: CGFloat = 0.0
|
||||
|
||||
switch isEmptyState {
|
||||
case let .empty(isLoadingValue, _):
|
||||
if isLoadingValue {
|
||||
needsShimmerNode = true
|
||||
}
|
||||
case .notEmpty:
|
||||
break
|
||||
}
|
||||
|
||||
if needsShimmerNode {
|
||||
self.shimmerNodeOffset = shimmerNodeOffset
|
||||
if self.emptyShimmerEffectNode == nil {
|
||||
let emptyShimmerEffectNode = ChatListShimmerNode()
|
||||
self.emptyShimmerEffectNode = emptyShimmerEffectNode
|
||||
self.insertSubnode(emptyShimmerEffectNode, belowSubnode: self.chatListNode)
|
||||
if let currentParams = self.currentParams, let offset = self.floatingHeaderOffset {
|
||||
self.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: currentParams.size, insets: UIEdgeInsets(top: currentParams.topInset, left: currentParams.sideInset, bottom: currentParams.bottomInset, right: currentParams.sideInset), verticalOffset: offset + self.shimmerNodeOffset, transition: .immediate)
|
||||
}
|
||||
}
|
||||
} else if let emptyShimmerEffectNode = self.emptyShimmerEffectNode {
|
||||
self.emptyShimmerEffectNode = nil
|
||||
let emptyNodeTransition = transition.isAnimated ? transition : .animated(duration: 0.3, curve: .easeInOut)
|
||||
emptyNodeTransition.updateAlpha(node: emptyShimmerEffectNode, alpha: 0.0, completion: { [weak emptyShimmerEffectNode] _ in
|
||||
emptyShimmerEffectNode?.removeFromSupernode()
|
||||
})
|
||||
self.chatListNode.alpha = 0.0
|
||||
emptyNodeTransition.updateAlpha(node: self.chatListNode, alpha: 1.0)
|
||||
}
|
||||
}
|
||||
|
||||
self.chatListNode.updateFloatingHeaderOffset = { [weak self] offset, transition in
|
||||
guard let self else {
|
||||
return
|
||||
}
|
||||
self.floatingHeaderOffset = offset
|
||||
if let currentParams = self.currentParams, let emptyShimmerEffectNode = self.emptyShimmerEffectNode {
|
||||
self.layoutEmptyShimmerEffectNode(node: emptyShimmerEffectNode, size: currentParams.size, insets: UIEdgeInsets(top: currentParams.topInset, left: currentParams.sideInset, bottom: currentParams.bottomInset, right: currentParams.sideInset), verticalOffset: offset + self.shimmerNodeOffset, transition: transition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
@ -164,6 +212,11 @@ public final class PeerInfoChatListPaneNode: ASDisplayNode, PeerInfoPaneNode, UI
|
|||
return true
|
||||
}
|
||||
|
||||
private func layoutEmptyShimmerEffectNode(node: ChatListShimmerNode, size: CGSize, insets: UIEdgeInsets, verticalOffset: CGFloat, transition: ContainedViewLayoutTransition) {
|
||||
node.update(context: self.context, animationCache: self.context.animationCache, animationRenderer: self.context.animationRenderer, size: size, isInlineMode: false, presentationData: self.presentationData, transition: .immediate)
|
||||
transition.updateFrameAdditive(node: node, frame: CGRect(origin: CGPoint(x: 0.0, y: verticalOffset), size: size))
|
||||
}
|
||||
|
||||
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
|
||||
if gestureRecognizer.state != .failed, let otherGestureRecognizer = otherGestureRecognizer as? UIPanGestureRecognizer {
|
||||
let _ = otherGestureRecognizer
|
||||
|
|
|
|||
|
|
@ -830,9 +830,9 @@ func peerInfoScreenData(context: AccountContext, peerId: PeerId, strings: Presen
|
|||
}
|
||||
}
|
||||
|
||||
/*if peerId == context.account.peerId, case .peer = chatLocation {
|
||||
if peerId == context.account.peerId, case .peer = chatLocation {
|
||||
availablePanes?.insert(.savedMessagesChats, at: 0)
|
||||
}*/
|
||||
}
|
||||
} else {
|
||||
availablePanes = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
private var currentPanelStatusData: PeerInfoStatusData?
|
||||
func update(width: CGFloat, containerHeight: CGFloat, containerInset: CGFloat, statusBarHeight: CGFloat, navigationHeight: CGFloat, isModalOverlay: Bool, isMediaOnly: Bool, contentOffset: CGFloat, paneContainerY: CGFloat, presentationData: PresentationData, peer: Peer?, cachedData: CachedPeerData?, threadData: MessageHistoryThreadData?, peerNotificationSettings: TelegramPeerNotificationSettings?, threadNotificationSettings: TelegramPeerNotificationSettings?, globalNotificationSettings: EngineGlobalNotificationSettings?, statusData: PeerInfoStatusData?, panelStatusData: (PeerInfoStatusData?, PeerInfoStatusData?, CGFloat?), isSecretChat: Bool, isContact: Bool, isSettings: Bool, state: PeerInfoState, metrics: LayoutMetrics, deviceMetrics: DeviceMetrics, transition: ContainedViewLayoutTransition, additive: Bool, animateHeader: Bool) -> CGFloat {
|
||||
var threadData = threadData
|
||||
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.messageId.peerId == self.context.account.peerId {
|
||||
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId {
|
||||
threadData = nil
|
||||
}
|
||||
|
||||
|
|
@ -1606,7 +1606,7 @@ final class PeerInfoHeaderNode: ASDisplayNode {
|
|||
if self.isSettings {
|
||||
expandablePart += 20.0
|
||||
} else {
|
||||
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.messageId.peerId == self.context.account.peerId {
|
||||
if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId {
|
||||
expandablePart = 0.0
|
||||
} else if peer?.id == self.context.account.peerId {
|
||||
expandablePart = 0.0
|
||||
|
|
|
|||
|
|
@ -6009,7 +6009,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||
private func openChatWithMessageSearch() {
|
||||
if let navigationController = (self.controller?.navigationController as? NavigationController) {
|
||||
if case let .replyThread(currentMessage) = self.chatLocation, let current = navigationController.viewControllers.first(where: { controller in
|
||||
if let controller = controller as? ChatController, case let .replyThread(message) = controller.chatLocation, message.messageId == currentMessage.messageId {
|
||||
if let controller = controller as? ChatController, case let .replyThread(message) = controller.chatLocation, message.peerId == currentMessage.peerId, message.threadId == currentMessage.threadId {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
@ -10922,7 +10922,7 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen, KeyShortc
|
|||
let navigateChatLocation: NavigateToChatControllerParams.Location
|
||||
if let threadId = item.threadId {
|
||||
navigateChatLocation = .replyThread(ChatReplyThreadMessage(
|
||||
messageId: MessageId(peerId: item.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: item.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
))
|
||||
} else {
|
||||
navigateChatLocation = .peer(itemPeer)
|
||||
|
|
|
|||
|
|
@ -2563,7 +2563,7 @@ final class StorageUsageScreenComponent: Component {
|
|||
|
||||
var chatLocation: NavigateToChatControllerParams.Location = .peer(peer)
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum), let threadId = message.threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
}
|
||||
|
||||
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
|
|
@ -2666,7 +2666,7 @@ final class StorageUsageScreenComponent: Component {
|
|||
|
||||
var chatLocation: NavigateToChatControllerParams.Location = .peer(peer)
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum), let threadId = message.threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
}
|
||||
|
||||
component.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(
|
||||
|
|
|
|||
|
|
@ -477,11 +477,11 @@ public final class AccountContextImpl: AccountContext {
|
|||
case let .peer(peerId):
|
||||
return .peer(peerId: peerId, threadId: nil)
|
||||
case let .replyThread(data):
|
||||
if data.isForumPost {
|
||||
return .peer(peerId: data.messageId.peerId, threadId: Int64(data.messageId.id))
|
||||
if data.isForumPost || data.peerId.namespace != Namespaces.Peer.CloudChannel {
|
||||
return .peer(peerId: data.peerId, threadId: data.threadId)
|
||||
} else {
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
return .thread(peerId: data.messageId.peerId, threadId: makeMessageThreadId(data.messageId), data: context.state)
|
||||
return .thread(peerId: data.peerId, threadId: data.threadId, data: context.state)
|
||||
}
|
||||
case .feed:
|
||||
preconditionFailure()
|
||||
|
|
@ -494,7 +494,7 @@ public final class AccountContextImpl: AccountContext {
|
|||
return .single(nil)
|
||||
case let .replyThread(data):
|
||||
if data.isForumPost, let peerId = location.peerId {
|
||||
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.messageId.peerId, threadId: Int64(data.messageId.id))
|
||||
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.peerId, threadId: data.threadId)
|
||||
return self.account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> MessageId? in
|
||||
if let threadInfo = views.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.data.get(MessageHistoryThreadData.self) {
|
||||
|
|
@ -503,9 +503,11 @@ public final class AccountContextImpl: AccountContext {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if data.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
return context.maxReadOutgoingMessageId
|
||||
} else {
|
||||
return .single(nil)
|
||||
}
|
||||
case .feed:
|
||||
return .single(nil)
|
||||
|
|
@ -530,7 +532,7 @@ public final class AccountContextImpl: AccountContext {
|
|||
}
|
||||
case let .replyThread(data):
|
||||
if data.isForumPost {
|
||||
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.messageId.peerId, threadId: Int64(data.messageId.id))
|
||||
let viewKey: PostboxViewKey = .messageHistoryThreadInfo(peerId: data.peerId, threadId: data.threadId)
|
||||
return self.account.postbox.combinedView(keys: [viewKey])
|
||||
|> map { views -> Int in
|
||||
if let threadInfo = views.views[viewKey] as? MessageHistoryThreadInfoView, let data = threadInfo.info?.data.get(MessageHistoryThreadData.self) {
|
||||
|
|
@ -539,6 +541,8 @@ public final class AccountContextImpl: AccountContext {
|
|||
return 0
|
||||
}
|
||||
}
|
||||
} else if data.peerId.namespace != Namespaces.Peer.CloudChannel {
|
||||
return .single(0)
|
||||
} else {
|
||||
let context = chatLocationContext(holder: contextHolder, account: self.account, data: data)
|
||||
return context.unreadCount
|
||||
|
|
@ -722,7 +726,7 @@ private final class ChatLocationReplyContextHolderImpl: ChatLocationContextHolde
|
|||
let context: ReplyThreadHistoryContext
|
||||
|
||||
init(account: Account, data: ChatReplyThreadMessage) {
|
||||
self.context = ReplyThreadHistoryContext(account: account, peerId: data.messageId.peerId, data: data)
|
||||
self.context = ReplyThreadHistoryContext(account: account, peerId: data.peerId, data: data)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ final class AuthorizedApplicationContext {
|
|||
let chatLocation: NavigateToChatControllerParams.Location
|
||||
if let _ = threadData, let threadId = firstMessage.threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(
|
||||
messageId: MessageId(peerId: firstMessage.id.peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: firstMessage.id.peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
).normalized)
|
||||
} else {
|
||||
guard let peer = firstMessage.peers[firstMessage.id.peerId] else {
|
||||
|
|
@ -905,7 +905,7 @@ final class AuthorizedApplicationContext {
|
|||
let chatLocation: NavigateToChatControllerParams.Location
|
||||
if let threadId = threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(
|
||||
messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
peerId: peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false
|
||||
))
|
||||
} else {
|
||||
chatLocation = .peer(peer)
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ extension ChatControllerImpl {
|
|||
params: NavigateToMessageParams
|
||||
) {
|
||||
var id = id
|
||||
if case let .replyThread(message) = self.chatLocation {
|
||||
if case let .replyThread(message) = self.chatLocation, let effectiveMessageId = message.effectiveMessageId {
|
||||
if let channelMessageId = message.channelMessageId, id == channelMessageId {
|
||||
id = message.messageId
|
||||
id = effectiveMessageId
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ extension ChatControllerImpl {
|
|||
|
||||
let navigateToLocation: NavigateToChatControllerParams.Location
|
||||
if let message = messages.first, let threadId = message.threadId, let channel = message.peers[message.id.peerId] as? TelegramChannel, channel.flags.contains(.isForum) {
|
||||
navigateToLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
navigateToLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
} else {
|
||||
navigateToLocation = .peer(peer)
|
||||
}
|
||||
|
|
@ -148,7 +148,7 @@ extension ChatControllerImpl {
|
|||
if let navigationController = self.effectiveNavigationController {
|
||||
var chatLocation: NavigateToChatControllerParams.Location = .peer(peer)
|
||||
if case let .channel(channel) = peer, channel.flags.contains(.isForum), let message = message, let threadId = message.threadId {
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
chatLocation = .replyThread(ChatReplyThreadMessage(peerId: peer.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
}
|
||||
|
||||
var quote: ChatControllerSubject.MessageHighlight.Quote?
|
||||
|
|
@ -221,7 +221,7 @@ extension ChatControllerImpl {
|
|||
let searchLocation: ChatHistoryInitialSearchLocation
|
||||
switch messageLocation {
|
||||
case let .id(id, _):
|
||||
if case let .replyThread(message) = self.chatLocation, id == message.messageId {
|
||||
if case let .replyThread(message) = self.chatLocation, id == message.effectiveMessageId {
|
||||
searchLocation = .index(.absoluteLowerBound())
|
||||
} else {
|
||||
searchLocation = .id(id)
|
||||
|
|
|
|||
|
|
@ -608,13 +608,17 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
locationBroadcastPanelSource = .none
|
||||
groupCallPanelSource = .none
|
||||
let promise = Promise<Message?>()
|
||||
promise.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: replyThreadMessage.messageId))
|
||||
|> map { message -> Message? in
|
||||
guard let message = message else {
|
||||
return nil
|
||||
}
|
||||
return message._asMessage()
|
||||
})
|
||||
if let effectiveMessageId = replyThreadMessage.effectiveMessageId {
|
||||
promise.set(context.engine.data.subscribe(TelegramEngine.EngineData.Item.Messages.Message(id: effectiveMessageId))
|
||||
|> map { message -> Message? in
|
||||
guard let message = message else {
|
||||
return nil
|
||||
}
|
||||
return message._asMessage()
|
||||
})
|
||||
} else {
|
||||
promise.set(.single(nil))
|
||||
}
|
||||
self.chatLocationInfoData = .replyThread(promise)
|
||||
case .feed:
|
||||
locationBroadcastPanelSource = .none
|
||||
|
|
@ -1038,11 +1042,6 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
|
||||
let openChatLocation = strongSelf.chatLocation
|
||||
/*if case let .replyThread(replyThreadMessage) = openChatLocation {
|
||||
if message.threadId != makeMessageThreadId(replyThreadMessage.messageId) {
|
||||
openChatLocation = .peer(id: message.id.peerId)
|
||||
}
|
||||
}*/
|
||||
|
||||
return context.sharedContext.openChatMessage(OpenChatMessageParams(context: context, updatedPresentationData: strongSelf.updatedPresentationData, chatLocation: openChatLocation, chatLocationContextHolder: strongSelf.chatLocationContextHolder, message: message, standalone: false, reverseMessageGalleryOrder: false, mode: mode, navigationController: strongSelf.effectiveNavigationController, dismissInput: {
|
||||
self?.chatDisplayNode.dismissInput()
|
||||
|
|
@ -2804,12 +2803,12 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
|
||||
if isCopyLink, let channel = channel as? TelegramChannel {
|
||||
var threadMessageId: MessageId?
|
||||
var threadId: Int64?
|
||||
|
||||
if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation {
|
||||
threadMessageId = replyThreadMessage.messageId
|
||||
threadId = replyThreadMessage.threadId
|
||||
}
|
||||
let _ = (context.engine.messages.exportMessageLink(peerId: messageId.peerId, messageId: messageId, isThread: threadMessageId != nil)
|
||||
let _ = (context.engine.messages.exportMessageLink(peerId: messageId.peerId, messageId: messageId, isThread: threadId != nil)
|
||||
|> map { result -> String? in
|
||||
return result
|
||||
}
|
||||
|
|
@ -2995,7 +2994,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
}
|
||||
if let strongSelf = self {
|
||||
if case let .replyThread(replyThreadMessage) = strongSelf.chatLocation, replyThreadMessage.messageId == message.id {
|
||||
if case let .replyThread(replyThreadMessage) = strongSelf.chatLocation, replyThreadMessage.effectiveMessageId == message.id {
|
||||
return .none
|
||||
}
|
||||
if case .peer = strongSelf.chatLocation, let channel = strongSelf.presentationInterfaceState.renderedPeer?.peer as? TelegramChannel, channel.flags.contains(.isForum) {
|
||||
|
|
@ -3027,7 +3026,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
strongSelf.navigateToMessage(from: nil, to: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT()))), scrollPosition: .bottom(0.0), rememberInStack: false, animated: true, completion: nil)
|
||||
}
|
||||
case let .replyThread(replyThreadMessage):
|
||||
let peerId = replyThreadMessage.messageId.peerId
|
||||
let peerId = replyThreadMessage.peerId
|
||||
strongSelf.navigateToMessage(from: nil, to: .index(MessageIndex(id: MessageId(peerId: peerId, namespace: 0, id: 0), timestamp: timestamp - Int32(NSTimeZone.local.secondsFromGMT()))), scrollPosition: .bottom(0.0), rememberInStack: false, forceInCurrentChat: true, animated: true, completion: nil)
|
||||
case .feed:
|
||||
break
|
||||
|
|
@ -5705,7 +5704,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
case .peer:
|
||||
replyThreadType = .replies
|
||||
case let .replyThread(replyThreadMessage):
|
||||
if replyThreadMessage.messageId.peerId == context.account.peerId {
|
||||
if replyThreadMessage.peerId == context.account.peerId {
|
||||
replyThreadId = replyThreadMessage.threadId
|
||||
replyThreadType = .replies
|
||||
} else {
|
||||
|
|
@ -5751,8 +5750,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
|
||||
let savedMessagesPeerId: PeerId?
|
||||
if case let .replyThread(replyThreadMessage) = chatLocation, replyThreadMessage.messageId.peerId == context.account.peerId {
|
||||
savedMessagesPeerId = PeerId(makeMessageThreadId(replyThreadMessage.messageId))
|
||||
if case let .replyThread(replyThreadMessage) = chatLocation, replyThreadMessage.peerId == context.account.peerId {
|
||||
savedMessagesPeerId = PeerId(replyThreadMessage.threadId)
|
||||
} else {
|
||||
savedMessagesPeerId = nil
|
||||
}
|
||||
|
|
@ -6302,7 +6301,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
case let .peer(peerId):
|
||||
activitySpace = PeerActivitySpace(peerId: peerId, category: .global)
|
||||
case let .replyThread(replyThreadMessage):
|
||||
activitySpace = PeerActivitySpace(peerId: replyThreadMessage.messageId.peerId, category: .thread(makeMessageThreadId(replyThreadMessage.messageId)))
|
||||
activitySpace = PeerActivitySpace(peerId: replyThreadMessage.peerId, category: .thread(replyThreadMessage.threadId))
|
||||
case .feed:
|
||||
activitySpace = nil
|
||||
}
|
||||
|
|
@ -6868,7 +6867,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
|
||||
let chatLocation: ChatLocation
|
||||
if let threadId {
|
||||
chatLocation = .replyThread(message: ChatReplyThreadMessage(messageId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
chatLocation = .replyThread(message: ChatReplyThreadMessage(peerId: peerId, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false))
|
||||
} else {
|
||||
chatLocation = .peer(id: peerId)
|
||||
}
|
||||
|
|
@ -7176,7 +7175,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
var closeOnEmpty = false
|
||||
if case .pinnedMessages = self.presentationInterfaceState.subject {
|
||||
closeOnEmpty = true
|
||||
} else if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.messageId.peerId == self.context.account.peerId {
|
||||
} else if case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId {
|
||||
closeOnEmpty = true
|
||||
}
|
||||
|
||||
|
|
@ -10999,7 +10998,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
case let .peer(peerId):
|
||||
activitySpace = PeerActivitySpace(peerId: peerId, category: .global)
|
||||
case let .replyThread(replyThreadMessage):
|
||||
activitySpace = PeerActivitySpace(peerId: replyThreadMessage.messageId.peerId, category: .thread(makeMessageThreadId(replyThreadMessage.messageId)))
|
||||
activitySpace = PeerActivitySpace(peerId: replyThreadMessage.peerId, category: .thread(replyThreadMessage.threadId))
|
||||
case .feed:
|
||||
activitySpace = nil
|
||||
}
|
||||
|
|
@ -11315,7 +11314,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
|
||||
if case let .replyThread(message) = self.chatLocation, message.isForumPost {
|
||||
if self.keepMessageCountersSyncrhonizedDisposable == nil {
|
||||
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: message.messageId.peerId, threadId: Int64(message.messageId.id)).startStrict()
|
||||
self.keepMessageCountersSyncrhonizedDisposable = self.context.engine.messages.keepMessageCountersSyncrhonized(peerId: message.peerId, threadId: message.threadId).startStrict()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -11851,8 +11850,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
case let .peer(peerIdValue):
|
||||
peerId = peerIdValue
|
||||
case let .replyThread(replyThreadMessage):
|
||||
peerId = replyThreadMessage.messageId.peerId
|
||||
threadId = makeMessageThreadId(replyThreadMessage.messageId)
|
||||
peerId = replyThreadMessage.peerId
|
||||
threadId = replyThreadMessage.threadId
|
||||
case .feed:
|
||||
return
|
||||
}
|
||||
|
|
@ -12392,7 +12391,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
}))
|
||||
case .replyThread:
|
||||
if let peer = self.presentationInterfaceState.renderedPeer?.peer, case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.messageId.peerId == self.context.account.peerId {
|
||||
if let peer = self.presentationInterfaceState.renderedPeer?.peer, case let .replyThread(replyThreadMessage) = self.chatLocation, replyThreadMessage.peerId == self.context.account.peerId {
|
||||
if let infoController = self.context.sharedContext.makePeerInfoController(context: self.context, updatedPresentationData: self.updatedPresentationData, peer: peer, mode: .forumTopic(thread: replyThreadMessage), avatarInitiallyExpanded: false, fromChat: true, requestsContext: nil) {
|
||||
self.effectiveNavigationController?.pushViewController(infoController)
|
||||
}
|
||||
|
|
@ -14948,7 +14947,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
case .peer:
|
||||
break
|
||||
case let .replyThread(replyThreadMessage):
|
||||
defaultReplyMessageSubject = EngineMessageReplySubject(messageId: replyThreadMessage.messageId, quote: nil)
|
||||
if let effectiveMessageId = replyThreadMessage.effectiveMessageId {
|
||||
defaultReplyMessageSubject = EngineMessageReplySubject(messageId: effectiveMessageId, quote: nil)
|
||||
}
|
||||
case .feed:
|
||||
break
|
||||
}
|
||||
|
|
@ -15651,22 +15652,22 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
}
|
||||
return nil
|
||||
}
|
||||
var searchTopMsgId: MessageId?
|
||||
var threadId: Int64?
|
||||
switch self.chatLocation {
|
||||
case .peer:
|
||||
break
|
||||
case let .replyThread(replyThreadMessage):
|
||||
searchTopMsgId = replyThreadMessage.messageId
|
||||
threadId = replyThreadMessage.threadId
|
||||
case .feed:
|
||||
break
|
||||
}
|
||||
switch search.domain {
|
||||
case .everything:
|
||||
derivedSearchState = ChatSearchState(query: search.query, location: .peer(peerId: peerId, fromId: nil, tags: nil, topMsgId: searchTopMsgId, minDate: nil, maxDate: nil), loadMoreState: loadMoreStateFromResultsState(search.resultsState))
|
||||
derivedSearchState = ChatSearchState(query: search.query, location: .peer(peerId: peerId, fromId: nil, tags: nil, threadId: threadId, minDate: nil, maxDate: nil), loadMoreState: loadMoreStateFromResultsState(search.resultsState))
|
||||
case .members:
|
||||
derivedSearchState = nil
|
||||
case let .member(peer):
|
||||
derivedSearchState = ChatSearchState(query: search.query, location: .peer(peerId: peerId, fromId: peer.id, tags: nil, topMsgId: searchTopMsgId, minDate: nil, maxDate: nil), loadMoreState: loadMoreStateFromResultsState(search.resultsState))
|
||||
derivedSearchState = ChatSearchState(query: search.query, location: .peer(peerId: peerId, fromId: peer.id, tags: nil, threadId: threadId, minDate: nil, maxDate: nil), loadMoreState: loadMoreStateFromResultsState(search.resultsState))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -15972,8 +15973,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
peerId = peerIdValue
|
||||
threadId = nil
|
||||
case let .replyThread(replyThreadMessage):
|
||||
peerId = replyThreadMessage.messageId.peerId
|
||||
threadId = makeMessageThreadId(replyThreadMessage.messageId)
|
||||
peerId = replyThreadMessage.peerId
|
||||
threadId = replyThreadMessage.threadId
|
||||
case .feed:
|
||||
return
|
||||
}
|
||||
|
|
@ -16009,8 +16010,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||
peerId = peerIdValue
|
||||
threadId = nil
|
||||
case let .replyThread(replyThreadMessage):
|
||||
peerId = replyThreadMessage.messageId.peerId
|
||||
threadId = makeMessageThreadId(replyThreadMessage.messageId)
|
||||
peerId = replyThreadMessage.peerId
|
||||
threadId = replyThreadMessage.threadId
|
||||
case .feed:
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ private func extractAssociatedData(
|
|||
}
|
||||
}
|
||||
} else if case let .replyThread(message) = chatLocation, message.isForumPost {
|
||||
automaticDownloadPeerId = message.messageId.peerId
|
||||
automaticDownloadPeerId = message.peerId
|
||||
}
|
||||
|
||||
return ChatMessageItemAssociatedData(automaticDownloadPeerType: automaticMediaDownloadPeerType, automaticDownloadPeerId: automaticDownloadPeerId, automaticDownloadNetworkType: automaticDownloadNetworkType, isRecentActions: false, subject: subject, contactsPeerIds: contactsPeerIds, channelDiscussionGroup: channelDiscussionGroup, animatedEmojiStickers: animatedEmojiStickers, additionalAnimatedEmojiStickers: additionalAnimatedEmojiStickers, currentlyPlayingMessageId: currentlyPlayingMessageId, isCopyProtectionEnabled: isCopyProtectionEnabled, availableReactions: availableReactions, defaultReaction: defaultReaction, isPremium: isPremium, accountPeer: accountPeer, alwaysDisplayTranscribeButton: alwaysDisplayTranscribeButton, topicAuthorId: topicAuthorId, hasBots: hasBots, translateToLanguage: translateToLanguage, maxReadStoryId: maxReadStoryId, recommendedChannels: recommendedChannels, audioTranscriptionTrial: audioTranscriptionTrial, chatThemes: chatThemes)
|
||||
|
|
@ -1145,11 +1145,11 @@ public final class ChatHistoryListNodeImpl: ListView, ChatHistoryNode, ChatHisto
|
|||
additionalData.append(.totalUnreadState)
|
||||
}
|
||||
if case let .replyThread(replyThreadMessage) = self.chatLocation {
|
||||
additionalData.append(.cachedPeerData(replyThreadMessage.messageId.peerId))
|
||||
additionalData.append(.peerNotificationSettings(replyThreadMessage.messageId.peerId))
|
||||
if replyThreadMessage.messageId.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
additionalData.append(.cacheEntry(cachedChannelAdminRanksEntryId(peerId: replyThreadMessage.messageId.peerId)))
|
||||
additionalData.append(.peer(replyThreadMessage.messageId.peerId))
|
||||
additionalData.append(.cachedPeerData(replyThreadMessage.peerId))
|
||||
additionalData.append(.peerNotificationSettings(replyThreadMessage.peerId))
|
||||
if replyThreadMessage.peerId.namespace == Namespaces.Peer.CloudChannel {
|
||||
additionalData.append(.cacheEntry(cachedChannelAdminRanksEntryId(peerId: replyThreadMessage.peerId)))
|
||||
additionalData.append(.peer(replyThreadMessage.peerId))
|
||||
}
|
||||
|
||||
additionalData.append(.message(replyThreadMessage.effectiveTopId))
|
||||
|
|
|
|||
|
|
@ -718,7 +718,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||
|
||||
let readCounters: Signal<Bool, NoError>
|
||||
if case let .replyThread(threadMessage) = chatPresentationInterfaceState.chatLocation, threadMessage.isForumPost {
|
||||
readCounters = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.ThreadData(id: threadMessage.messageId.peerId, threadId: Int64(threadMessage.messageId.id)))
|
||||
readCounters = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.ThreadData(id: threadMessage.peerId, threadId: threadMessage.threadId))
|
||||
|> map { threadData -> Bool in
|
||||
guard let threadData else {
|
||||
return false
|
||||
|
|
@ -1248,7 +1248,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||
} else {
|
||||
for attribute in messages[0].attributes {
|
||||
if let attribute = attribute as? ReplyThreadMessageAttribute, attribute.count > 0 {
|
||||
threadId = makeMessageThreadId(messages[0].id)
|
||||
threadId = Int64(messages[0].id.id)
|
||||
threadMessageCount = Int(attribute.count)
|
||||
}
|
||||
}
|
||||
|
|
@ -1256,7 +1256,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||
} else {
|
||||
for attribute in messages[0].attributes {
|
||||
if let attribute = attribute as? ReplyThreadMessageAttribute, attribute.count > 0 {
|
||||
threadId = makeMessageThreadId(messages[0].id)
|
||||
threadId = Int64(messages[0].id.id)
|
||||
threadMessageCount = Int(attribute.count)
|
||||
}
|
||||
}
|
||||
|
|
@ -1404,7 +1404,7 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||
}, action: { _, f in
|
||||
var threadMessageId: MessageId?
|
||||
if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation {
|
||||
threadMessageId = replyThreadMessage.messageId
|
||||
threadMessageId = replyThreadMessage.effectiveMessageId
|
||||
}
|
||||
let _ = (context.engine.messages.exportMessageLink(peerId: message.id.peerId, messageId: message.id, isThread: threadMessageId != nil)
|
||||
|> map { result -> String? in
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
|||
}
|
||||
}
|
||||
|
||||
if case let .replyThread(message) = chatPresentationInterfaceState.chatLocation, message.messageId.peerId == context.account.peerId {
|
||||
if case let .replyThread(message) = chatPresentationInterfaceState.chatLocation, message.peerId == context.account.peerId {
|
||||
if let currentPanel = (currentPanel as? ChatChannelSubscriberInputPanelNode) ?? (currentSecondaryPanel as? ChatChannelSubscriberInputPanelNode) {
|
||||
return (currentPanel, nil)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func rightNavigationButtonForChatInterfaceState(context: AccountContext, present
|
|||
}
|
||||
}
|
||||
|
||||
if case let .replyThread(message) = presentationInterfaceState.chatLocation, message.messageId.peerId == context.account.peerId {
|
||||
if case let .replyThread(message) = presentationInterfaceState.chatLocation, message.peerId == context.account.peerId {
|
||||
return chatInfoNavigationButton
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam
|
|||
return true
|
||||
}
|
||||
case let .replyThread(replyThreadMessage):
|
||||
if message.id.peerId == replyThreadMessage.messageId.peerId {
|
||||
if message.id.peerId == replyThreadMessage.peerId {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,10 +206,10 @@ func openResolvedUrlImpl(
|
|||
case let .channelMessage(peer, messageId, timecode):
|
||||
openPeer(EnginePeer(peer), .chat(textInputState: nil, subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: timecode), peekData: nil))
|
||||
case let .replyThreadMessage(replyThreadMessage, messageId):
|
||||
if let navigationController = navigationController {
|
||||
if let navigationController = navigationController, let effectiveMessageId = replyThreadMessage.effectiveMessageId {
|
||||
let _ = ChatControllerImpl.openMessageReplies(context: context, navigationController: navigationController, present: { c, a in
|
||||
present(c, a)
|
||||
}, messageId: replyThreadMessage.messageId, isChannelPost: replyThreadMessage.isChannelPost, atMessage: messageId, displayModalProgress: true).startStandalone()
|
||||
}, messageId: effectiveMessageId, isChannelPost: replyThreadMessage.isChannelPost, atMessage: messageId, displayModalProgress: true).startStandalone()
|
||||
}
|
||||
case let .replyThread(messageId):
|
||||
if let navigationController = navigationController {
|
||||
|
|
|
|||
|
|
@ -72,10 +72,10 @@ func handleTextLinkActionImpl(context: AccountContext, peerId: EnginePeer.Id?, n
|
|||
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(EnginePeer(peer)), subject: .message(id: .id(messageId), highlight: ChatControllerSubject.MessageHighlight(quote: nil), timecode: timecode)))
|
||||
}
|
||||
case let .replyThreadMessage(replyThreadMessage, messageId):
|
||||
if let navigationController = controller.navigationController as? NavigationController {
|
||||
if let navigationController = controller.navigationController as? NavigationController, let effectiveMessageId = replyThreadMessage.effectiveMessageId {
|
||||
let _ = ChatControllerImpl.openMessageReplies(context: context, navigationController: navigationController, present: { [weak controller] c, a in
|
||||
controller?.present(c, in: .window(.root), with: a)
|
||||
}, messageId: replyThreadMessage.messageId, isChannelPost: replyThreadMessage.isChannelPost, atMessage: messageId, displayModalProgress: true).start()
|
||||
}, messageId: effectiveMessageId, isChannelPost: replyThreadMessage.isChannelPost, atMessage: messageId, displayModalProgress: true).start()
|
||||
}
|
||||
case let .replyThread(messageId):
|
||||
if let navigationController = controller.navigationController as? NavigationController {
|
||||
|
|
|
|||
|
|
@ -719,7 +719,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
} else {
|
||||
return .result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
|
|
@ -744,7 +744,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: replyThreadMessageId.id)), threadId: Int64(replyThreadMessageId.id), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: replyId)))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: Int64(replyThreadMessageId.id), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: replyId)))
|
||||
} else {
|
||||
return .result(.peer(peer._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
|
|
@ -760,7 +760,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||
guard let result = result else {
|
||||
return .result(.channelMessage(peer: peer._asPeer(), messageId: replyThreadMessageId, timecode: nil))
|
||||
}
|
||||
return .result(.replyThreadMessage(replyThreadMessage: result, messageId: MessageId(peerId: result.messageId.peerId, namespace: Namespaces.Message.Cloud, id: replyId)))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: result, messageId: MessageId(peerId: result.peerId, namespace: Namespaces.Message.Cloud, id: replyId)))
|
||||
})
|
||||
}
|
||||
case let .voiceChat(invite):
|
||||
|
|
@ -825,7 +825,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: Int64(threadId), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: Int64(threadId), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
} else {
|
||||
return .result(.peer(peer?._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
|
|
@ -849,7 +849,7 @@ private func resolveInternalUrl(context: AccountContext, url: ParsedInternalUrl)
|
|||
return .progress
|
||||
case let .result(info):
|
||||
if let _ = info {
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(messageId: MessageId(peerId: channel.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
return .result(.replyThreadMessage(replyThreadMessage: ChatReplyThreadMessage(peerId: channel.id, threadId: threadId, channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false), messageId: messageId))
|
||||
} else {
|
||||
return .result(.peer(peer?._asPeer(), .chat(textInputState: nil, subject: nil, peekData: nil)))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue