diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index 5b4c9ef05d..717ea2eaca 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -368,7 +368,7 @@ public class GalleryController: ViewController { switch source { case .peerMessagesAtId: if let tags = tagsForMessage(message!) { - let namespaces: HistoryViewNamespaces + let namespaces: MessageIdNamespaces if Namespaces.Message.allScheduled.contains(message!.id.namespace) { namespaces = .just(Namespaces.Message.allScheduled) } else { diff --git a/submodules/Postbox/Postbox/Message.swift b/submodules/Postbox/Postbox/Message.swift index d2f402bd53..aef32af5b9 100644 --- a/submodules/Postbox/Postbox/Message.swift +++ b/submodules/Postbox/Postbox/Message.swift @@ -726,3 +726,20 @@ final class InternalStoreMessage { self.media = media } } + +public enum MessageIdNamespaces { + case all + case just(Set) + case not(Set) + + public func contains(_ namespace: MessageId.Namespace) -> Bool { + switch self { + case .all: + return true + case let .just(namespaces): + return namespaces.contains(namespace) + case let .not(namespaces): + return !namespaces.contains(namespace) + } + } +} diff --git a/submodules/Postbox/Postbox/MessageHistoryTable.swift b/submodules/Postbox/Postbox/MessageHistoryTable.swift index 644d81e914..701d92990a 100644 --- a/submodules/Postbox/Postbox/MessageHistoryTable.swift +++ b/submodules/Postbox/Postbox/MessageHistoryTable.swift @@ -2422,9 +2422,18 @@ final class MessageHistoryTable: Table { return messageIds } - func allMessageIndices(peerId: PeerId) -> [MessageIndex] { + func allMessageIndices(peerId: PeerId, namespace: MessageId.Namespace? = nil) -> [MessageIndex] { var messages: [MessageIndex] = [] - self.valueBox.range(self.table, start: self.key(MessageIndex.lowerBound(peerId: peerId)).predecessor, end: self.key(MessageIndex.upperBound(peerId: peerId)).successor, keys: { key in + let start: ValueBoxKey + let end: ValueBoxKey + if let namespace = namespace { + start = self.lowerBound(peerId: peerId, namespace: namespace) + end = self.upperBound(peerId: peerId, namespace: namespace) + } else { + start = self.key(MessageIndex.lowerBound(peerId: peerId)).predecessor + end = self.key(MessageIndex.upperBound(peerId: peerId)).successor + } + self.valueBox.range(self.table, start: start, end: end, keys: { key in messages.append(extractKey(key)) return true }, limit: 0) diff --git a/submodules/Postbox/Postbox/MessageHistoryView.swift b/submodules/Postbox/Postbox/MessageHistoryView.swift index c21ad9de35..0a5aed86a2 100644 --- a/submodules/Postbox/Postbox/MessageHistoryView.swift +++ b/submodules/Postbox/Postbox/MessageHistoryView.swift @@ -224,27 +224,10 @@ public enum HistoryViewInputAnchor: Equatable { case unread } -public enum HistoryViewNamespaces { - case all - case just(Set) - case not(Set) - - public func contains(_ namespace: MessageId.Namespace) -> Bool { - switch self { - case .all: - return true - case let .just(namespaces): - return namespaces.contains(namespace) - case let .not(namespaces): - return !namespaces.contains(namespace) - } - } -} - final class MutableMessageHistoryView { private(set) var peerIds: MessageHistoryViewPeerIds let tag: MessageTags? - let namespaces: HistoryViewNamespaces + let namespaces: MessageIdNamespaces private let orderStatistics: MessageHistoryViewOrderStatistics private let anchor: HistoryViewInputAnchor @@ -259,7 +242,7 @@ final class MutableMessageHistoryView { fileprivate(set) var sampledState: HistoryViewSample - init(postbox: Postbox, orderStatistics: MessageHistoryViewOrderStatistics, peerIds: MessageHistoryViewPeerIds, anchor inputAnchor: HistoryViewInputAnchor, combinedReadStates: MessageHistoryViewReadState?, transientReadStates: MessageHistoryViewReadState?, tag: MessageTags?, namespaces: HistoryViewNamespaces, count: Int, topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?], additionalDatas: [AdditionalMessageHistoryViewDataEntry], getMessageCountInRange: (MessageIndex, MessageIndex) -> Int32) { + init(postbox: Postbox, orderStatistics: MessageHistoryViewOrderStatistics, peerIds: MessageHistoryViewPeerIds, anchor inputAnchor: HistoryViewInputAnchor, combinedReadStates: MessageHistoryViewReadState?, transientReadStates: MessageHistoryViewReadState?, tag: MessageTags?, namespaces: MessageIdNamespaces, count: Int, topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?], additionalDatas: [AdditionalMessageHistoryViewDataEntry], getMessageCountInRange: (MessageIndex, MessageIndex) -> Int32) { self.anchor = inputAnchor self.orderStatistics = orderStatistics @@ -689,7 +672,7 @@ final class MutableMessageHistoryView { public final class MessageHistoryView { public let tagMask: MessageTags? - public let namespaces: HistoryViewNamespaces + public let namespaces: MessageIdNamespaces public let anchorIndex: MessageHistoryAnchorIndex public let earlierId: MessageIndex? public let laterId: MessageIndex? diff --git a/submodules/Postbox/Postbox/MessageHistoryViewState.swift b/submodules/Postbox/Postbox/MessageHistoryViewState.swift index 10a6084cfb..c00bb54ef6 100644 --- a/submodules/Postbox/Postbox/MessageHistoryViewState.swift +++ b/submodules/Postbox/Postbox/MessageHistoryViewState.swift @@ -748,7 +748,7 @@ struct HistoryViewLoadedSample { final class HistoryViewLoadedState { let anchor: HistoryViewAnchor let tag: MessageTags? - let namespaces: HistoryViewNamespaces + let namespaces: MessageIdNamespaces let statistics: MessageHistoryViewOrderStatistics let halfLimit: Int let seedConfiguration: SeedConfiguration @@ -756,7 +756,7 @@ final class HistoryViewLoadedState { var holes: HistoryViewHoles var spacesWithRemovals = Set() - init(anchor: HistoryViewAnchor, tag: MessageTags?, namespaces: HistoryViewNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewPeerIds, postbox: Postbox, holes: HistoryViewHoles) { + init(anchor: HistoryViewAnchor, tag: MessageTags?, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewPeerIds, postbox: Postbox, holes: HistoryViewHoles) { precondition(halfLimit >= 3) self.anchor = anchor self.tag = tag @@ -1178,7 +1178,7 @@ final class HistoryViewLoadedState { } } -private func fetchHoles(postbox: Postbox, locations: MessageHistoryViewPeerIds, tag: MessageTags?, namespaces: HistoryViewNamespaces) -> [PeerIdAndNamespace: IndexSet] { +private func fetchHoles(postbox: Postbox, locations: MessageHistoryViewPeerIds, tag: MessageTags?, namespaces: MessageIdNamespaces) -> [PeerIdAndNamespace: IndexSet] { var holesBySpace: [PeerIdAndNamespace: IndexSet] = [:] var peerIds: [PeerId] = [] switch locations { @@ -1217,7 +1217,7 @@ final class HistoryViewLoadingState { let halfLimit: Int var holes: HistoryViewHoles - init(postbox: Postbox, locations: MessageHistoryViewPeerIds, tag: MessageTags?, namespaces: HistoryViewNamespaces, messageId: MessageId, halfLimit: Int) { + init(postbox: Postbox, locations: MessageHistoryViewPeerIds, tag: MessageTags?, namespaces: MessageIdNamespaces, messageId: MessageId, halfLimit: Int) { self.messageId = messageId self.tag = tag self.halfLimit = halfLimit @@ -1261,7 +1261,7 @@ enum HistoryViewState { case loaded(HistoryViewLoadedState) case loading(HistoryViewLoadingState) - init(postbox: Postbox, inputAnchor: HistoryViewInputAnchor, tag: MessageTags?, namespaces: HistoryViewNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewPeerIds) { + init(postbox: Postbox, inputAnchor: HistoryViewInputAnchor, tag: MessageTags?, namespaces: MessageIdNamespaces, statistics: MessageHistoryViewOrderStatistics, halfLimit: Int, locations: MessageHistoryViewPeerIds) { switch inputAnchor { case let .index(index): self = .loaded(HistoryViewLoadedState(anchor: .index(index), tag: tag, namespaces: namespaces, statistics: statistics, halfLimit: halfLimit, locations: locations, postbox: postbox, holes: HistoryViewHoles(holesBySpace: fetchHoles(postbox: postbox, locations: locations, tag: tag, namespaces: namespaces)))) diff --git a/submodules/Postbox/Postbox/Postbox.swift b/submodules/Postbox/Postbox/Postbox.swift index 005b38a090..c7216d6498 100644 --- a/submodules/Postbox/Postbox/Postbox.swift +++ b/submodules/Postbox/Postbox/Postbox.swift @@ -82,8 +82,8 @@ public final class Transaction { self.postbox?.deleteMessagesInRange(peerId: peerId, namespace: namespace, minId: minId, maxId: maxId) } - public func withAllMessages(peerId: PeerId, _ f: (Message) -> Bool) { - self.postbox?.withAllMessages(peerId: peerId, f) + public func withAllMessages(peerId: PeerId, namespace: MessageId.Namespace? = nil, _ f: (Message) -> Bool) { + self.postbox?.withAllMessages(peerId: peerId, namespace: namespace, f) } public func clearHistory(_ peerId: PeerId) { @@ -1507,8 +1507,8 @@ public final class Postbox { self.messageHistoryTable.removeMessagesInRange(peerId: peerId, namespace: namespace, minId: minId, maxId: maxId, operationsByPeerId: &self.currentOperationsByPeerId, updatedMedia: &self.currentUpdatedMedia, unsentMessageOperations: ¤tUnsentOperations, updatedPeerReadStateOperations: &self.currentUpdatedSynchronizeReadStateOperations, globalTagsOperations: &self.currentGlobalTagsOperations, pendingActionsOperations: &self.currentPendingMessageActionsOperations, updatedMessageActionsSummaries: &self.currentUpdatedMessageActionsSummaries, updatedMessageTagSummaries: &self.currentUpdatedMessageTagSummaries, invalidateMessageTagSummaries: &self.currentInvalidateMessageTagSummaries, localTagsOperations: &self.currentLocalTagsOperations) } - fileprivate func withAllMessages(peerId: PeerId, _ f: (Message) -> Bool) { - for index in self.messageHistoryTable.allMessageIndices(peerId: peerId) { + fileprivate func withAllMessages(peerId: PeerId, namespace: MessageId.Namespace?, _ f: (Message) -> Bool) { + for index in self.messageHistoryTable.allMessageIndices(peerId: peerId, namespace: namespace) { if let message = self.messageHistoryTable.getMessage(index) { if !f(self.renderIntermediateMessage(message)) { break @@ -2219,7 +2219,7 @@ public final class Postbox { return peerIds } - public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocation, count: Int, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: HistoryViewNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundMessageOfInterestHistoryViewForChatLocation(_ chatLocation: ChatLocation, count: Int, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { return self.transactionSignal(userInteractive: true, { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, tagMask: tagMask) @@ -2267,14 +2267,14 @@ public final class Postbox { }) } - public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, messageId: MessageId, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: HistoryViewNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundIdMessageHistoryViewForLocation(_ chatLocation: ChatLocation, count: Int, messageId: MessageId, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { return self.transactionSignal { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, tagMask: tagMask) return self.syncAroundMessageHistoryViewForPeerId(subscriber: subscriber, peerIds: peerIds, count: count, anchor: .message(messageId), fixedCombinedReadStates: nil, topTaggedMessageIdNamespaces: topTaggedMessageIdNamespaces, tagMask: tagMask, namespaces: namespaces, orderStatistics: orderStatistics, additionalData: additionalData) } } - public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, anchor: HistoryViewInputAnchor, count: Int, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: HistoryViewNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { + public func aroundMessageHistoryViewForLocation(_ chatLocation: ChatLocation, anchor: HistoryViewInputAnchor, count: Int, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData] = []) -> Signal<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError> { return self.transactionSignal { subscriber, transaction in let peerIds = self.peerIdsForLocation(chatLocation, tagMask: tagMask) @@ -2282,7 +2282,7 @@ public final class Postbox { } } - private func syncAroundMessageHistoryViewForPeerId(subscriber: Subscriber<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>, peerIds: MessageHistoryViewPeerIds, count: Int, anchor: HistoryViewInputAnchor, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: HistoryViewNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Disposable { + private func syncAroundMessageHistoryViewForPeerId(subscriber: Subscriber<(MessageHistoryView, ViewUpdateType, InitialMessageHistoryData?), NoError>, peerIds: MessageHistoryViewPeerIds, count: Int, anchor: HistoryViewInputAnchor, fixedCombinedReadStates: MessageHistoryViewReadState?, topTaggedMessageIdNamespaces: Set, tagMask: MessageTags?, namespaces: MessageIdNamespaces, orderStatistics: MessageHistoryViewOrderStatistics, additionalData: [AdditionalMessageHistoryViewData]) -> Disposable { var topTaggedMessages: [MessageId.Namespace: MessageHistoryTopTaggedMessage?] = [:] var mainPeerId: PeerId? switch peerIds { diff --git a/submodules/TelegramCore/TelegramCore/AccountIntermediateState.swift b/submodules/TelegramCore/TelegramCore/AccountIntermediateState.swift index 447163567f..4ba684656c 100644 --- a/submodules/TelegramCore/TelegramCore/AccountIntermediateState.swift +++ b/submodules/TelegramCore/TelegramCore/AccountIntermediateState.swift @@ -66,6 +66,7 @@ enum AccountStateGlobalNotificationSettingsSubject { enum AccountStateMutationOperation { case AddMessages([StoreMessage], AddMessagesLocation) + case AddScheduledMessages([StoreMessage]) case DeleteMessagesWithGlobalIds([Int32]) case DeleteMessages([MessageId]) case EditMessage(MessageId, StoreMessage) @@ -200,6 +201,10 @@ struct AccountMutableState { self.addOperation(.AddMessages(messages, location)) } + mutating func addScheduledMessages(_ messages: [StoreMessage]) { + self.addOperation(.AddScheduledMessages(messages)) + } + mutating func addDisplayAlert(_ text: String, isDropAuth: Bool) { self.displayAlerts.append((text: text, isDropAuth: isDropAuth)) } @@ -427,7 +432,18 @@ struct AccountMutableState { break inner } } - + } + case let .AddScheduledMessages(messages): + 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 + } + } } case let .UpdateState(state): self.state = state diff --git a/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift b/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift index 244df06a7f..d5a5384b50 100644 --- a/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/TelegramCore/AccountStateManagementUtils.swift @@ -1306,7 +1306,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo updatedState.updatePeersNearby(peersNearby) case let .updateNewScheduledMessage(apiMessage): if let message = StoreMessage(apiMessage: apiMessage, namespace: Namespaces.Message.ScheduledCloud) { - updatedState.addMessages([message], location: .Random) + updatedState.addScheduledMessages([message]) } case let .updateDeleteScheduledMessages(peer, messages): var messageIds: [MessageId] = [] @@ -2025,12 +2025,16 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation]) var updatedChannelStates: [PeerId: ChannelState] = [:] var currentAddMessages: OptimizeAddMessagesState? + var currentAddScheduledMessages: OptimizeAddMessagesState? for operation in operations { switch operation { case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMessageReactions, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby: if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty { result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location)) } + if let currentAddScheduledMessages = currentAddScheduledMessages, !currentAddScheduledMessages.messages.isEmpty { + result.append(.AddScheduledMessages(currentAddScheduledMessages.messages)) + } currentAddMessages = nil result.append(operation) case let .UpdateState(state): @@ -2046,12 +2050,22 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation]) } currentAddMessages = OptimizeAddMessagesState(messages: messages, location: location) } + case let .AddScheduledMessages(messages): + if let currentAddScheduledMessages = currentAddScheduledMessages { + currentAddScheduledMessages.messages.append(contentsOf: messages) + } else { + currentAddScheduledMessages = OptimizeAddMessagesState(messages: messages, location: .Random) + } } } if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty { result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location)) } + if let currentAddScheduledMessages = currentAddScheduledMessages, !currentAddScheduledMessages.messages.isEmpty { + result.append(.AddScheduledMessages(currentAddScheduledMessages.messages)) + } + if let updatedState = updatedState { result.append(.UpdateState(updatedState)) } @@ -2238,6 +2252,16 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP } } } + case let .AddScheduledMessages(messages): + for message in messages { + if case let .Id(id) = message.id, let _ = transaction.getMessage(id) { + transaction.updateMessage(id) { _ -> PostboxUpdateMessage in + return .update(message) + } + } else { + let _ = transaction.addMessages(messages, location: .Random) + } + } case let .DeleteMessagesWithGlobalIds(ids): transaction.deleteMessagesWithGlobalIds(ids) case let .DeleteMessages(ids): diff --git a/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift b/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift index 19c61472be..c5d4863036 100644 --- a/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift +++ b/submodules/TelegramCore/TelegramCore/AccountViewTracker.swift @@ -76,12 +76,17 @@ private func fetchWebpage(account: Account, messageId: MessageId) -> Signal take(1) |> mapToSignal { peer in if let inputPeer = apiInputPeer(peer) { + let isScheduledMessage = Namespaces.Message.allScheduled.contains(messageId.namespace) let messages: Signal - switch inputPeer { - case let .inputPeerChannel(channelId, accessHash): - messages = account.network.request(Api.functions.channels.getMessages(channel: Api.InputChannel.inputChannel(channelId: channelId, accessHash: accessHash), id: [Api.InputMessage.inputMessageID(id: messageId.id)])) - default: - messages = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(id: messageId.id)])) + if isScheduledMessage { + messages = account.network.request(Api.functions.messages.getScheduledMessages(peer: inputPeer, id: [messageId.id])) + } else { + switch inputPeer { + case let .inputPeerChannel(channelId, accessHash): + messages = account.network.request(Api.functions.channels.getMessages(channel: Api.InputChannel.inputChannel(channelId: channelId, accessHash: accessHash), id: [Api.InputMessage.inputMessageID(id: messageId.id)])) + default: + messages = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(id: messageId.id)])) + } } return messages |> retryRequest @@ -125,7 +130,7 @@ private func fetchWebpage(account: Account, messageId: MessageId) -> Signal? - if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup { - fetchSignal = account.network.request(Api.functions.messages.getMessages(id: messageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) }))) + if let messageId = messageIds.first, messageId.namespace == Namespaces.Message.ScheduledCloud { + if let inputPeer = apiInputPeer(peer) { + fetchSignal = account.network.request(Api.functions.messages.getScheduledMessages(peer: inputPeer, id: messageIds.map { $0.id })) + } + } else if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup { + fetchSignal = account.network.request(Api.functions.messages.getMessages(id: messageIds.map { Api.InputMessage.inputMessageID(id: $0.id) })) } else if peerId.namespace == Namespaces.Peer.CloudChannel { if let inputChannel = apiInputChannel(peer) { - fetchSignal = account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.map({ Api.InputMessage.inputMessageID(id: $0.id) }))) + fetchSignal = account.network.request(Api.functions.channels.getMessages(channel: inputChannel, id: messageIds.map { Api.InputMessage.inputMessageID(id: $0.id) })) } } guard let signal = fetchSignal else { diff --git a/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift b/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift index 52ac2620ee..d8f478ede5 100644 --- a/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift +++ b/submodules/TelegramCore/TelegramCore/ApplyUpdateMessage.swift @@ -40,7 +40,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes var apiMessage: Api.Message? for resultMessage in result.messages { - if let id = resultMessage.id(namespace: message.scheduleTime != nil ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud) { + if let id = resultMessage.id(namespace: Namespaces.Message.allScheduled.contains(message.id.namespace) ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud) { if id.peerId == message.id.peerId { apiMessage = resultMessage break @@ -85,7 +85,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes transaction.updateMessage(message.id, update: { currentMessage in let updatedId: MessageId if let messageId = messageId { - let namespace = message.scheduleTime != nil ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud + let namespace = Namespaces.Message.allScheduled.contains(message.id.namespace) ? Namespaces.Message.ScheduledCloud : Namespaces.Message.Cloud updatedId = MessageId(peerId: currentMessage.id.peerId, namespace: namespace, id: messageId) } else { updatedId = currentMessage.id @@ -213,9 +213,14 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage return postbox.transaction { transaction -> Void in let updatedRawMessageIds = result.updatedRawMessageIds + var namespace = Namespaces.Message.Cloud + if let message = messages.first, Namespaces.Message.allScheduled.contains(message.id.namespace) { + namespace = Namespaces.Message.ScheduledCloud + } + var resultMessages: [MessageId: StoreMessage] = [:] for apiMessage in result.messages { - if let resultMessage = StoreMessage(apiMessage: apiMessage), case let .Id(id) = resultMessage.id { + if let resultMessage = StoreMessage(apiMessage: apiMessage, namespace: namespace), case let .Id(id) = resultMessage.id { resultMessages[id] = resultMessage } } @@ -232,7 +237,7 @@ func applyUpdateGroupMessages(postbox: Postbox, stateManager: AccountStateManage } if let uniqueId = uniqueId { if let updatedId = updatedRawMessageIds[uniqueId] { - if let storeMessage = resultMessages[MessageId(peerId: message.id.peerId, namespace: Namespaces.Message.Cloud, id: updatedId)], case let .Id(id) = storeMessage.id { + if let storeMessage = resultMessages[MessageId(peerId: message.id.peerId, namespace: namespace, id: updatedId)], case let .Id(id) = storeMessage.id { mapping.append((message, MessageIndex(id: id, timestamp: storeMessage.timestamp), storeMessage)) } } else { diff --git a/submodules/TelegramCore/TelegramCore/CloudChatRemoveMessagesOperation.swift b/submodules/TelegramCore/TelegramCore/CloudChatRemoveMessagesOperation.swift index c04b940624..5c684d6ac7 100644 --- a/submodules/TelegramCore/TelegramCore/CloudChatRemoveMessagesOperation.swift +++ b/submodules/TelegramCore/TelegramCore/CloudChatRemoveMessagesOperation.swift @@ -83,12 +83,31 @@ final class CloudChatRemoveChatOperation: PostboxCoding { } } +enum CloudChatClearHistoryType: Int32 { + case forLocalPeer + case forEveryone + case scheduledMessages +} + +extension CloudChatClearHistoryType { + init(_ type: InteractiveHistoryClearingType) { + switch type { + case .forLocalPeer: + self = .forLocalPeer + case .forEveryone: + self = .forEveryone + case .scheduledMessages: + self = .scheduledMessages + } + } +} + final class CloudChatClearHistoryOperation: PostboxCoding { let peerId: PeerId let topMessageId: MessageId - let type: InteractiveMessagesDeletionType + let type: CloudChatClearHistoryType - init(peerId: PeerId, topMessageId: MessageId, type: InteractiveMessagesDeletionType) { + init(peerId: PeerId, topMessageId: MessageId, type: CloudChatClearHistoryType) { self.peerId = peerId self.topMessageId = topMessageId self.type = type @@ -97,7 +116,7 @@ final class CloudChatClearHistoryOperation: PostboxCoding { init(decoder: PostboxDecoder) { self.peerId = PeerId(decoder.decodeInt64ForKey("p", orElse: 0)) self.topMessageId = MessageId(peerId: PeerId(decoder.decodeInt64ForKey("m.p", orElse: 0)), namespace: decoder.decodeInt32ForKey("m.n", orElse: 0), id: decoder.decodeInt32ForKey("m.i", orElse: 0)) - self.type = InteractiveMessagesDeletionType(rawValue: decoder.decodeInt32ForKey("type", orElse: 0)) ?? .forLocalPeer + self.type = CloudChatClearHistoryType(rawValue: decoder.decodeInt32ForKey("type", orElse: 0)) ?? .forLocalPeer } func encode(_ encoder: PostboxEncoder) { @@ -117,14 +136,23 @@ func cloudChatAddRemoveChatOperation(transaction: Transaction, peerId: PeerId, r transaction.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: CloudChatRemoveChatOperation(peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible, topMessageId: transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud))) } -func cloudChatAddClearHistoryOperation(transaction: Transaction, peerId: PeerId, explicitTopMessageId: MessageId?, type: InteractiveMessagesDeletionType) { - let topMessageId: MessageId? - if let explicitTopMessageId = explicitTopMessageId { - topMessageId = explicitTopMessageId +func cloudChatAddClearHistoryOperation(transaction: Transaction, peerId: PeerId, explicitTopMessageId: MessageId?, type: CloudChatClearHistoryType) { + if type == .scheduledMessages { + var messageIds: [MessageId] = [] + transaction.withAllMessages(peerId: peerId, namespace: Namespaces.Message.ScheduledCloud) { message -> Bool in + messageIds.append(message.id) + return true + } + cloudChatAddRemoveMessagesOperation(transaction: transaction, peerId: peerId, messageIds: messageIds, type: .forLocalPeer) } else { - topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud) - } - if let topMessageId = topMessageId { - transaction.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: CloudChatClearHistoryOperation(peerId: peerId, topMessageId: topMessageId, type: type)) + let topMessageId: MessageId? + if let explicitTopMessageId = explicitTopMessageId { + topMessageId = explicitTopMessageId + } else { + topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud) + } + if let topMessageId = topMessageId { + transaction.operationLogAddEntry(peerId: peerId, tag: OperationLogTags.CloudChatRemoveMessages, tagLocalIndex: .automatic, tagMergedIndex: .automatic, contents: CloudChatClearHistoryOperation(peerId: peerId, topMessageId: topMessageId, type: type)) + } } } diff --git a/submodules/TelegramCore/TelegramCore/DeleteMessagesInteractively.swift b/submodules/TelegramCore/TelegramCore/DeleteMessagesInteractively.swift index 4341dab5aa..6ddc2999b4 100644 --- a/submodules/TelegramCore/TelegramCore/DeleteMessagesInteractively.swift +++ b/submodules/TelegramCore/TelegramCore/DeleteMessagesInteractively.swift @@ -80,24 +80,33 @@ public func deleteMessagesInteractively(postbox: Postbox, messageIds initialMess } } -public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: InteractiveMessagesDeletionType) -> Signal { +public enum InteractiveHistoryClearingType: Int32 { + case forLocalPeer = 0 + case forEveryone = 1 + case scheduledMessages = 2 +} + +public func clearHistoryInteractively(postbox: Postbox, peerId: PeerId, type: InteractiveHistoryClearingType) -> Signal { return postbox.transaction { transaction -> Void in if peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudChannel { - cloudChatAddClearHistoryOperation(transaction: transaction, peerId: peerId, explicitTopMessageId: nil, type: type) - var topIndex: MessageIndex? - if let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud), let topMessage = transaction.getMessage(topMessageId) { - topIndex = topMessage.index - } - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId) - if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference { - cloudChatAddClearHistoryOperation(transaction: transaction, peerId: migrationReference.maxMessageId.peerId, explicitTopMessageId: MessageId(peerId: migrationReference.maxMessageId.peerId, namespace: migrationReference.maxMessageId.namespace, id: migrationReference.maxMessageId.id + 1), type: type) - clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId) - } - if let topIndex = topIndex { - if peerId.namespace == Namespaces.Peer.CloudUser { - let _ = transaction.addMessages([StoreMessage(id: topIndex.id, globallyUniqueId: nil, groupingKey: nil, timestamp: topIndex.timestamp, flags: StoreMessageFlags(), tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributes: [], media: [TelegramMediaAction(action: .historyCleared)])], location: .Random) - } else { - updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: peerId, minTimestamp: topIndex.timestamp, forceRootGroupIfNotExists: false) + cloudChatAddClearHistoryOperation(transaction: transaction, peerId: peerId, explicitTopMessageId: nil, type: CloudChatClearHistoryType(type)) + if type != .scheduledMessages { + var topIndex: MessageIndex? + if let topMessageId = transaction.getTopPeerMessageId(peerId: peerId, namespace: Namespaces.Message.Cloud), let topMessage = transaction.getMessage(topMessageId) { + topIndex = topMessage.index + } + + clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: peerId) + if let cachedData = transaction.getPeerCachedData(peerId: peerId) as? CachedChannelData, let migrationReference = cachedData.migrationReference { + cloudChatAddClearHistoryOperation(transaction: transaction, peerId: migrationReference.maxMessageId.peerId, explicitTopMessageId: MessageId(peerId: migrationReference.maxMessageId.peerId, namespace: migrationReference.maxMessageId.namespace, id: migrationReference.maxMessageId.id + 1), type: CloudChatClearHistoryType(type)) + clearHistory(transaction: transaction, mediaBox: postbox.mediaBox, peerId: migrationReference.maxMessageId.peerId) + } + if let topIndex = topIndex { + if peerId.namespace == Namespaces.Peer.CloudUser { + let _ = transaction.addMessages([StoreMessage(id: topIndex.id, globallyUniqueId: nil, groupingKey: nil, timestamp: topIndex.timestamp, flags: StoreMessageFlags(), tags: [], globalTags: [], localTags: [], forwardInfo: nil, authorId: nil, text: "", attributes: [], media: [TelegramMediaAction(action: .historyCleared)])], location: .Random) + } else { + updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: peerId, minTimestamp: topIndex.timestamp, forceRootGroupIfNotExists: false) + } } } } else if peerId.namespace == Namespaces.Peer.SecretChat { diff --git a/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift b/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift index 3b835c5dd0..bddb8cf8f4 100644 --- a/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift +++ b/submodules/TelegramCore/TelegramCore/EnqueueMessage.swift @@ -101,6 +101,8 @@ private func filterMessageAttributesForForwardedMessage(_ attributes: [MessageAt return true case _ as NotificationInfoMessageAttribute: return true + case _ as OutgoingScheduleInfoMessageAttribute: + return true default: return false } diff --git a/submodules/TelegramCore/TelegramCore/HistoryViewStateValidation.swift b/submodules/TelegramCore/TelegramCore/HistoryViewStateValidation.swift index b0aa0207a0..6911b76297 100644 --- a/submodules/TelegramCore/TelegramCore/HistoryViewStateValidation.swift +++ b/submodules/TelegramCore/TelegramCore/HistoryViewStateValidation.swift @@ -271,7 +271,7 @@ final class HistoryViewStateValidationContexts { let batch = HistoryStateValidationBatch(disposable: disposable) context.batch = batch - let messages: [Message] = view.entries.map { $0.message } + let messages: [Message] = view.entries.map { $0.message }.filter { $0.id.namespace == Namespaces.Message.ScheduledCloud } disposable.set((validateScheduledMessagesBatch(postbox: self.postbox, network: self.network, accountPeerId: peerId, tag: nil, messages: messages, historyState: .scheduledMessages(peerId)) |> deliverOn(self.queue)).start(completed: { [weak self] in @@ -476,7 +476,7 @@ private func validateBatch(postbox: Postbox, network: Network, transaction: Tran return .complete() } switch result { - case let .messages(messages, _, users, channelPts): + case let .messages(messages, _, _, channelPts): var storeMessages: [StoreMessage] = [] for message in messages { @@ -526,7 +526,7 @@ private func validateBatch(postbox: Postbox, network: Network, transaction: Tran } var ids = Set() for message in apiMessages { - if let parsedMessage = StoreMessage(apiMessage: message), case let .Id(id) = parsedMessage.id { + if let parsedMessage = StoreMessage(apiMessage: message, namespace: messageNamespace), case let .Id(id) = parsedMessage.id { if let tag = tag { if parsedMessage.tags.contains(tag) { ids.insert(id) diff --git a/submodules/TelegramCore/TelegramCore/LoadMessagesIfNecessary.swift b/submodules/TelegramCore/TelegramCore/LoadMessagesIfNecessary.swift index 1d545a67e8..fc18a97ab1 100644 --- a/submodules/TelegramCore/TelegramCore/LoadMessagesIfNecessary.swift +++ b/submodules/TelegramCore/TelegramCore/LoadMessagesIfNecessary.swift @@ -22,7 +22,6 @@ public enum GetMessagesStrategy { public func getMessagesLoadIfNecessary(_ messageIds: [MessageId], postbox: Postbox, network: Network, accountPeerId: PeerId, strategy: GetMessagesStrategy = .cloud) -> Signal <[Message], NoError> { let postboxSignal = postbox.transaction { transaction -> ([Message], Set, SimpleDictionary) in - var ids = messageIds if let cachedData = transaction.getPeerCachedData(peerId: messageIds[0].peerId) as? CachedChannelData { diff --git a/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift b/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift index 3644676d6f..65e252cfb9 100644 --- a/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift +++ b/submodules/TelegramCore/TelegramCore/ManagedCloudChatRemoveMessagesOperations.swift @@ -136,7 +136,41 @@ func managedCloudChatRemoveMessagesOperations(postbox: Postbox, network: Network } private func removeMessages(postbox: Postbox, network: Network, stateManager: AccountStateManager, peer: Peer, operation: CloudChatRemoveMessagesOperation) -> Signal { - if peer.id.namespace == Namespaces.Peer.CloudChannel { + var isScheduled = false + for id in operation.messageIds { + if id.namespace == Namespaces.Message.ScheduledCloud { + isScheduled = true + break + } + } + + if isScheduled { + if let inputPeer = apiInputPeer(peer) { + var signal: Signal = .complete() + for s in stride(from: 0, to: operation.messageIds.count, by: 100) { + let ids = Array(operation.messageIds[s ..< min(s + 100, operation.messageIds.count)]) + let partSignal = network.request(Api.functions.messages.deleteScheduledMessages(peer: inputPeer, id: ids.map { $0.id })) + |> map { result -> Api.Updates? in + return result + } + |> `catch` { _ in + return .single(nil) + } + |> mapToSignal { updates -> Signal in + if let updates = updates { + stateManager.addUpdates(updates) + } + return .complete() + } + + signal = signal + |> then(partSignal) + } + return signal + } else { + return .complete() + } + } else if peer.id.namespace == Namespaces.Peer.CloudChannel { if let inputChannel = apiInputChannel(peer) { var signal: Signal = .complete() for s in stride(from: 0, to: operation.messageIds.count, by: 100) { @@ -165,73 +199,38 @@ private func removeMessages(postbox: Postbox, network: Network, stateManager: Ac return .complete() } } else { - var isScheduled = false - for id in operation.messageIds { - if id.namespace == Namespaces.Message.ScheduledCloud { - isScheduled = true - break - } + var flags: Int32 + switch operation.type { + case .forEveryone: + flags = (1 << 0) + default: + flags = 0 } - if isScheduled { - if let inputPeer = apiInputPeer(peer) { - var signal: Signal = .complete() - for s in stride(from: 0, to: operation.messageIds.count, by: 100) { - let ids = Array(operation.messageIds[s ..< min(s + 100, operation.messageIds.count)]) - let partSignal = network.request(Api.functions.messages.deleteScheduledMessages(peer: inputPeer, id: ids.map { $0.id })) - |> map { result -> Api.Updates? in - return result - } - |> `catch` { _ in - return .single(nil) - } - |> mapToSignal { updates -> Signal in - if let updates = updates { - stateManager.addUpdates(updates) - } - return .complete() - } - - signal = signal - |> then(partSignal) + + var signal: Signal = .complete() + for s in stride(from: 0, to: operation.messageIds.count, by: 100) { + let ids = Array(operation.messageIds[s ..< min(s + 100, operation.messageIds.count)]) + let partSignal = network.request(Api.functions.messages.deleteMessages(flags: flags, id: ids.map { $0.id })) + |> map { result -> Api.messages.AffectedMessages? in + return result } - return signal - } else { - return .complete() - } - } else { - var flags: Int32 - switch operation.type { - case .forEveryone: - flags = (1 << 0) - default: - flags = 0 + |> `catch` { _ in + return .single(nil) + } + |> mapToSignal { result -> Signal in + if let result = result { + switch result { + case let .affectedMessages(pts, ptsCount): + stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)]) + } + } + return .complete() } - var signal: Signal = .complete() - for s in stride(from: 0, to: operation.messageIds.count, by: 100) { - let ids = Array(operation.messageIds[s ..< min(s + 100, operation.messageIds.count)]) - let partSignal = network.request(Api.functions.messages.deleteMessages(flags: flags, id: ids.map { $0.id })) - |> map { result -> Api.messages.AffectedMessages? in - return result - } - |> `catch` { _ in - return .single(nil) - } - |> mapToSignal { result -> Signal in - if let result = result { - switch result { - case let .affectedMessages(pts, ptsCount): - stateManager.addUpdateGroups([.updatePts(pts: pts, ptsCount: ptsCount)]) - } - } - return .complete() - } - - signal = signal - |> then(partSignal) - } - return signal + signal = signal + |> then(partSignal) } + return signal } } @@ -339,7 +338,7 @@ private func removeChat(transaction: Transaction, postbox: Postbox, network: Net } } -private func requestClearHistory(postbox: Postbox, network: Network, stateManager: AccountStateManager, inputPeer: Api.InputPeer, maxId: Int32, justClear: Bool, type: InteractiveMessagesDeletionType) -> Signal { +private func requestClearHistory(postbox: Postbox, network: Network, stateManager: AccountStateManager, inputPeer: Api.InputPeer, maxId: Int32, justClear: Bool, type: CloudChatClearHistoryType) -> Signal { var flags: Int32 = 0 if justClear { flags |= 1 << 0 diff --git a/submodules/TelegramCore/TelegramCore/MessageUtils.swift b/submodules/TelegramCore/TelegramCore/MessageUtils.swift index 99a08d8d10..153d35fcf6 100644 --- a/submodules/TelegramCore/TelegramCore/MessageUtils.swift +++ b/submodules/TelegramCore/TelegramCore/MessageUtils.swift @@ -189,4 +189,14 @@ public extension Message { return false } } + + func effectivelyFailed(timestamp: Int32) -> Bool { + if self.flags.contains(.Failed) { + return true + } else if self.id.namespace == Namespaces.Message.ScheduledCloud { + return timestamp > self.timestamp + } else { + return false + } + } } diff --git a/submodules/TelegramCore/TelegramCore/Network.swift b/submodules/TelegramCore/TelegramCore/Network.swift index d1c700db26..3d5b1ee268 100644 --- a/submodules/TelegramCore/TelegramCore/Network.swift +++ b/submodules/TelegramCore/TelegramCore/Network.swift @@ -780,7 +780,7 @@ public final class Network: NSObject, MTRequestMessageServiceDelegate { } public var globalTime: TimeInterval { - return context.globalTime() + return self.context.globalTime() } public var currentGlobalTime: Signal { diff --git a/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift b/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift index 643fd4a5fe..f97e33be98 100644 --- a/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift +++ b/submodules/TelegramCore/TelegramCore/PendingMessageManager.swift @@ -667,7 +667,7 @@ public final class PendingMessageManager { } else if let inputSourcePeerId = forwardPeerIds.first, let inputSourcePeer = transaction.getPeer(inputSourcePeerId).flatMap(apiInputPeer) { let dependencyTag = PendingMessageRequestDependencyTag(messageId: messages[0].0.id) - sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, scheduleDate: nil), tag: dependencyTag) + sendMessageRequest = network.request(Api.functions.messages.forwardMessages(flags: flags, fromPeer: inputSourcePeer, id: forwardIds.map { $0.0.id }, randomId: forwardIds.map { $0.1 }, toPeer: inputPeer, scheduleDate: scheduleTime), tag: dependencyTag) } else { assertionFailure() sendMessageRequest = .fail(MTRpcError(errorCode: 400, errorDescription: "Invalid forward source")) diff --git a/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift b/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift index beec16bf19..5061a35ea5 100644 --- a/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift +++ b/submodules/TelegramCore/TelegramCore/RequestEditMessage.swift @@ -161,46 +161,46 @@ private func requestEditMessageInternal(account: Account, messageId: MessageId, } return account.network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: text, media: inputMedia, replyMarkup: nil, entities: apiEntities, scheduleDate: effectiveScheduleTime)) - |> map { result -> Api.Updates? in - return result + |> map { result -> Api.Updates? in + return result + } + |> `catch` { error -> Signal in + if error.errorDescription == "MESSAGE_NOT_MODIFIED" { + return .single(nil) + } else { + return .fail(error) } - |> `catch` { error -> Signal in - if error.errorDescription == "MESSAGE_NOT_MODIFIED" { - return .single(nil) - } else { - return .fail(error) - } + } + |> mapError { error -> RequestEditMessageInternalError in + if error.errorDescription.hasPrefix("FILEREF_INVALID") || error.errorDescription.hasPrefix("FILE_REFERENCE_") { + return .invalidReference + } else if error.errorDescription.hasPrefix("CHAT_SEND_") && error.errorDescription.hasSuffix("_FORBIDDEN") { + return .error(.restricted) } - |> mapError { error -> RequestEditMessageInternalError in - if error.errorDescription.hasPrefix("FILEREF_INVALID") || error.errorDescription.hasPrefix("FILE_REFERENCE_") { - return .invalidReference - } else if error.errorDescription.hasPrefix("CHAT_SEND_") && error.errorDescription.hasSuffix("_FORBIDDEN") { - return .error(.restricted) - } - return .error(.generic) - } - |> mapToSignal { result -> Signal in - if let result = result { - return account.postbox.transaction { transaction -> RequestEditMessageResult in - var toMedia: Media? - if let message = result.messages.first.flatMap({ StoreMessage(apiMessage: $0) }) { - toMedia = message.media.first - } - - if case let .update(fromMedia) = media, let toMedia = toMedia { - applyMediaResourceChanges(from: fromMedia.media, to: toMedia, postbox: account.postbox) - } - account.stateManager.addUpdates(result) - - return .done(true) + return .error(.generic) + } + |> mapToSignal { result -> Signal in + if let result = result { + return account.postbox.transaction { transaction -> RequestEditMessageResult in + var toMedia: Media? + if let message = result.messages.first.flatMap({ StoreMessage(apiMessage: $0) }) { + toMedia = message.media.first } - |> mapError { _ -> RequestEditMessageInternalError in - return .error(.generic) + + if case let .update(fromMedia) = media, let toMedia = toMedia { + applyMediaResourceChanges(from: fromMedia.media, to: toMedia, postbox: account.postbox) } - } else { - return .single(.done(false)) + account.stateManager.addUpdates(result) + + return .done(true) } + |> mapError { _ -> RequestEditMessageInternalError in + return .error(.generic) + } + } else { + return .single(.done(false)) } + } } else { return .single(.done(false)) } diff --git a/submodules/TelegramCore/TelegramCore/SingleMessageView.swift b/submodules/TelegramCore/TelegramCore/SingleMessageView.swift index c265c00adf..24a395509c 100644 --- a/submodules/TelegramCore/TelegramCore/SingleMessageView.swift +++ b/submodules/TelegramCore/TelegramCore/SingleMessageView.swift @@ -41,7 +41,11 @@ public func singleMessageView(account: Account, messageId: MessageId, loadIfNotE private func fetchMessage(transaction: Transaction, account: Account, messageId: MessageId) -> Signal { if let peer = transaction.getPeer(messageId.peerId) { var signal: Signal? - if messageId.peerId.namespace == Namespaces.Peer.CloudUser || messageId.peerId.namespace == Namespaces.Peer.CloudGroup { + if messageId.namespace == Namespaces.Message.ScheduledCloud { + if let inputPeer = apiInputPeer(peer) { + signal = account.network.request(Api.functions.messages.getScheduledMessages(peer: inputPeer, id: [messageId.id])) + } + } else if messageId.peerId.namespace == Namespaces.Peer.CloudUser || messageId.peerId.namespace == Namespaces.Peer.CloudGroup { signal = account.network.request(Api.functions.messages.getMessages(id: [Api.InputMessage.inputMessageID(id: messageId.id)])) } else if messageId.peerId.namespace == Namespaces.Peer.CloudChannel { if let inputChannel = apiInputChannel(peer) { @@ -96,7 +100,7 @@ private func fetchMessage(transaction: Transaction, account: Account, messageId: }) for message in apiMessages { - if let message = StoreMessage(apiMessage: message) { + if let message = StoreMessage(apiMessage: message, namespace: messageId.namespace) { let _ = transaction.addMessages([message], location: .Random) } }