diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index a999a2f534..29668b118c 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -13,6 +13,10 @@ C2366C871E4F403C0097CCFF /* AddressNames.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C851E4F403C0097CCFF /* AddressNames.swift */; }; C2366C891E4F40480097CCFF /* SupportPeerId.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C881E4F40480097CCFF /* SupportPeerId.swift */; }; C2366C8A1E4F40480097CCFF /* SupportPeerId.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2366C881E4F40480097CCFF /* SupportPeerId.swift */; }; + C239BE971E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift in Sources */ = {isa = PBXBuildFile; fileRef = C239BE961E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift */; }; + C239BE981E62F0D200C2C453 /* LoadMessagesIfNecessary.swift in Sources */ = {isa = PBXBuildFile; fileRef = C239BE961E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift */; }; + C239BE9C1E630CA700C2C453 /* UpdatePinnedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C239BE9B1E630CA700C2C453 /* UpdatePinnedMessage.swift */; }; + C239BE9D1E630CB300C2C453 /* UpdatePinnedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C239BE9B1E630CA700C2C453 /* UpdatePinnedMessage.swift */; }; C26A37EF1E5E0C41006977AC /* ChannelParticipants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BB7C591E5C8074001527C3 /* ChannelParticipants.swift */; }; C2A315C01E2E776A00D89000 /* RequestStartBot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01749581E1092BC0057C89A /* RequestStartBot.swift */; }; D001F3E81E128A1C007A8C60 /* ChannelState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B0CFF1D62255C00955575 /* ChannelState.swift */; }; @@ -413,6 +417,8 @@ C2366C821E4F3EAA0097CCFF /* GroupReturnAndLeft.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupReturnAndLeft.swift; sourceTree = ""; }; C2366C851E4F403C0097CCFF /* AddressNames.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddressNames.swift; sourceTree = ""; }; C2366C881E4F40480097CCFF /* SupportPeerId.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SupportPeerId.swift; sourceTree = ""; }; + C239BE961E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadMessagesIfNecessary.swift; sourceTree = ""; }; + C239BE9B1E630CA700C2C453 /* UpdatePinnedMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatePinnedMessage.swift; sourceTree = ""; }; D003702A1DA42586004308D3 /* PhoneNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhoneNumber.swift; sourceTree = ""; }; D00C7CCB1E3620C30080C3D5 /* CachedChannelParticipants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CachedChannelParticipants.swift; sourceTree = ""; }; D00C7CCE1E3628180080C3D5 /* UpdateCachedChannelParticipants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdateCachedChannelParticipants.swift; sourceTree = ""; }; @@ -942,6 +948,7 @@ D02ABC7A1E30058F00CAE539 /* DeleteMessagesInteractively.swift */, D0AAD1A91E32638500D5B9DE /* ApplyMaxReadIndexInteractively.swift */, D00C7CDF1E3785700080C3D5 /* MarkMessageContentAsConsumedInteractively.swift */, + C239BE961E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift */, ); name = Messages; sourceTree = ""; @@ -1081,6 +1088,7 @@ D0613FD61E606B3B00202CDB /* ConvertGroupToSupergroup.swift */, D033FEB21E61F3C000644997 /* ReportPeer.swift */, D033FEB51E61F3F900644997 /* BlockedPeers.swift */, + C239BE9B1E630CA700C2C453 /* UpdatePinnedMessage.swift */, ); name = Peers; sourceTree = ""; @@ -1403,6 +1411,7 @@ D0BEAF5D1E54941B00BD963D /* Authorization.swift in Sources */, D0B843831DA6EDB8005F29E1 /* CachedGroupData.swift in Sources */, D0E35A121DE4A25E00BC6096 /* OutgoingChatContextResultMessageAttribute.swift in Sources */, + C239BE9C1E630CA700C2C453 /* UpdatePinnedMessage.swift in Sources */, D0B844531DAC0773005F29E1 /* TelegramUserPresence.swift in Sources */, D0B843871DA6F705005F29E1 /* UpdateCachedPeerData.swift in Sources */, D03B0D6D1D631AA300955575 /* ContactManagement.swift in Sources */, @@ -1443,6 +1452,7 @@ D03B0E441D631E6600955575 /* NetworkLogging.m in Sources */, D03121021DA57E93006A2A60 /* TelegramPeerNotificationSettings.swift in Sources */, D03B0CBB1D62233C00955575 /* MergeLists.swift in Sources */, + C239BE971E62EE1E00C2C453 /* LoadMessagesIfNecessary.swift in Sources */, D03B0CC11D62235000955575 /* StringFormat.swift in Sources */, D0B843C31DA7FF30005F29E1 /* NBPhoneMetaDataGenerator.m in Sources */, C2366C861E4F403C0097CCFF /* AddressNames.swift in Sources */, @@ -1477,6 +1487,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + C239BE9D1E630CB300C2C453 /* UpdatePinnedMessage.swift in Sources */, + C239BE981E62F0D200C2C453 /* LoadMessagesIfNecessary.swift in Sources */, C26A37EF1E5E0C41006977AC /* ChannelParticipants.swift in Sources */, D050F26A1E4A5B6D00988324 /* ManagedGlobalNotificationSettings.swift in Sources */, D050F26B1E4A5B6D00988324 /* ApplyMaxReadIndexInteractively.swift in Sources */, diff --git a/TelegramCore/AccountStateManagementUtils.swift b/TelegramCore/AccountStateManagementUtils.swift index 681cd2879f..a2d25289be 100644 --- a/TelegramCore/AccountStateManagementUtils.swift +++ b/TelegramCore/AccountStateManagementUtils.swift @@ -887,20 +887,6 @@ private func finalStateWithUpdates(account: Account, state: AccountMutableState, } } -private func messagesIdsGroupedByPeerId(_ ids: Set) -> [PeerId: [MessageId]] { - var dict: [PeerId: [MessageId]] = [:] - - for id in ids { - let peerId = id.peerId - if dict[peerId] == nil { - dict[peerId] = [id] - } else { - dict[peerId]!.append(id) - } - } - - return dict -} private func resolveAssociatedMessages(account: Account, state: AccountMutableState) -> Signal { let missingMessageIds = state.initialState.messageIds.subtracting(state.storedMessages) diff --git a/TelegramCore/LoadMessagesIfNecessary.swift b/TelegramCore/LoadMessagesIfNecessary.swift index cde6d26bd6..2c856c3726 100644 --- a/TelegramCore/LoadMessagesIfNecessary.swift +++ b/TelegramCore/LoadMessagesIfNecessary.swift @@ -1,13 +1,121 @@ -// -// LoadMessagesIfNecessary.swift -// TelegramCore -// -// Created by keepcoder on 26/02/2017. -// Copyright © 2017 Peter. All rights reserved. -// +import Foundation +#if os(macOS) + import PostboxMac + import SwiftSignalKitMac + import MtProtoKitMac +#else + import Postbox + import SwiftSignalKit + import MtProtoKitDynamic +#endif -import Cocoa - -class LoadMessagesIfNecessary: NSObject { +public enum GetMessagesStrategy { + case local + case cloud +} + +public func getMessagesLoadIfNecessary(_ messageIds:[MessageId], postbox:Postbox, network:Network, strategy:GetMessagesStrategy = .cloud) -> Signal <[Message], Void> { + + + let postboxSignal = postbox.modify { modifier -> ([Message], Set, SimpleDictionary) in + var messages:[Message] = [] + var missingMessageIds:Set = Set() + var supportPeers:SimpleDictionary = SimpleDictionary() + for messageId in messageIds { + if let message = modifier.getMessage(messageId) { + messages.append(message) + } else { + missingMessageIds.insert(messageId) + if let peer = modifier.getPeer(messageId.peerId) { + supportPeers[messageId.peerId] = peer + } + } + } + return (messages, missingMessageIds, supportPeers) + } + + if strategy == .cloud { + return postboxSignal |> mapToSignal { (existMessages, missingMessageIds, supportPeers) in + + var signals: [Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>] = [] + for (peerId, messageIds) in messagesIdsGroupedByPeerId(missingMessageIds) { + if let peer = supportPeers[peerId] { + var signal: Signal? + if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup { + signal = network.request(Api.functions.messages.getMessages(id: messageIds.map({ $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.map({ $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, chats, users): + return (messages, chats, users) + } + } |> `catch` { _ in + return Signal<([Api.Message], [Api.Chat], [Api.User]), NoError>.single(([], [], [])) + }) + } + } + } + + return combineLatest(signals) |> mapToSignal { results -> Signal<[Message], Void> in + + return postbox.modify { modifier -> [Message] in + + for (messages, chats, users) in results { + if !messages.isEmpty { + var storeMessages: [StoreMessage] = [] + + for message in messages { + if let message = StoreMessage(apiMessage: message) { + storeMessages.append(message) + } + } + _ = modifier.addMessages(storeMessages, location: .Random) + } + + var peers: [Peer] = [] + var peerPresences: [PeerId: PeerPresence] = [:] + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) + } + } + for user in users { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + if let presence = TelegramUserPresence(apiUser: user) { + peerPresences[telegramUser.id] = presence + } + } + + updatePeers(modifier: modifier, peers: peers, update: { _, updated -> Peer in + return updated + }) + modifier.updatePeerPresences(peerPresences) + } + var loadedMessages:[Message] = [] + for messageId in missingMessageIds { + if let message = modifier.getMessage(messageId) { + loadedMessages.append(message) + } + } + + return existMessages + loadedMessages + } + } + + } + } else { + return postboxSignal |> map {$0.0} + } + } diff --git a/TelegramCore/MessageUtils.swift b/TelegramCore/MessageUtils.swift index fe065b1670..93652414aa 100644 --- a/TelegramCore/MessageUtils.swift +++ b/TelegramCore/MessageUtils.swift @@ -56,3 +56,19 @@ public extension Message { return false } } + + +func messagesIdsGroupedByPeerId(_ ids: Set) -> [PeerId: [MessageId]] { + var dict: [PeerId: [MessageId]] = [:] + + for id in ids { + let peerId = id.peerId + if dict[peerId] == nil { + dict[peerId] = [id] + } else { + dict[peerId]!.append(id) + } + } + + return dict +} diff --git a/TelegramCore/UpdatePinnedMessage.swift b/TelegramCore/UpdatePinnedMessage.swift index 3a4517f788..fd90c4d429 100644 --- a/TelegramCore/UpdatePinnedMessage.swift +++ b/TelegramCore/UpdatePinnedMessage.swift @@ -13,7 +13,7 @@ public enum UpdatePinnedMessageError { case generic } -public func updatePinnedMessage(_ pinnedMessageId:MessageId?, for peerId:PeerId, account:Account) -> Signal { +public func updatePinnedMessage(_ pinnedMessageId:MessageId?, silent:Bool = false, for peerId:PeerId, account:Account) -> Signal { return account.postbox.modify { modifier -> Peer? in return modifier.getPeer(peerId) } |> mapError { () -> UpdatePinnedMessageError in @@ -32,7 +32,7 @@ public func updatePinnedMessage(_ pinnedMessageId:MessageId?, for peerId:PeerId, var flags:Int32 = 0 let messageId:Int32 = pinnedMessageId?.id ?? 0 - if messageId > 0 { + if silent { flags |= (1 << 0) } @@ -43,6 +43,7 @@ public func updatePinnedMessage(_ pinnedMessageId:MessageId?, for peerId:PeerId, return .generic } |> mapToSignal { updates -> Signal in + account.stateManager.addUpdates(updates) return account.postbox.modify { modifier in modifier.updatePeerCachedData(peerIds: Set([peerId]), update: { _, current in if let current = current as? CachedChannelData {