Fetch reply messages with a dedicated method

This commit is contained in:
Ali 2022-11-08 13:38:56 +04:00
parent 45e50a68d7
commit ba0a07aefa
6 changed files with 185 additions and 60 deletions

View File

@ -143,6 +143,38 @@ enum StateResetForumTopics {
case error(PeerId)
}
struct ReferencedReplyMessageIds {
var targetIdsBySourceId: [MessageId: MessageId] = [:]
var isEmpty: Bool {
return self.targetIdsBySourceId.isEmpty
}
mutating func add(sourceId: MessageId, targetId: MessageId) {
if self.targetIdsBySourceId[targetId] == nil {
self.targetIdsBySourceId[targetId] = sourceId
}
}
mutating func formUnion(_ other: ReferencedReplyMessageIds) {
for (targetId, sourceId) in other.targetIdsBySourceId {
if self.targetIdsBySourceId[targetId] == nil {
self.targetIdsBySourceId[targetId] = sourceId
}
}
}
func subtractingStoredIds(_ ids: Set<MessageId>) -> ReferencedReplyMessageIds {
var result = ReferencedReplyMessageIds()
for (targetId, sourceId) in self.targetIdsBySourceId {
if !ids.contains(targetId) {
result.add(sourceId: sourceId, targetId: targetId)
}
}
return result
}
}
struct AccountMutableState {
let initialState: AccountInitialState
let branchOperationIndex: Int
@ -153,7 +185,8 @@ struct AccountMutableState {
var peers: [PeerId: Peer]
var channelStates: [PeerId: AccountStateChannelState]
var peerChatInfos: [PeerId: PeerChatInfo]
var referencedMessageIds: Set<MessageId>
var referencedReplyMessageIds: ReferencedReplyMessageIds
var referencedGeneralMessageIds: Set<MessageId>
var storedMessages: Set<MessageId>
var readInboxMaxIds: [PeerId: MessageId]
var namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]]
@ -176,11 +209,12 @@ struct AccountMutableState {
var authorizationListUpdated: Bool = false
init(initialState: AccountInitialState, initialPeers: [PeerId: Peer], initialReferencedMessageIds: Set<MessageId>, initialStoredMessages: Set<MessageId>, initialReadInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]) {
init(initialState: AccountInitialState, initialPeers: [PeerId: Peer], initialReferencedReplyMessageIds: ReferencedReplyMessageIds, initialReferencedGeneralMessageIds: Set<MessageId>, initialStoredMessages: Set<MessageId>, initialReadInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>]) {
self.initialState = initialState
self.state = initialState.state
self.peers = initialPeers
self.referencedMessageIds = initialReferencedMessageIds
self.referencedReplyMessageIds = initialReferencedReplyMessageIds
self.referencedGeneralMessageIds = initialReferencedGeneralMessageIds
self.storedMessages = initialStoredMessages
self.readInboxMaxIds = initialReadInboxMaxIds
self.channelStates = initialState.channelStates
@ -191,13 +225,14 @@ struct AccountMutableState {
self.updatedOutgoingUniqueMessageIds = [:]
}
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: AccountStateChannelState], peerChatInfos: [PeerId: PeerChatInfo], referencedMessageIds: Set<MessageId>, storedMessages: Set<MessageId>, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]], updatedOutgoingUniqueMessageIds: [Int64: Int32], displayAlerts: [(text: String, isDropAuth: Bool)], dismissBotWebViews: [Int64], branchOperationIndex: Int) {
init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], channelStates: [PeerId: AccountStateChannelState], peerChatInfos: [PeerId: PeerChatInfo], referencedReplyMessageIds: ReferencedReplyMessageIds, referencedGeneralMessageIds: Set<MessageId>, storedMessages: Set<MessageId>, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>], namespacesWithHolesFromPreviousState: [PeerId: [MessageId.Namespace: HoleFromPreviousState]], updatedOutgoingUniqueMessageIds: [Int64: Int32], displayAlerts: [(text: String, isDropAuth: Bool)], dismissBotWebViews: [Int64], branchOperationIndex: Int) {
self.initialState = initialState
self.operations = operations
self.state = state
self.peers = peers
self.channelStates = channelStates
self.referencedMessageIds = referencedMessageIds
self.referencedReplyMessageIds = referencedReplyMessageIds
self.referencedGeneralMessageIds = referencedGeneralMessageIds
self.storedMessages = storedMessages
self.peerChatInfos = peerChatInfos
self.readInboxMaxIds = readInboxMaxIds
@ -210,11 +245,13 @@ struct AccountMutableState {
}
func branch() -> AccountMutableState {
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerChatInfos: self.peerChatInfos, referencedMessageIds: self.referencedMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, updatedOutgoingUniqueMessageIds: self.updatedOutgoingUniqueMessageIds, displayAlerts: self.displayAlerts, dismissBotWebViews: self.dismissBotWebViews, branchOperationIndex: self.operations.count)
return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, channelStates: self.channelStates, peerChatInfos: self.peerChatInfos, referencedReplyMessageIds: self.referencedReplyMessageIds, referencedGeneralMessageIds: self.referencedGeneralMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, updatedOutgoingUniqueMessageIds: self.updatedOutgoingUniqueMessageIds, displayAlerts: self.displayAlerts, dismissBotWebViews: self.dismissBotWebViews, branchOperationIndex: self.operations.count)
}
mutating func merge(_ other: AccountMutableState) {
self.referencedMessageIds.formUnion(other.referencedMessageIds)
self.referencedReplyMessageIds.formUnion(other.referencedReplyMessageIds)
self.referencedGeneralMessageIds.formUnion(other.referencedGeneralMessageIds)
for i in other.branchOperationIndex ..< other.operations.count {
self.addOperation(other.operations[i])
}
@ -567,11 +604,11 @@ struct AccountMutableState {
}
}
}
}
inner: for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute {
self.referencedMessageIds.insert(attribute.messageId)
break inner
inner: for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute {
self.referencedReplyMessageIds.add(sourceId: id, targetId: attribute.messageId)
break inner
}
}
}
}
@ -579,11 +616,11 @@ struct AccountMutableState {
for message in messages {
if case let .Id(id) = message.id {
self.storedMessages.insert(id)
}
inner: for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute {
self.referencedMessageIds.insert(attribute.messageId)
break inner
inner: for attribute in message.attributes {
if let attribute = attribute as? ReplyMessageAttribute {
self.referencedReplyMessageIds.add(sourceId: id, targetId: attribute.messageId)
break inner
}
}
}
}

View File

@ -236,24 +236,30 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] {
}
}
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> [MessageId]? {
func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? {
switch message {
case let .message(_, _, _, chatPeerId, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
case let .message(_, id, _, chatPeerId, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _):
if let replyTo = replyTo {
let peerId: PeerId = chatPeerId.peerId
switch replyTo {
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, _):
return [MessageId(peerId: replyToPeerId?.peerId ?? peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)]
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
var replyIds = ReferencedReplyMessageIds()
replyIds.add(sourceId: MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: id), targetId: targetId)
return (replyIds, [])
}
}
case .messageEmpty:
break
case let .messageService(_, _, _, chatPeerId, replyHeader, _, _, _):
case let .messageService(_, id, _, chatPeerId, replyHeader, _, _, _):
if let replyHeader = replyHeader {
switch replyHeader {
case let .messageReplyHeader(_, replyToMsgId, replyToPeerId, _):
return [MessageId(peerId: replyToPeerId?.peerId ?? chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)]
let targetId = MessageId(peerId: replyToPeerId?.peerId ?? chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: replyToMsgId)
var replyIds = ReferencedReplyMessageIds()
replyIds.add(sourceId: MessageId(peerId: chatPeerId.peerId, namespace: Namespaces.Message.Cloud, id: id), targetId: targetId)
return (replyIds, [])
}
}
}

View File

@ -88,20 +88,20 @@ private func activeChannelsFromUpdateGroups(_ groups: [UpdateGroup]) -> Set<Peer
return peerIds.intersection(peerIdsRequiringLocalChatStateFromUpdateGroups(groups))
}
private func associatedMessageIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> Set<MessageId> {
var messageIds = Set<MessageId>()
private func associatedMessageIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> (replyIds: ReferencedReplyMessageIds, generalIds: Set<MessageId>) {
var replyIds = ReferencedReplyMessageIds()
var generalIds = Set<MessageId>()
for group in groups {
for update in group.updates {
if let associatedMessageIds = update.associatedMessageIds {
for messageId in associatedMessageIds {
messageIds.insert(messageId)
}
replyIds.formUnion(associatedMessageIds.replyIds)
generalIds.formUnion(associatedMessageIds.generalIds)
}
}
}
return messageIds
return (replyIds, generalIds)
}
private func peerIdsRequiringLocalChatStateFromUpdates(_ updates: [Api.Update]) -> Set<PeerId> {
@ -282,23 +282,22 @@ private func activeChannelsFromDifference(_ difference: Api.updates.Difference)
return peerIds
}
private func associatedMessageIdsFromDifference(_ difference: Api.updates.Difference) -> Set<MessageId> {
var messageIds = Set<MessageId>()
private func associatedMessageIdsFromDifference(_ difference: Api.updates.Difference) -> (replyIds: ReferencedReplyMessageIds, generalIds: Set<MessageId>) {
var replyIds = ReferencedReplyMessageIds()
var generalIds = Set<MessageId>()
switch difference {
case let .difference(newMessages, _, otherUpdates, _, _, _):
for message in newMessages {
if let associatedMessageIds = apiMessageAssociatedMessageIds(message) {
for messageId in associatedMessageIds {
messageIds.insert(messageId)
}
replyIds.formUnion(associatedMessageIds.replyIds)
generalIds.formUnion(associatedMessageIds.generalIds)
}
}
for update in otherUpdates {
if let associatedMessageIds = update.associatedMessageIds {
for messageId in associatedMessageIds {
messageIds.insert(messageId)
}
replyIds.formUnion(associatedMessageIds.replyIds)
generalIds.formUnion(associatedMessageIds.generalIds)
}
}
case .differenceEmpty:
@ -306,24 +305,22 @@ private func associatedMessageIdsFromDifference(_ difference: Api.updates.Differ
case let .differenceSlice(newMessages, _, otherUpdates, _, _, _):
for message in newMessages {
if let associatedMessageIds = apiMessageAssociatedMessageIds(message) {
for messageId in associatedMessageIds {
messageIds.insert(messageId)
}
replyIds.formUnion(associatedMessageIds.replyIds)
generalIds.formUnion(associatedMessageIds.generalIds)
}
}
for update in otherUpdates {
if let associatedMessageIds = update.associatedMessageIds {
for messageId in associatedMessageIds {
messageIds.insert(messageId)
}
replyIds.formUnion(associatedMessageIds.replyIds)
generalIds.formUnion(associatedMessageIds.generalIds)
}
}
case .differenceTooLong:
break
}
return messageIds
return (replyIds, generalIds)
}
private func peerIdsRequiringLocalChatStateFromDifference(_ difference: Api.updates.Difference) -> Set<PeerId> {
@ -424,7 +421,7 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u
return messageTimestamps
}
private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<PeerId>, activeChannelIds: Set<PeerId>, associatedMessageIds: Set<MessageId>, peerIdsRequiringLocalChatState: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<PeerId>, activeChannelIds: Set<PeerId>, referencedReplyMessageIds: ReferencedReplyMessageIds, referencedGeneralMessageIds: Set<MessageId>, peerIdsRequiringLocalChatState: Set<PeerId>, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState {
var peers: [PeerId: Peer] = [:]
var channelStates: [PeerId: AccountStateChannelState] = [:]
@ -454,7 +451,8 @@ private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<Pe
}
}
let storedMessages = transaction.filterStoredMessageIds(associatedMessageIds)
let storedMessages = transaction.filterStoredMessageIds(Set(referencedReplyMessageIds.targetIdsBySourceId.keys).union(referencedGeneralMessageIds))
var storedMessagesByPeerIdAndTimestamp: [PeerId: Set<MessageIndex>] = [:]
if !locallyGeneratedMessageTimestamps.isEmpty {
for (peerId, namespacesAndTimestamps) in locallyGeneratedMessageTimestamps {
@ -517,7 +515,7 @@ private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set<Pe
}
}
let state = AccountMutableState(initialState: AccountInitialState(state: (transaction.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates, channelsToPollExplicitely: channelsToPollExplicitely), initialPeers: peers, initialReferencedMessageIds: associatedMessageIds, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
let state = AccountMutableState(initialState: AccountInitialState(state: (transaction.getState() as? AuthorizedAccountState)!.state!, peerIds: peerIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestamps, cloudReadStates: cloudReadStates, channelsToPollExplicitely: channelsToPollExplicitely), initialPeers: peers, initialReferencedReplyMessageIds: referencedReplyMessageIds, initialReferencedGeneralMessageIds: referencedGeneralMessageIds, initialStoredMessages: storedMessages, initialReadInboxMaxIds: readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: storedMessagesByPeerIdAndTimestamp)
return state
}
@ -528,7 +526,7 @@ func initialStateWithUpdateGroups(postbox: Postbox, groups: [UpdateGroup]) -> Si
let associatedMessageIds = associatedMessageIdsFromUpdateGroups(groups)
let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromUpdateGroups(groups)
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromUpdateGroups(groups))
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, referencedReplyMessageIds: associatedMessageIds.replyIds, referencedGeneralMessageIds: associatedMessageIds.generalIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromUpdateGroups(groups))
}
}
@ -538,7 +536,7 @@ func initialStateWithDifference(postbox: Postbox, difference: Api.updates.Differ
let activeChannelIds = activeChannelsFromDifference(difference)
let associatedMessageIds = associatedMessageIdsFromDifference(difference)
let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromDifference(difference)
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromDifference(difference))
return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, referencedReplyMessageIds: associatedMessageIds.replyIds, referencedGeneralMessageIds: associatedMessageIds.generalIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromDifference(difference))
}
}
@ -2058,8 +2056,10 @@ private func reactionsFromState(_ state: AccountMutableState) -> [MessageReactio
}
private func resolveAssociatedMessages(postbox: Postbox, network: Network, state: AccountMutableState) -> Signal<AccountMutableState, NoError> {
let missingMessageIds = state.referencedMessageIds.subtracting(state.storedMessages)
if missingMessageIds.isEmpty {
let missingReplyMessageIds = state.referencedReplyMessageIds.subtractingStoredIds(state.storedMessages)
let missingGeneralMessageIds = state.referencedGeneralMessageIds.subtracting(state.storedMessages)
if missingReplyMessageIds.isEmpty && missingGeneralMessageIds.isEmpty {
return resolveUnknownEmojiFiles(postbox: postbox, source: .network(network), messages: messagesFromOperations(state: state), reactions: reactionsFromState(state), result: state)
|> mapToSignal { state in
return resolveForumThreads(postbox: postbox, network: network, state: state)
@ -2069,7 +2069,38 @@ private func resolveAssociatedMessages(postbox: Postbox, network: Network, state
let _ = missingPeers
var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = []
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingMessageIds) {
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingReplyMessageIds) {
if let peer = state.peers[peerId] {
var signal: Signal<Api.messages.Messages, MTRpcError>?
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
signal = network.request(Api.functions.messages.getMessages(id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
if let inputChannel = apiInputChannel(peer) {
signal = network.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
}
}
if let signal = signal {
signals.append(signal |> map { result in
switch result {
case let .messages(messages, chats, users):
return (messages, chats, users)
case let .messagesSlice(_, _, _, _, messages, chats, users):
return (messages, chats, users)
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
let _ = apiTopics
return (messages, chats, users)
case .messagesNotModified:
return ([], [], [])
}
} |> `catch` { _ in
return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], []))
})
}
} else {
missingPeers = true
}
}
for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingGeneralMessageIds) {
if let peer = state.peers[peerId] {
var signal: Signal<Api.messages.Messages, MTRpcError>?
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
@ -2290,7 +2321,7 @@ func pollChannelOnce(accountPeerId: PeerId, postbox: Postbox, network: Network,
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
}
}
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedReplyMessageIds: ReferencedReplyMessageIds(), initialReferencedGeneralMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState)
|> mapToSignal { (finalState, _, timeout) -> Signal<Int32, NoError> in
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)
@ -2344,7 +2375,7 @@ public func standalonePollChannelOnce(accountPeerId: PeerId, postbox: Postbox, n
peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings)
}
}
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), channelStates: channelStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedReplyMessageIds: ReferencedReplyMessageIds(), initialReferencedGeneralMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:])
return pollChannel(accountPeerId: accountPeerId, postbox: postbox, network: network, peer: peer, state: initialState)
|> mapToSignal { (finalState, _, timeout) -> Signal<Never, NoError> in
return resolveAssociatedMessages(postbox: postbox, network: network, state: finalState)

View File

@ -103,20 +103,29 @@ func resolveUnknownEmojiFiles<T>(postbox: Postbox, source: FetchMessageHistoryHo
private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMessageHistoryHoleSource, peers: [PeerId: Peer], storeMessages: [StoreMessage], _ f: @escaping (Transaction, [Peer], [StoreMessage]) -> T) -> Signal<T, NoError> {
return postbox.transaction { transaction -> Signal<T, NoError> in
var storedIds = Set<MessageId>()
var referencedIds = Set<MessageId>()
var referencedReplyIds = ReferencedReplyMessageIds()
var referencedGeneralIds = Set<MessageId>()
for message in storeMessages {
guard case let .Id(id) = message.id else {
continue
}
storedIds.insert(id)
for attribute in message.attributes {
referencedIds.formUnion(attribute.associatedMessageIds)
if let attribute = attribute as? ReplyMessageAttribute {
referencedReplyIds.add(sourceId: id, targetId: attribute.messageId)
} else {
referencedGeneralIds.formUnion(attribute.associatedMessageIds)
}
}
}
referencedIds.subtract(storedIds)
referencedIds.subtract(transaction.filterStoredMessageIds(referencedIds))
if referencedIds.isEmpty {
let allPossiblyStoredReferencedIds = storedIds.union(referencedGeneralIds).union(referencedReplyIds.targetIdsBySourceId.keys)
let allStoredReferencedIds = transaction.filterStoredMessageIds(allPossiblyStoredReferencedIds)
referencedReplyIds = referencedReplyIds.subtractingStoredIds(allStoredReferencedIds)
referencedGeneralIds.subtract(allStoredReferencedIds)
if referencedReplyIds.isEmpty && referencedGeneralIds.isEmpty {
return resolveUnknownEmojiFiles(postbox: postbox, source: source, messages: storeMessages, reactions: [], result: Void())
|> mapToSignal { _ -> Signal<T, NoError> in
return postbox.transaction { transaction -> T in
@ -125,7 +134,38 @@ private func withResolvedAssociatedMessages<T>(postbox: Postbox, source: FetchMe
}
} else {
var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = []
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedIds) {
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedReplyIds) {
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
var signal: Signal<Api.messages.Messages, MTRpcError>?
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {
signal = source.request(Api.functions.messages.getMessages(id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
} else if peerId.namespace == Namespaces.Peer.CloudChannel {
if let inputChannel = apiInputChannel(peer) {
signal = source.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.targetIdsBySourceId.values.map({ Api.InputMessage.inputMessageReplyTo(id: $0.id) })))
}
}
if let signal = signal {
signals.append(signal
|> map { result in
switch result {
case let .messages(messages, chats, users):
return (messages, chats, users)
case let .messagesSlice(_, _, _, _, messages, chats, users):
return (messages, chats, users)
case let .channelMessages(_, _, _, _, messages, apiTopics, chats, users):
let _ = apiTopics
return (messages, chats, users)
case .messagesNotModified:
return ([], [], [])
}
}
|> `catch` { _ in
return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], []))
})
}
}
}
for (peerId, messageIds) in messagesIdsGroupedByPeerId(referencedGeneralIds) {
if let peer = transaction.getPeer(peerId) ?? peers[peerId] {
var signal: Signal<Api.messages.Messages, MTRpcError>?
if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup {

View File

@ -305,7 +305,7 @@ extension Api.Update {
}
}
var associatedMessageIds: [MessageId]? {
var associatedMessageIds: (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? {
switch self {
case let .updateNewMessage(message, _, _):
return apiMessageAssociatedMessageIds(message)

View File

@ -156,6 +156,17 @@ func messagesIdsGroupedByPeerId(_ ids: [MessageId]) -> [PeerId: [MessageId]] {
return dict
}
func messagesIdsGroupedByPeerId(_ ids: ReferencedReplyMessageIds) -> [PeerId: ReferencedReplyMessageIds] {
var dict: [PeerId: ReferencedReplyMessageIds] = [:]
for (targetId, sourceId) in ids.targetIdsBySourceId {
let peerId = sourceId.peerId
dict[peerId, default: ReferencedReplyMessageIds()].add(sourceId: sourceId, targetId: targetId)
}
return dict
}
func locallyRenderedMessage(message: StoreMessage, peers: [PeerId: Peer]) -> Message? {
guard case let .Id(id) = message.id else {
return nil