diff --git a/TelegramCore.xcodeproj/project.pbxproj b/TelegramCore.xcodeproj/project.pbxproj index d3438afdf2..35547ac657 100644 --- a/TelegramCore.xcodeproj/project.pbxproj +++ b/TelegramCore.xcodeproj/project.pbxproj @@ -665,6 +665,8 @@ D0C50E351E93A86600F62E39 /* CallSessionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C50E331E93A86600F62E39 /* CallSessionManager.swift */; }; D0CA3F84207391560042D2B6 /* SecureIdPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0CA3F83207391560042D2B6 /* SecureIdPadding.swift */; }; D0CA3F85207391560042D2B6 /* SecureIdPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0CA3F83207391560042D2B6 /* SecureIdPadding.swift */; }; + D0CA8E4B227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0CA8E4A227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift */; }; + D0CA8E4C227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0CA8E4A227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift */; }; D0CAF2EA1D75EC600011F558 /* MtProtoKitDynamic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */; }; D0D1026C2212FE52003ADA5E /* AccountSortOrderAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D1026B2212FE52003ADA5E /* AccountSortOrderAttribute.swift */; }; D0D1026D2212FE52003ADA5E /* AccountSortOrderAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0D1026B2212FE52003ADA5E /* AccountSortOrderAttribute.swift */; }; @@ -1176,6 +1178,7 @@ D0C48F3B1E8142EF0075317D /* LoadedPeerFromMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadedPeerFromMessage.swift; sourceTree = ""; }; D0C50E331E93A86600F62E39 /* CallSessionManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CallSessionManager.swift; sourceTree = ""; }; D0CA3F83207391560042D2B6 /* SecureIdPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureIdPadding.swift; sourceTree = ""; }; + D0CA8E4A227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManagedSynchronizeGroupMessageStats.swift; sourceTree = ""; }; D0CAF2E91D75EC600011F558 /* MtProtoKitDynamic.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MtProtoKitDynamic.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D0D1026B2212FE52003ADA5E /* AccountSortOrderAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountSortOrderAttribute.swift; sourceTree = ""; }; D0D748011E7AE98B00F4B1F6 /* StickerPackInteractiveOperations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StickerPackInteractiveOperations.swift; sourceTree = ""; }; @@ -1574,6 +1577,7 @@ 09EDAD3922131D010012A50B /* ManagedAutodownloadSettingsUpdates.swift */, 093857A72243D87900EB6A54 /* SynchronizeEmojiKeywordsOperation.swift */, 093857A62243D87800EB6A54 /* ManagedSynchronizeEmojiKeywordsOperations.swift */, + D0CA8E4A227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift */, ); name = State; sourceTree = ""; @@ -2208,6 +2212,7 @@ D03229F41E6B39700000AF9C /* ImportAccount.swift in Sources */, D021E0DF1DB539FC00C6B04F /* StickerPack.swift in Sources */, D03B0D091D62255C00955575 /* EnqueueMessage.swift in Sources */, + D0CA8E4B227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift in Sources */, D0DFD5DF1FCDBCFD0039B3B1 /* CachedSentMediaReferences.swift in Sources */, D093D7EE206413F600BC3599 /* SecureIdDataTypes.swift in Sources */, D00D343C1E6EC9770057B307 /* TelegramMediaGame.swift in Sources */, @@ -2944,6 +2949,7 @@ D02ABC7F1E3109F000CAE539 /* CloudChatRemoveMessagesOperation.swift in Sources */, D0528E611E65B94E00E2FEF5 /* SingleMessageView.swift in Sources */, D0FC195C2020D1CA00FEDBB2 /* PeerGroupMessageStateVersionAttribute.swift in Sources */, + D0CA8E4C227209C4008A74C3 /* ManagedSynchronizeGroupMessageStats.swift in Sources */, D08CAA851ED8164B0000FDA8 /* Localization.swift in Sources */, D0528E5B1E658B3600E2FEF5 /* ManagedLocalInputActivities.swift in Sources */, D0FA8BA51E1FA341001E855B /* SecretChatKeychain.swift in Sources */, diff --git a/TelegramCore/Account.swift b/TelegramCore/Account.swift index f75d9fd2ad..e10c6c4dc1 100644 --- a/TelegramCore/Account.swift +++ b/TelegramCore/Account.swift @@ -264,7 +264,7 @@ let telegramPostboxSeedConfiguration: SeedConfiguration = { } else { return [.regularChatsAndPrivateGroups] } - }, additionalChatListIndexNamespace: Namespaces.Message.Cloud) + }, additionalChatListIndexNamespace: Namespaces.Message.Cloud, messageNamespacesRequiringGroupStatsValidation: [Namespaces.Message.Cloud]) }() public func accountPreferenceEntries(rootPath: String, id: AccountRecordId, keys: Set, encryptionParameters: ValueBoxEncryptionParameters) -> Signal<(String, [ValueBoxKey: PreferencesEntry]), NoError> { @@ -985,6 +985,7 @@ public class Account { self.accountPresenceManager = AccountPresenceManager(shouldKeepOnlinePresence: self.shouldKeepOnlinePresence.get(), network: network) let _ = (postbox.transaction { transaction -> Void in transaction.updatePeerPresencesInternal(presences: [peerId: TelegramUserPresence(status: .present(until: Int32.max - 1), lastActivity: 0)], merge: { _, updated in return updated }) + transaction.setNeedsPeerGroupMessageStatsSynchronization(groupId: Namespaces.PeerGroup.archive, namespace: Namespaces.Message.Cloud) }).start() self.notificationAutolockReportManager = NotificationAutolockReportManager(deadline: self.autolockReportDeadline.get(), network: network) self.autolockReportDeadline.set( diff --git a/TelegramCore/AccountIntermediateState.swift b/TelegramCore/AccountIntermediateState.swift index 77d9e23a28..25e9e87782 100644 --- a/TelegramCore/AccountIntermediateState.swift +++ b/TelegramCore/AccountIntermediateState.swift @@ -9,22 +9,26 @@ import Foundation import MtProtoKitDynamic #endif +struct PeerChatInfo { + var notificationSettings: PeerNotificationSettings +} + final class AccountInitialState { let state: AuthorizedAccountState.State let peerIds: Set let chatStates: [PeerId: PeerChatState] - let peerNotificationSettings: [PeerId: PeerNotificationSettings] - let peerIdsWithNewMessages: Set + let peerChatInfos: [PeerId: PeerChatInfo] + let peerIdsRequiringLocalChatState: Set let locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]] let cloudReadStates: [PeerId: PeerReadState] let channelsToPollExplicitely: Set - init(state: AuthorizedAccountState.State, peerIds: Set, peerIdsWithNewMessages: Set, chatStates: [PeerId: PeerChatState], peerNotificationSettings: [PeerId: PeerNotificationSettings], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]], cloudReadStates: [PeerId: PeerReadState], channelsToPollExplicitely: Set) { + init(state: AuthorizedAccountState.State, peerIds: Set, peerIdsRequiringLocalChatState: Set, chatStates: [PeerId: PeerChatState], peerChatInfos: [PeerId: PeerChatInfo], locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]], cloudReadStates: [PeerId: PeerReadState], channelsToPollExplicitely: Set) { self.state = state self.peerIds = peerIds self.chatStates = chatStates - self.peerIdsWithNewMessages = peerIdsWithNewMessages - self.peerNotificationSettings = peerNotificationSettings + self.peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatState + self.peerChatInfos = peerChatInfos self.locallyGeneratedMessageTimestamps = locallyGeneratedMessageTimestamps self.cloudReadStates = cloudReadStates self.channelsToPollExplicitely = channelsToPollExplicitely @@ -81,7 +85,7 @@ enum AccountStateMutationOperation { case AddSecretMessages([Api.EncryptedMessage]) case ReadSecretOutbox(peerId: PeerId, maxTimestamp: Int32, actionTimestamp: Int32) case AddPeerInputActivity(chatPeerId: PeerId, peerId: PeerId?, activity: PeerInputActivity?) - case UpdatePinnedItemIds(PeerGroupId?, AccountStateUpdatePinnedItemIdsOperation) + case UpdatePinnedItemIds(PeerGroupId, AccountStateUpdatePinnedItemIdsOperation) case ReadMessageContents((PeerId?, [Int32])) case UpdateMessageImpressionCount(MessageId, Int32) case UpdateInstalledStickerPacks(AccountStateUpdateStickerPacksOperation) @@ -90,8 +94,7 @@ enum AccountStateMutationOperation { case UpdateCall(Api.PhoneCall) case UpdateLangPack(String, Api.LangPackDifference?) case UpdateMinAvailableMessage(MessageId) - case UpdatePeerInclusionMinTimestamp(PeerId, Int32) - case UpdatePeerGroup(PeerId, PeerGroupId?) + case UpdatePeerChatInclusion(PeerId, PeerGroupId) } struct AccountMutableState { @@ -103,7 +106,7 @@ struct AccountMutableState { var state: AuthorizedAccountState.State var peers: [PeerId: Peer] var chatStates: [PeerId: PeerChatState] - var peerNotificationSettings: [PeerId: PeerNotificationSettings] + var peerChatInfos: [PeerId: PeerChatInfo] var referencedMessageIds: Set var storedMessages: Set var readInboxMaxIds: [PeerId: MessageId] @@ -127,13 +130,13 @@ struct AccountMutableState { self.storedMessages = initialStoredMessages self.readInboxMaxIds = initialReadInboxMaxIds self.chatStates = initialState.chatStates - self.peerNotificationSettings = initialState.peerNotificationSettings + self.peerChatInfos = initialState.peerChatInfos self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp self.branchOperationIndex = 0 self.namespacesWithHolesFromPreviousState = [:] } - init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], chatStates: [PeerId: PeerChatState], peerNotificationSettings: [PeerId: PeerNotificationSettings], referencedMessageIds: Set, storedMessages: Set, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set], namespacesWithHolesFromPreviousState: [PeerId: Set], displayAlerts: [(text: String, isDropAuth: Bool)], branchOperationIndex: Int) { + init(initialState: AccountInitialState, operations: [AccountStateMutationOperation], state: AuthorizedAccountState.State, peers: [PeerId: Peer], chatStates: [PeerId: PeerChatState], peerChatInfos: [PeerId: PeerChatInfo], referencedMessageIds: Set, storedMessages: Set, readInboxMaxIds: [PeerId: MessageId], storedMessagesByPeerIdAndTimestamp: [PeerId: Set], namespacesWithHolesFromPreviousState: [PeerId: Set], displayAlerts: [(text: String, isDropAuth: Bool)], branchOperationIndex: Int) { self.initialState = initialState self.operations = operations self.state = state @@ -141,7 +144,7 @@ struct AccountMutableState { self.chatStates = chatStates self.referencedMessageIds = referencedMessageIds self.storedMessages = storedMessages - self.peerNotificationSettings = peerNotificationSettings + self.peerChatInfos = peerChatInfos self.readInboxMaxIds = readInboxMaxIds self.storedMessagesByPeerIdAndTimestamp = storedMessagesByPeerIdAndTimestamp self.namespacesWithHolesFromPreviousState = namespacesWithHolesFromPreviousState @@ -150,7 +153,7 @@ struct AccountMutableState { } func branch() -> AccountMutableState { - return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, chatStates: self.chatStates, peerNotificationSettings: self.peerNotificationSettings, referencedMessageIds: self.referencedMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, displayAlerts: self.displayAlerts, branchOperationIndex: self.operations.count) + return AccountMutableState(initialState: self.initialState, operations: self.operations, state: self.state, peers: self.peers, chatStates: self.chatStates, peerChatInfos: self.peerChatInfos, referencedMessageIds: self.referencedMessageIds, storedMessages: self.storedMessages, readInboxMaxIds: self.readInboxMaxIds, storedMessagesByPeerIdAndTimestamp: self.storedMessagesByPeerIdAndTimestamp, namespacesWithHolesFromPreviousState: self.namespacesWithHolesFromPreviousState, displayAlerts: self.displayAlerts, branchOperationIndex: self.operations.count) } mutating func merge(_ other: AccountMutableState) { @@ -279,12 +282,8 @@ struct AccountMutableState { self.addOperation(.UpdateMinAvailableMessage(id)) } - mutating func updatePeerInclusionMinTimestamp(peerId: PeerId, timestamp: Int32) { - self.addOperation(.UpdatePeerInclusionMinTimestamp(peerId, timestamp)) - } - - mutating func updatePeerGroup(peerId: PeerId, groupId: PeerGroupId?) { - self.addOperation(.UpdatePeerGroup(peerId, groupId)) + mutating func updatePeerChatInclusion(peerId: PeerId, groupId: PeerGroupId) { + self.addOperation(.UpdatePeerChatInclusion(peerId, groupId)) } mutating func mergeUsers(_ users: [Api.User]) { @@ -327,7 +326,7 @@ struct AccountMutableState { self.addOperation(.AddPeerInputActivity(chatPeerId: chatPeerId, peerId: peerId, activity: activity)) } - mutating func addUpdatePinnedItemIds(groupId: PeerGroupId?, operation: AccountStateUpdatePinnedItemIdsOperation) { + mutating func addUpdatePinnedItemIds(groupId: PeerGroupId, operation: AccountStateUpdatePinnedItemIdsOperation) { self.addOperation(.UpdatePinnedItemIds(groupId, operation)) } @@ -357,7 +356,7 @@ struct AccountMutableState { mutating func addOperation(_ operation: AccountStateMutationOperation) { switch operation { - case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerInclusionMinTimestamp, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerGroup: + case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion: break case let .AddMessages(messages, location): for message in messages { @@ -389,7 +388,10 @@ struct AccountMutableState { self.chatStates[peerId] = channelState case let .UpdateNotificationSettings(subject, notificationSettings): if case let .peer(peerId) = subject { - self.peerNotificationSettings[peerId] = notificationSettings + if var currentInfo = self.peerChatInfos[peerId] { + currentInfo.notificationSettings = notificationSettings + self.peerChatInfos[peerId] = currentInfo + } } case .UpdateGlobalNotificationSettings: break diff --git a/TelegramCore/AccountStateManagementUtils.swift b/TelegramCore/AccountStateManagementUtils.swift index 8a5e534782..42bc5de57e 100644 --- a/TelegramCore/AccountStateManagementUtils.swift +++ b/TelegramCore/AccountStateManagementUtils.swift @@ -72,22 +72,39 @@ private func associatedMessageIdsFromUpdateGroups(_ groups: [UpdateGroup]) -> Se return messageIds } -private func peersWithNewMessagesFromUpdateGroups(_ groups: [UpdateGroup]) -> Set { +private func peerIdsRequiringLocalChatStateFromUpdates(_ updates: [Api.Update]) -> Set { + var peerIds = Set() + for update in updates { + if let messageId = update.messageId { + peerIds.insert(messageId.peerId) + } + switch update { + case let .updateChannelTooLong(_, channelId, _): + let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + peerIds.insert(peerId) + case let .updateFolderPeers(folderPeers, _, _): + for peer in folderPeers { + switch peer { + case let .folderPeer(peer, _): + peerIds.insert(peer.peerId) + } + } + case let .updateReadChannelInbox(_, _, channelId, _, _, _): + peerIds.insert(PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)) + case let .updateReadHistoryInbox(_, _, peer, _, _, _, _): + peerIds.insert(peer.peerId) + default: + break + } + } + return peerIds +} + +private func peerIdsRequiringLocalChatStateFromUpdateGroups(_ groups: [UpdateGroup]) -> Set { var peerIds = Set() for group in groups { - for update in group.updates { - if let messageId = update.messageId { - peerIds.insert(messageId.peerId) - } - switch update { - case let .updateChannelTooLong(_, channelId, _): - let peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) - peerIds.insert(peerId) - default: - break - } - } + peerIds.formUnion(peerIdsRequiringLocalChatStateFromUpdates(group.updates)) } return peerIds @@ -239,7 +256,7 @@ private func associatedMessageIdsFromDifference(_ difference: Api.updates.Differ return messageIds } -private func peersWithNewMessagesFromDifference(_ difference: Api.updates.Difference) -> Set { +private func peerIdsRequiringLocalChatStateFromDifference(_ difference: Api.updates.Difference) -> Set { var peerIds = Set() switch difference { @@ -249,6 +266,7 @@ private func peersWithNewMessagesFromDifference(_ difference: Api.updates.Differ peerIds.insert(messageId.peerId) } } + peerIds.formUnion(peerIdsRequiringLocalChatStateFromUpdates(otherUpdates)) for update in otherUpdates { if let messageId = update.messageId { peerIds.insert(messageId.peerId) @@ -270,6 +288,7 @@ private func peersWithNewMessagesFromDifference(_ difference: Api.updates.Differ } } + peerIds.formUnion(peerIdsRequiringLocalChatStateFromUpdates(otherUpdates)) for update in otherUpdates { if let messageId = update.messageId { peerIds.insert(messageId.peerId) @@ -325,7 +344,7 @@ private func locallyGeneratedMessageTimestampsFromDifference(_ difference: Api.u return messageTimestamps } -private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set, activeChannelIds: Set, associatedMessageIds: Set, peerIdsWithNewMessages: Set, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState { +private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set, activeChannelIds: Set, associatedMessageIds: Set, peerIdsRequiringLocalChatState: Set, locallyGeneratedMessageTimestamps: [PeerId: [(MessageId.Namespace, Int32)]]) -> AccountMutableState { var peers: [PeerId: Peer] = [:] var chatStates: [PeerId: PeerChatState] = [:] @@ -371,13 +390,23 @@ private func initialStateWithPeerIds(_ transaction: Transaction, peerIds: Set Signal { @@ -403,9 +432,9 @@ func initialStateWithUpdateGroups(postbox: Postbox, groups: [UpdateGroup]) -> Si let peerIds = peerIdsFromUpdateGroups(groups) let activeChannelIds = activeChannelsFromUpdateGroups(groups) let associatedMessageIds = associatedMessageIdsFromUpdateGroups(groups) - let peerIdsWithNewMessages = peersWithNewMessagesFromUpdateGroups(groups) + let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromUpdateGroups(groups) - return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromUpdateGroups(groups)) + return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromUpdateGroups(groups)) } } @@ -414,8 +443,8 @@ func initialStateWithDifference(postbox: Postbox, difference: Api.updates.Differ let peerIds = peerIdsFromDifference(difference) let activeChannelIds = activeChannelsFromDifference(difference) let associatedMessageIds = associatedMessageIdsFromDifference(difference) - let peerIdsWithNewMessages = peersWithNewMessagesFromDifference(difference) - return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsWithNewMessages: peerIdsWithNewMessages, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromDifference(difference)) + let peerIdsRequiringLocalChatState = peerIdsRequiringLocalChatStateFromDifference(difference) + return initialStateWithPeerIds(transaction, peerIds: peerIds, activeChannelIds: activeChannelIds, associatedMessageIds: associatedMessageIds, peerIdsRequiringLocalChatState: peerIdsRequiringLocalChatState, locallyGeneratedMessageTimestamps: locallyGeneratedMessageTimestampsFromDifference(difference)) } } @@ -930,11 +959,11 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } else { updatedState.addDisplayAlert(text, isDropAuth: type.hasPrefix("AUTH_KEY_DROP_")) } - case let .updateReadChannelInbox(channelId, maxId): + case let .updateReadChannelInbox(_, folderId, channelId, maxId, stillUnreadCount, pts): updatedState.readInbox(MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: maxId)) case let .updateReadChannelOutbox(channelId, maxId): updatedState.readOutbox(MessageId(peerId: PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId), namespace: Namespaces.Message.Cloud, id: maxId), timestamp: nil) - case let .updateReadHistoryInbox(peer, maxId, _, _): + case let .updateReadHistoryInbox(_, folderId, peer, maxId, stillUnreadCount, _, _): updatedState.readInbox(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: maxId)) case let .updateReadHistoryOutbox(peer, maxId, _, _): updatedState.readOutbox(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: maxId), timestamp: updatesDate) @@ -1164,7 +1193,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo updatedState.addPeerInputActivity(chatPeerId: PeerId(namespace: Namespaces.Peer.SecretChat, id: chatId), peerId: nil, activity: .typingText) } case let .updateDialogPinned(flags, folderId, peer): - let groupId: PeerGroupId? = folderId.flatMap(PeerGroupId.init(rawValue:)) + let groupId: PeerGroupId = folderId.flatMap(PeerGroupId.init(rawValue:)) ?? .root let item: PinnedItemId switch peer { case let .dialogPeer(peer): @@ -1178,7 +1207,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo updatedState.addUpdatePinnedItemIds(groupId: groupId, operation: .unpin(item)) } case let .updatePinnedDialogs(_, folderId, order): - let groupId: PeerGroupId? = folderId.flatMap(PeerGroupId.init(rawValue:)) + let groupId: PeerGroupId = folderId.flatMap(PeerGroupId.init(rawValue:)) ?? .root if let order = order { updatedState.addUpdatePinnedItemIds(groupId: groupId, operation: .reorder(order.map { let item: PinnedItemId @@ -1243,7 +1272,7 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo for folderPeer in folderPeers { switch folderPeer { case let .folderPeer(peer, folderId): - updatedState.updatePeerGroup(peerId: peer.peerId, groupId: folderId == 0 ? nil : PeerGroupId(rawValue: folderId)) + updatedState.updatePeerChatInclusion(peerId: peer.peerId, groupId: PeerGroupId(rawValue: folderId)) } } default: @@ -1299,12 +1328,9 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo } return resolveAssociatedMessages(network: network, state: finalState) |> mapToSignal { resultingState -> Signal in - return resolveMissingPeerNotificationSettings(network: network, state: resultingState) - |> mapToSignal { resultingState -> Signal in - return resolveMissingPeerCloudReadStates(postbox: postbox, network: network, state: resultingState) - |> map { resultingState -> AccountFinalState in - return AccountFinalState(state: resultingState, shouldPoll: shouldPoll || hadError, incomplete: missingUpdates) - } + return resolveMissingPeerChatInfos(network: network, state: resultingState) + |> map { resultingState -> AccountFinalState in + return AccountFinalState(state: resultingState, shouldPoll: shouldPoll || hadError, incomplete: missingUpdates) } } } @@ -1376,15 +1402,15 @@ private func resolveAssociatedMessages(network: Network, state: AccountMutableSt } } -private func resolveMissingPeerNotificationSettings(network: Network, state: AccountMutableState) -> Signal { +private func resolveMissingPeerChatInfos(network: Network, state: AccountMutableState) -> Signal { var missingPeers: [PeerId: Api.InputPeer] = [:] - for peerId in state.initialState.peerIdsWithNewMessages { - if state.peerNotificationSettings[peerId] == nil { + for peerId in state.initialState.peerIdsRequiringLocalChatState { + if state.peerChatInfos[peerId] == nil { if let peer = state.peers[peerId], let inputPeer = apiInputPeer(peer) { missingPeers[peerId] = inputPeer } else { - Logger.shared.log("State", "can't fetch notification settings for peer \(peerId): can't create inputPeer") + Logger.shared.log("State", "can't fetch chat info for peer \(peerId): can't create inputPeer") } } } @@ -1392,66 +1418,71 @@ private func resolveMissingPeerNotificationSettings(network: Network, state: Acc if missingPeers.isEmpty { return .single(state) } else { - Logger.shared.log("State", "will fetch notification settings for \(missingPeers.count) peers") - var signals: [Signal<(PeerId, PeerNotificationSettings)?, NoError>] = [] - for (peerId, peer) in missingPeers { - let fetchSettings = network.request(Api.functions.account.getNotifySettings(peer: .inputNotifyPeer(peer: peer))) - |> map { settings -> (PeerId, PeerNotificationSettings)? in - return (peerId, TelegramPeerNotificationSettings(apiSettings: settings)) - } - |> `catch` { _ -> Signal<(PeerId, PeerNotificationSettings)?, NoError> in - return .single(nil) - } - signals.append(fetchSettings) - } - return combineLatest(signals) - |> map { peersAndSettings -> AccountMutableState in - var updatedState = state - for pair in peersAndSettings { - if let (peerId, settings) = pair { - updatedState.updateNotificationSettings(.peer(peerId), notificationSettings: settings) - } - } - return updatedState - } - } -} - -private func resolveMissingPeerCloudReadStates(postbox: Postbox, network: Network, state: AccountMutableState) -> Signal { - var missingPeers: [PeerId: Api.InputPeer] = [:] - - for peerId in state.initialState.peerIdsWithNewMessages { - if state.initialState.cloudReadStates[peerId] == nil && (peerId.namespace == Namespaces.Peer.CloudUser || peerId.namespace == Namespaces.Peer.CloudGroup) { - if let peer = state.peers[peerId], let inputPeer = apiInputPeer(peer) { - missingPeers[peerId] = inputPeer - } else { - Logger.shared.log("State", "can't fetch notification settings for peer \(peerId): can't create inputPeer") - } - } - } - - if missingPeers.isEmpty { - return .single(state) - } else { - Logger.shared.log("State", "will fetch cloud read states for \(missingPeers.count) peers") + Logger.shared.log("State", "will fetch chat info for \(missingPeers.count) peers") + let signal = network.request(Api.functions.messages.getPeerDialogs(peers: missingPeers.values.map(Api.InputDialogPeer.inputDialogPeer(peer:)))) + |> map(Optional.init) - var signals: [Signal<(PeerId, PeerReadState)?, NoError>] = [] - for (peerId, inputPeer) in missingPeers { - let fetchSettings = fetchPeerCloudReadState(network: network, postbox: postbox, peerId: peerId, inputPeer: inputPeer) - |> map { state -> (PeerId, PeerReadState)? in - return state.flatMap { (peerId, $0) } - } - signals.append(fetchSettings) + return signal + |> `catch` { _ -> Signal in + return .single(nil) } - return combineLatest(signals) - |> map { peersAndSettings -> AccountMutableState in + |> map { result -> AccountMutableState in + guard let result = result else { + return state + } + + var channelStates: [PeerId: ChannelState] = [:] + var updatedState = state - for pair in peersAndSettings { - if let (peerId, state) = pair { - if case let .idBased(maxIncomingReadId, maxOutgoingReadId, maxKnownId, count, markedUnread) = state { - updatedState.resetReadState(peerId, namespace: Namespaces.Message.Cloud, maxIncomingReadId: maxIncomingReadId, maxOutgoingReadId: maxOutgoingReadId, maxKnownId: maxKnownId, count: count, markedUnread: markedUnread) + switch result { + case let .peerDialogs(dialogs, messages, chats, users, state): + updatedState.mergeChats(chats) + updatedState.mergeUsers(users) + + var topMessageIds = Set() + + for dialog in dialogs { + switch dialog { + case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, notifySettings, pts, draft, folderId): + updatedState.setNeedsHoleFromPreviousState(peerId: peer.peerId, namespace: Namespaces.Message.Cloud) + + if topMessage != 0 { + topMessageIds.insert(MessageId(peerId: peer.peerId, namespace: Namespaces.Message.Cloud, id: topMessage)) + } + + updatedState.updatePeerChatInclusion(peerId: peer.peerId, groupId: PeerGroupId(rawValue: folderId ?? 0)) + updatedState.updateNotificationSettings(.peer(peer.peerId), notificationSettings: TelegramPeerNotificationSettings(apiSettings: notifySettings)) + updatedState.resetReadState(peer.peerId, namespace: Namespaces.Message.Cloud, maxIncomingReadId: readInboxMaxId, maxOutgoingReadId: readOutboxMaxId, maxKnownId: topMessage, count: unreadCount, markedUnread: nil) + updatedState.resetMessageTagSummary(peer.peerId, namespace: Namespaces.Message.Cloud, count: unreadMentionsCount, range: MessageHistoryTagNamespaceCountValidityRange(maxId: topMessage)) + if let pts = pts { + channelStates[peer.peerId] = ChannelState(pts: pts, invalidatedPts: pts) + } + case .dialogFolder: + assertionFailure() + break + } + } + + var storeMessages: [StoreMessage] = [] + for message in messages { + if let storeMessage = StoreMessage(apiMessage: message) { + var updatedStoreMessage = storeMessage + if case let .Id(id) = storeMessage.id { + if let channelState = channelStates[id.peerId] { + var updatedAttributes = storeMessage.attributes + updatedAttributes.append(ChannelMessageStateVersionAttribute(pts: channelState.pts)) + updatedStoreMessage = updatedStoreMessage.withUpdatedAttributes(updatedAttributes) + } + } + storeMessages.append(updatedStoreMessage) + } + } + + for message in storeMessages { + if case let .Id(id) = message.id { + updatedState.addMessages([message], location: topMessageIds.contains(id) ? .UpperHistoryBlock : .Random) + } } - } } return updatedState } @@ -1466,16 +1497,26 @@ func keepPollingChannel(postbox: Postbox, network: Network, peerId: PeerId, stat chatStates[peerId] = channelState } let initialPeers: [PeerId: Peer] = [peerId: peer] - var peerNotificationSettings: [PeerId: TelegramPeerNotificationSettings] = [:] - if let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings { - peerNotificationSettings[peerId] = notificationSettings + var peerChatInfos: [PeerId: PeerChatInfo] = [:] + let inclusion = transaction.getPeerChatListInclusion(peerId) + var hasValidInclusion = false + switch inclusion { + case .ifHasMessagesOrOneOf: + hasValidInclusion = true + case .notIncluded: + hasValidInclusion = false } - let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsWithNewMessages: Set(), chatStates: chatStates, peerNotificationSettings: peerNotificationSettings, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) + if hasValidInclusion { + if let notificationSettings = transaction.getPeerNotificationSettings(peerId) as? TelegramPeerNotificationSettings { + peerChatInfos[peerId] = PeerChatInfo(notificationSettings: notificationSettings) + } + } + let initialState = AccountMutableState(initialState: AccountInitialState(state: accountState, peerIds: Set(), peerIdsRequiringLocalChatState: Set(), chatStates: chatStates, peerChatInfos: peerChatInfos, locallyGeneratedMessageTimestamps: [:], cloudReadStates: [:], channelsToPollExplicitely: Set()), initialPeers: initialPeers, initialReferencedMessageIds: Set(), initialStoredMessages: Set(), initialReadInboxMaxIds: [:], storedMessagesByPeerIdAndTimestamp: [:]) return pollChannel(network: network, peer: peer, state: initialState) |> mapToSignal { (finalState, _, timeout) -> Signal in return resolveAssociatedMessages(network: network, state: finalState) |> mapToSignal { resultingState -> Signal in - return resolveMissingPeerNotificationSettings(network: network, state: resultingState) + return resolveMissingPeerChatInfos(network: network, state: resultingState) |> map { resultingState -> AccountFinalState in return AccountFinalState(state: resultingState, shouldPoll: false, incomplete: false) } @@ -1540,6 +1581,7 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl var apiChannelPts: Int32? let apiNotificationSettings: Api.PeerNotifySettings let apiMarkedUnread: Bool + let groupId: PeerGroupId switch dialog { case let .dialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, peerNotificationSettings, pts, _, folderId): apiPeer = peer @@ -1551,6 +1593,7 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl apiUnreadMentionsCount = unreadMentionsCount apiNotificationSettings = peerNotificationSettings apiChannelPts = pts + groupId = PeerGroupId(rawValue: folderId ?? 0) case .dialogFolder: assertionFailure() continue loop @@ -1580,6 +1623,8 @@ private func resetChannels(network: Network, peers: [Peer], state: AccountMutabl } notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings) + + updatedState.updatePeerChatInclusion(peerId: peerId, groupId: groupId) } for message in messages { @@ -1892,7 +1937,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation]) var currentAddMessages: OptimizeAddMessagesState? for operation in operations { switch operation { - case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerInclusionMinTimestamp, .UpdatePeerGroup, .UpdateIsContact: + case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion: if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty { result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location)) } @@ -1961,8 +2006,6 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP var delayNotificatonsUntil: Int32? var peerActivityTimestamps: [PeerId: Int32] = [:] - var addHolesToGroupFeedIds = Set() - for (peerId, namespaces) in finalState.state.namespacesWithHolesFromPreviousState { for namespace in namespaces { if let id = transaction.getTopPeerMessageId(peerId: peerId, namespace: namespace) { @@ -1970,30 +2013,9 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP } else { transaction.addHole(peerId: peerId, namespace: namespace, space: .everywhere, range: 1 ... Int32.max) } - - if namespace == Namespaces.Message.Cloud { - let peer: Peer? = finalState.state.peers[peerId] ?? transaction.getPeer(peerId) - if let peer = peer { - var groupId: PeerGroupId? - if groupId == nil { - //groupId = transaction.getPeerGroupId(peerId) - } - if let groupId = groupId { - addHolesToGroupFeedIds.insert(groupId) - } - } else { - assertionFailure() - } - } } } - /*for groupId in addHolesToGroupFeedIds { - transaction.addFeedHoleFromLatestEntries(groupId: groupId) - let groupState = (transaction.getPeerGroupState(groupId) as? TelegramPeerGroupState) ?? TelegramPeerGroupState() - transaction.setPeerGroupState(groupId, state: groupState.withInvalidatedStateIndex()) - }*/ - var addedOperationIncomingMessageIds: [MessageId] = [] for operation in finalState.state.operations { switch operation { @@ -2107,16 +2129,18 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: id.peerId, minTimestamp: message.timestamp) } transaction.deleteMessagesInRange(peerId: id.peerId, namespace: id.namespace, minId: 1, maxId: id.id) - case let .UpdatePeerInclusionMinTimestamp(peerId, timestamp): - let inclusion = transaction.getPeerChatListInclusion(peerId) - switch inclusion { - case .ifHasMessages, .ifHasMessagesOrOneOf: - transaction.updatePeerChatListInclusion(peerId, inclusion: inclusion.withSetIfHasMessagesOrMaxMinTimestamp(timestamp)) + case let .UpdatePeerChatInclusion(peerId, groupId): + let currentInclusion = transaction.getPeerChatListInclusion(peerId) + var currentPinningIndex: UInt16? + var currentMinTimestamp: Int32? + switch currentInclusion { + case let .ifHasMessagesOrOneOf(_, pinningIndex, minTimestamp): + currentPinningIndex = pinningIndex + currentMinTimestamp = minTimestamp default: break } - case let .UpdatePeerGroup(peerId, groupId): - transaction.updatePeerGroupId(peerId, groupId: groupId) + transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessagesOrOneOf(groupId: groupId, pinningIndex: currentPinningIndex, minTimestamp: currentMinTimestamp)) case let .EditMessage(id, message): transaction.updateMessage(id, update: { previousMessage in var updatedFlags = message.flags @@ -2311,7 +2335,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP case let .pin(itemId): switch itemId { case let .peer(peerId): - if transaction.getPeer(peerId) == nil || transaction.getPeerChatListInclusion(peerId) == .notSpecified { + if transaction.getPeer(peerId) == nil || transaction.getPeerChatListInclusion(peerId) == .notIncluded { addSynchronizePinnedChatsOperation(transaction: transaction, groupId: groupId) } else { var currentItemIds = transaction.getPinnedItemIds(groupId: groupId) @@ -2320,8 +2344,6 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP transaction.setPinnedItemIds(groupId: groupId, itemIds: currentItemIds) } } - case .group: - break } case let .unpin(itemId): switch itemId { @@ -2333,8 +2355,6 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP } else { addSynchronizePinnedChatsOperation(transaction: transaction, groupId: groupId) } - case .group: - break } case let .reorder(itemIds): let currentItemIds = transaction.getPinnedItemIds(groupId: groupId) @@ -2399,10 +2419,6 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP updatePeerPresenceLastActivities(transaction: transaction, accountPeerId: accountPeerId, activities: peerActivityTimestamps) } - for peerId in finalState.state.initialState.peerIdsWithNewMessages { - updatePeerChatInclousionWithNewMessages(transaction: transaction, id: peerId) - } - if !stickerPackOperations.isEmpty { if stickerPackOperations.contains(where: { if case .sync = $0 { diff --git a/TelegramCore/AccountStateManager.swift b/TelegramCore/AccountStateManager.swift index 2ac4941c09..363f5f00f2 100644 --- a/TelegramCore/AccountStateManager.swift +++ b/TelegramCore/AccountStateManager.swift @@ -96,8 +96,8 @@ public final class AccountStateManager { return self.isUpdatingValue.get() } - private let notificationMessagesPipe = ValuePipe<[([Message], PeerGroupId?, Bool)]>() - public var notificationMessages: Signal<[([Message], PeerGroupId?, Bool)], NoError> { + private let notificationMessagesPipe = ValuePipe<[([Message], PeerGroupId, Bool)]>() + public var notificationMessages: Signal<[([Message], PeerGroupId, Bool)], NoError> { return self.notificationMessagesPipe.signal() } @@ -385,9 +385,11 @@ public final class AccountStateManager { |> mapToSignal { difference -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in switch difference { case .differenceTooLong: - return accountStateReset(postbox: postbox, network: network, accountPeerId: accountPeerId) |> mapToSignal { _ -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in + preconditionFailure() + /*return accountStateReset(postbox: postbox, network: network, accountPeerId: accountPeerId) |> mapToSignal { _ -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in return .complete() - } |> then(.single((nil, nil))) + } + |> then(.single((nil, nil)))*/ default: return initialStateWithDifference(postbox: postbox, difference: difference) |> mapToSignal { state -> Signal<(Api.updates.Difference?, AccountReplayedFinalState?), NoError> in @@ -625,13 +627,12 @@ public final class AccountStateManager { let _ = self.delayNotificatonsUntil.swap(events.delayNotificatonsUntil) } - let signal = self.postbox.transaction { transaction -> [([Message], PeerGroupId?, Bool)] in - var messageList: [([Message], PeerGroupId?, Bool)] = [] + let signal = self.postbox.transaction { transaction -> [([Message], PeerGroupId, Bool)] in + var messageList: [([Message], PeerGroupId, Bool)] = [] for id in events.addedIncomingMessageIds { let (messages, notify, _, _) = messagesForNotification(transaction: transaction, id: id, alwaysReturnMessage: false) if !messages.isEmpty { - messageList.append((messages, nil, notify)) - //messageList.append((messages, transaction.getPeerGroupId(messages[0].id.peerId), notify)) + messageList.append((messages, .root, notify)) } } return messageList diff --git a/TelegramCore/AccountStateReset.swift b/TelegramCore/AccountStateReset.swift index 1b08429383..a1ed9f1a99 100644 --- a/TelegramCore/AccountStateReset.swift +++ b/TelegramCore/AccountStateReset.swift @@ -123,14 +123,14 @@ private struct ResolvedChatListResetRange { let remote: FetchedChatList } -func accountStateReset(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal { +/*func accountStateReset(postbox: Postbox, network: Network, accountPeerId: PeerId) -> Signal { let pinnedChats: Signal = network.request(Api.functions.messages.getPinnedDialogs(folderId: 0)) |> retryRequest let state: Signal = network.request(Api.functions.updates.getState()) |> retryRequest return postbox.transaction { transaction -> [ChatListNamespaceEntry] in - return transaction.getChatListNamespaceEntries(groupId: nil, namespace: Namespaces.Message.Cloud, summaryTag: MessageTags.unseenPersonalMessage) + return transaction.getChatListNamespaceEntries(groupId: .root, namespace: Namespaces.Message.Cloud, summaryTag: MessageTags.unseenPersonalMessage) } |> mapToSignal { localChatListEntries -> Signal in let localRanges = localChatListEntryRanges(localChatListEntries, limit: 100) @@ -292,4 +292,4 @@ func accountStateReset(postbox: Postbox, network: Network, accountPeerId: PeerId } } } -} +}*/ diff --git a/TelegramCore/AccountViewTracker.swift b/TelegramCore/AccountViewTracker.swift index 92690d572c..d3f5ffaf83 100644 --- a/TelegramCore/AccountViewTracker.swift +++ b/TelegramCore/AccountViewTracker.swift @@ -1169,7 +1169,7 @@ public final class AccountViewTracker { }) } - public func tailChatListView(groupId: PeerGroupId?, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func tailChatListView(groupId: PeerGroupId, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { if let account = self.account { return self.wrappedChatListView(signal: account.postbox.tailChatListView(groupId: groupId, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) } else { @@ -1177,7 +1177,7 @@ public final class AccountViewTracker { } } - public func aroundChatListView(groupId: PeerGroupId?, index: ChatListIndex, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { + public func aroundChatListView(groupId: PeerGroupId, index: ChatListIndex, count: Int) -> Signal<(ChatListView, ViewUpdateType), NoError> { if let account = self.account { return self.wrappedChatListView(signal: account.postbox.aroundChatListView(groupId: groupId, index: index, count: count, summaryComponents: ChatListEntrySummaryComponents(tagSummary: ChatListEntryMessageTagSummaryComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), actionsSummary: ChatListEntryPendingMessageActionsSummaryComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)))) } else { diff --git a/TelegramCore/Api0.swift b/TelegramCore/Api0.swift index deb180742f..a6ee495a3f 100644 --- a/TelegramCore/Api0.swift +++ b/TelegramCore/Api0.swift @@ -9,8 +9,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-457104426] = { return Api.InputGeoPoint.parse_inputGeoPointEmpty($0) } dict[-206066487] = { return Api.InputGeoPoint.parse_inputGeoPoint($0) } dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) } - dict[478652186] = { return Api.ChatFull.parse_channelFull($0) } - dict[581055962] = { return Api.ChatFull.parse_chatFull($0) } + dict[461151667] = { return Api.ChatFull.parse_chatFull($0) } + dict[56920439] = { return Api.ChatFull.parse_channelFull($0) } dict[1465219162] = { return Api.PollResults.parse_pollResults($0) } dict[-925415106] = { return Api.ChatParticipant.parse_chatParticipant($0) } dict[-636267638] = { return Api.ChatParticipant.parse_chatParticipantCreator($0) } @@ -94,7 +94,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[483104362] = { return Api.RichText.parse_textPhone($0) } dict[136105807] = { return Api.RichText.parse_textImage($0) } dict[894777186] = { return Api.RichText.parse_textAnchor($0) } - dict[-1901811583] = { return Api.UserFull.parse_userFull($0) } + dict[1951750604] = { return Api.UserFull.parse_userFull($0) } dict[-292807034] = { return Api.InputChannel.parse_inputChannelEmpty($0) } dict[-1343524562] = { return Api.InputChannel.parse_inputChannel($0) } dict[414687501] = { return Api.DcOption.parse_dcOption($0) } @@ -184,14 +184,12 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) } dict[-298113238] = { return Api.Update.parse_updatePrivacy($0) } dict[314130811] = { return Api.Update.parse_updateUserPhone($0) } - dict[-1721631396] = { return Api.Update.parse_updateReadHistoryInbox($0) } dict[791617983] = { return Api.Update.parse_updateReadHistoryOutbox($0) } dict[2139689491] = { return Api.Update.parse_updateWebPage($0) } dict[1757493555] = { return Api.Update.parse_updateReadMessagesContents($0) } dict[-352032773] = { return Api.Update.parse_updateChannelTooLong($0) } dict[-1227598250] = { return Api.Update.parse_updateChannel($0) } dict[1656358105] = { return Api.Update.parse_updateNewChannelMessage($0) } - dict[1108669311] = { return Api.Update.parse_updateReadChannelInbox($0) } dict[-1015733815] = { return Api.Update.parse_updateDeleteChannelMessages($0) } dict[-1734268085] = { return Api.Update.parse_updateChannelMessageViews($0) } dict[-1232070311] = { return Api.Update.parse_updateChatParticipantAdmin($0) } @@ -232,6 +230,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[422972864] = { return Api.Update.parse_updateFolderPeers($0) } dict[1852826908] = { return Api.Update.parse_updateDialogPinned($0) } dict[-99664734] = { return Api.Update.parse_updatePinnedDialogs($0) } + dict[856380452] = { return Api.Update.parse_updateReadChannelInbox($0) } + dict[-1667805217] = { return Api.Update.parse_updateReadHistoryInbox($0) } dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) } dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) } dict[367766557] = { return Api.ChannelParticipant.parse_channelParticipant($0) } diff --git a/TelegramCore/Api1.swift b/TelegramCore/Api1.swift index 15a10e22b8..15a19a2a46 100644 --- a/TelegramCore/Api1.swift +++ b/TelegramCore/Api1.swift @@ -50,14 +50,33 @@ extension Api { } enum ChatFull: TypeConstructorDescription { - case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?) - case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?) + case chatFull(flags: Int32, id: Int32, about: String, participants: Api.ChatParticipants, chatPhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo]?, pinnedMsgId: Int32?, folderId: Int32?) + case channelFull(flags: Int32, id: Int32, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite, botInfo: [Api.BotInfo], migratedFromChatId: Int32?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, pts: Int32) func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId): + case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId): if boxed { - buffer.appendInt32(478652186) + buffer.appendInt32(461151667) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(id, buffer: buffer, boxed: false) + serializeString(about, buffer: buffer, boxed: false) + participants.serialize(buffer, true) + if Int(flags) & Int(1 << 2) != 0 {chatPhoto!.serialize(buffer, true)} + notifySettings.serialize(buffer, true) + exportedInvite.serialize(buffer, true) + if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(botInfo!.count)) + for item in botInfo! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 6) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + break + case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let pts): + if boxed { + buffer.appendInt32(56920439) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt32(id, buffer: buffer, boxed: false) @@ -83,37 +102,69 @@ extension Api { if Int(flags) & Int(1 << 5) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} if Int(flags) & Int(1 << 8) != 0 {stickerset!.serialize(buffer, true)} if Int(flags) & Int(1 << 9) != 0 {serializeInt32(availableMinId!, buffer: buffer, boxed: false)} - break - case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId): - if boxed { - buffer.appendInt32(581055962) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt32(id, buffer: buffer, boxed: false) - serializeString(about, buffer: buffer, boxed: false) - participants.serialize(buffer, true) - if Int(flags) & Int(1 << 2) != 0 {chatPhoto!.serialize(buffer, true)} - notifySettings.serialize(buffer, true) - exportedInvite.serialize(buffer, true) - if Int(flags) & Int(1 << 3) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(botInfo!.count)) - for item in botInfo! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 6) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + serializeInt32(pts, buffer: buffer, boxed: false) break } } func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId): - return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId)]) - case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId): - return ("chatFull", [("flags", flags), ("id", id), ("about", about), ("participants", participants), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId)]) + case .chatFull(let flags, let id, let about, let participants, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let pinnedMsgId, let folderId): + return ("chatFull", [("flags", flags), ("id", id), ("about", about), ("participants", participants), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("folderId", folderId)]) + case .channelFull(let flags, let id, let about, let participantsCount, let adminsCount, let kickedCount, let bannedCount, let onlineCount, let readInboxMaxId, let readOutboxMaxId, let unreadCount, let chatPhoto, let notifySettings, let exportedInvite, let botInfo, let migratedFromChatId, let migratedFromMaxId, let pinnedMsgId, let stickerset, let availableMinId, let folderId, let pts): + return ("channelFull", [("flags", flags), ("id", id), ("about", about), ("participantsCount", participantsCount), ("adminsCount", adminsCount), ("kickedCount", kickedCount), ("bannedCount", bannedCount), ("onlineCount", onlineCount), ("readInboxMaxId", readInboxMaxId), ("readOutboxMaxId", readOutboxMaxId), ("unreadCount", unreadCount), ("chatPhoto", chatPhoto), ("notifySettings", notifySettings), ("exportedInvite", exportedInvite), ("botInfo", botInfo), ("migratedFromChatId", migratedFromChatId), ("migratedFromMaxId", migratedFromMaxId), ("pinnedMsgId", pinnedMsgId), ("stickerset", stickerset), ("availableMinId", availableMinId), ("folderId", folderId), ("pts", pts)]) } } + static func parse_chatFull(_ reader: BufferReader) -> ChatFull? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: String? + _3 = parseString(reader) + var _4: Api.ChatParticipants? + if let signature = reader.readInt32() { + _4 = Api.parse(reader, signature: signature) as? Api.ChatParticipants + } + var _5: Api.Photo? + if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { + _5 = Api.parse(reader, signature: signature) as? Api.Photo + } } + var _6: Api.PeerNotifySettings? + if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings + } + var _7: Api.ExportedChatInvite? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite + } + var _8: [Api.BotInfo]? + if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { + _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInfo.self) + } } + var _9: Int32? + if Int(_1!) & Int(1 << 6) != 0 {_9 = reader.readInt32() } + var _10: Int32? + if Int(_1!) & Int(1 << 11) != 0 {_10 = reader.readInt32() } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil + let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil + let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { + return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7!, botInfo: _8, pinnedMsgId: _9, folderId: _10) + } + else { + return nil + } + } static func parse_channelFull(_ reader: BufferReader) -> ChatFull? { var _1: Int32? _1 = reader.readInt32() @@ -165,6 +216,10 @@ extension Api { } } var _20: Int32? if Int(_1!) & Int(1 << 9) != 0 {_20 = reader.readInt32() } + var _21: Int32? + if Int(_1!) & Int(1 << 11) != 0 {_21 = reader.readInt32() } + var _22: Int32? + _22 = reader.readInt32() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil @@ -185,53 +240,10 @@ extension Api { let _c18 = (Int(_1!) & Int(1 << 5) == 0) || _18 != nil let _c19 = (Int(_1!) & Int(1 << 8) == 0) || _19 != nil let _c20 = (Int(_1!) & Int(1 << 9) == 0) || _20 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 { - return Api.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14!, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20) - } - else { - return nil - } - } - static func parse_chatFull(_ reader: BufferReader) -> ChatFull? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - var _3: String? - _3 = parseString(reader) - var _4: Api.ChatParticipants? - if let signature = reader.readInt32() { - _4 = Api.parse(reader, signature: signature) as? Api.ChatParticipants - } - var _5: Api.Photo? - if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.Photo - } } - var _6: Api.PeerNotifySettings? - if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.PeerNotifySettings - } - var _7: Api.ExportedChatInvite? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.ExportedChatInvite - } - var _8: [Api.BotInfo]? - if Int(_1!) & Int(1 << 3) != 0 {if let _ = reader.readInt32() { - _8 = Api.parseVector(reader, elementSignature: 0, elementType: Api.BotInfo.self) - } } - var _9: Int32? - if Int(_1!) & Int(1 << 6) != 0 {_9 = reader.readInt32() } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = (Int(_1!) & Int(1 << 2) == 0) || _5 != nil - let _c6 = _6 != nil - let _c7 = _7 != nil - let _c8 = (Int(_1!) & Int(1 << 3) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 6) == 0) || _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.ChatFull.chatFull(flags: _1!, id: _2!, about: _3!, participants: _4!, chatPhoto: _5, notifySettings: _6!, exportedInvite: _7!, botInfo: _8, pinnedMsgId: _9) + let _c21 = (Int(_1!) & Int(1 << 11) == 0) || _21 != nil + let _c22 = _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.ChatFull.channelFull(flags: _1!, id: _2!, about: _3!, participantsCount: _4, adminsCount: _5, kickedCount: _6, bannedCount: _7, onlineCount: _8, readInboxMaxId: _9!, readOutboxMaxId: _10!, unreadCount: _11!, chatPhoto: _12!, notifySettings: _13!, exportedInvite: _14!, botInfo: _15!, migratedFromChatId: _16, migratedFromMaxId: _17, pinnedMsgId: _18, stickerset: _19, availableMinId: _20, folderId: _21, pts: _22!) } else { return nil @@ -2510,13 +2522,13 @@ extension Api { } enum UserFull: TypeConstructorDescription { - case userFull(flags: Int32, user: Api.User, about: String?, link: Api.contacts.Link, profilePhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32) + case userFull(flags: Int32, user: Api.User, about: String?, link: Api.contacts.Link, profilePhoto: Api.Photo?, notifySettings: Api.PeerNotifySettings, botInfo: Api.BotInfo?, pinnedMsgId: Int32?, commonChatsCount: Int32, folderId: Int32?) func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { - case .userFull(let flags, let user, let about, let link, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount): + case .userFull(let flags, let user, let about, let link, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId): if boxed { - buffer.appendInt32(-1901811583) + buffer.appendInt32(1951750604) } serializeInt32(flags, buffer: buffer, boxed: false) user.serialize(buffer, true) @@ -2527,14 +2539,15 @@ extension Api { if Int(flags) & Int(1 << 3) != 0 {botInfo!.serialize(buffer, true)} if Int(flags) & Int(1 << 6) != 0 {serializeInt32(pinnedMsgId!, buffer: buffer, boxed: false)} serializeInt32(commonChatsCount, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 11) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} break } } func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .userFull(let flags, let user, let about, let link, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount): - return ("userFull", [("flags", flags), ("user", user), ("about", about), ("link", link), ("profilePhoto", profilePhoto), ("notifySettings", notifySettings), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("commonChatsCount", commonChatsCount)]) + case .userFull(let flags, let user, let about, let link, let profilePhoto, let notifySettings, let botInfo, let pinnedMsgId, let commonChatsCount, let folderId): + return ("userFull", [("flags", flags), ("user", user), ("about", about), ("link", link), ("profilePhoto", profilePhoto), ("notifySettings", notifySettings), ("botInfo", botInfo), ("pinnedMsgId", pinnedMsgId), ("commonChatsCount", commonChatsCount), ("folderId", folderId)]) } } @@ -2567,6 +2580,8 @@ extension Api { if Int(_1!) & Int(1 << 6) != 0 {_8 = reader.readInt32() } var _9: Int32? _9 = reader.readInt32() + var _10: Int32? + if Int(_1!) & Int(1 << 11) != 0 {_10 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil @@ -2576,8 +2591,9 @@ extension Api { let _c7 = (Int(_1!) & Int(1 << 3) == 0) || _7 != nil let _c8 = (Int(_1!) & Int(1 << 6) == 0) || _8 != nil let _c9 = _9 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 { - return Api.UserFull.userFull(flags: _1!, user: _2!, about: _3, link: _4!, profilePhoto: _5, notifySettings: _6!, botInfo: _7, pinnedMsgId: _8, commonChatsCount: _9!) + let _c10 = (Int(_1!) & Int(1 << 11) == 0) || _10 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 { + return Api.UserFull.userFull(flags: _1!, user: _2!, about: _3, link: _4!, profilePhoto: _5, notifySettings: _6!, botInfo: _7, pinnedMsgId: _8, commonChatsCount: _9!, folderId: _10) } else { return nil @@ -3924,14 +3940,12 @@ extension Api { case updateServiceNotification(flags: Int32, inboxDate: Int32?, type: String, message: String, media: Api.MessageMedia, entities: [Api.MessageEntity]) case updatePrivacy(key: Api.PrivacyKey, rules: [Api.PrivacyRule]) case updateUserPhone(userId: Int32, phone: String) - case updateReadHistoryInbox(peer: Api.Peer, maxId: Int32, pts: Int32, ptsCount: Int32) case updateReadHistoryOutbox(peer: Api.Peer, maxId: Int32, pts: Int32, ptsCount: Int32) case updateWebPage(webpage: Api.WebPage, pts: Int32, ptsCount: Int32) case updateReadMessagesContents(messages: [Int32], pts: Int32, ptsCount: Int32) case updateChannelTooLong(flags: Int32, channelId: Int32, pts: Int32?) case updateChannel(channelId: Int32) case updateNewChannelMessage(message: Api.Message, pts: Int32, ptsCount: Int32) - case updateReadChannelInbox(channelId: Int32, maxId: Int32) case updateDeleteChannelMessages(channelId: Int32, messages: [Int32], pts: Int32, ptsCount: Int32) case updateChannelMessageViews(channelId: Int32, id: Int32, views: Int32) case updateChatParticipantAdmin(chatId: Int32, userId: Int32, isAdmin: Api.Bool, version: Int32) @@ -3972,6 +3986,8 @@ extension Api { case updateFolderPeers(folderPeers: [Api.FolderPeer], pts: Int32, ptsCount: Int32) case updateDialogPinned(flags: Int32, folderId: Int32?, peer: Api.DialogPeer) case updatePinnedDialogs(flags: Int32, folderId: Int32?, order: [Api.DialogPeer]?) + case updateReadChannelInbox(flags: Int32, folderId: Int32?, channelId: Int32, maxId: Int32, stillUnreadCount: Int32, pts: Int32) + case updateReadHistoryInbox(flags: Int32, folderId: Int32?, peer: Api.Peer, maxId: Int32, stillUnreadCount: Int32, pts: Int32, ptsCount: Int32) func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -4159,15 +4175,6 @@ extension Api { serializeInt32(userId, buffer: buffer, boxed: false) serializeString(phone, buffer: buffer, boxed: false) break - case .updateReadHistoryInbox(let peer, let maxId, let pts, let ptsCount): - if boxed { - buffer.appendInt32(-1721631396) - } - peer.serialize(buffer, true) - serializeInt32(maxId, buffer: buffer, boxed: false) - serializeInt32(pts, buffer: buffer, boxed: false) - serializeInt32(ptsCount, buffer: buffer, boxed: false) - break case .updateReadHistoryOutbox(let peer, let maxId, let pts, let ptsCount): if boxed { buffer.appendInt32(791617983) @@ -4219,13 +4226,6 @@ extension Api { serializeInt32(pts, buffer: buffer, boxed: false) serializeInt32(ptsCount, buffer: buffer, boxed: false) break - case .updateReadChannelInbox(let channelId, let maxId): - if boxed { - buffer.appendInt32(1108669311) - } - serializeInt32(channelId, buffer: buffer, boxed: false) - serializeInt32(maxId, buffer: buffer, boxed: false) - break case .updateDeleteChannelMessages(let channelId, let messages, let pts, let ptsCount): if boxed { buffer.appendInt32(-1015733815) @@ -4557,6 +4557,29 @@ extension Api { item.serialize(buffer, true) }} break + case .updateReadChannelInbox(let flags, let folderId, let channelId, let maxId, let stillUnreadCount, let pts): + if boxed { + buffer.appendInt32(856380452) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + serializeInt32(channelId, buffer: buffer, boxed: false) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(stillUnreadCount, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + break + case .updateReadHistoryInbox(let flags, let folderId, let peer, let maxId, let stillUnreadCount, let pts, let ptsCount): + if boxed { + buffer.appendInt32(-1667805217) + } + serializeInt32(flags, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(folderId!, buffer: buffer, boxed: false)} + peer.serialize(buffer, true) + serializeInt32(maxId, buffer: buffer, boxed: false) + serializeInt32(stillUnreadCount, buffer: buffer, boxed: false) + serializeInt32(pts, buffer: buffer, boxed: false) + serializeInt32(ptsCount, buffer: buffer, boxed: false) + break } } @@ -4606,8 +4629,6 @@ extension Api { return ("updatePrivacy", [("key", key), ("rules", rules)]) case .updateUserPhone(let userId, let phone): return ("updateUserPhone", [("userId", userId), ("phone", phone)]) - case .updateReadHistoryInbox(let peer, let maxId, let pts, let ptsCount): - return ("updateReadHistoryInbox", [("peer", peer), ("maxId", maxId), ("pts", pts), ("ptsCount", ptsCount)]) case .updateReadHistoryOutbox(let peer, let maxId, let pts, let ptsCount): return ("updateReadHistoryOutbox", [("peer", peer), ("maxId", maxId), ("pts", pts), ("ptsCount", ptsCount)]) case .updateWebPage(let webpage, let pts, let ptsCount): @@ -4620,8 +4641,6 @@ extension Api { return ("updateChannel", [("channelId", channelId)]) case .updateNewChannelMessage(let message, let pts, let ptsCount): return ("updateNewChannelMessage", [("message", message), ("pts", pts), ("ptsCount", ptsCount)]) - case .updateReadChannelInbox(let channelId, let maxId): - return ("updateReadChannelInbox", [("channelId", channelId), ("maxId", maxId)]) case .updateDeleteChannelMessages(let channelId, let messages, let pts, let ptsCount): return ("updateDeleteChannelMessages", [("channelId", channelId), ("messages", messages), ("pts", pts), ("ptsCount", ptsCount)]) case .updateChannelMessageViews(let channelId, let id, let views): @@ -4702,6 +4721,10 @@ extension Api { return ("updateDialogPinned", [("flags", flags), ("folderId", folderId), ("peer", peer)]) case .updatePinnedDialogs(let flags, let folderId, let order): return ("updatePinnedDialogs", [("flags", flags), ("folderId", folderId), ("order", order)]) + case .updateReadChannelInbox(let flags, let folderId, let channelId, let maxId, let stillUnreadCount, let pts): + return ("updateReadChannelInbox", [("flags", flags), ("folderId", folderId), ("channelId", channelId), ("maxId", maxId), ("stillUnreadCount", stillUnreadCount), ("pts", pts)]) + case .updateReadHistoryInbox(let flags, let folderId, let peer, let maxId, let stillUnreadCount, let pts, let ptsCount): + return ("updateReadHistoryInbox", [("flags", flags), ("folderId", folderId), ("peer", peer), ("maxId", maxId), ("stillUnreadCount", stillUnreadCount), ("pts", pts), ("ptsCount", ptsCount)]) } } @@ -5095,28 +5118,6 @@ extension Api { return nil } } - static func parse_updateReadHistoryInbox(_ reader: BufferReader) -> Update? { - var _1: Api.Peer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.Peer - } - var _2: Int32? - _2 = reader.readInt32() - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - _4 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.Update.updateReadHistoryInbox(peer: _1!, maxId: _2!, pts: _3!, ptsCount: _4!) - } - else { - return nil - } - } static func parse_updateReadHistoryOutbox(_ reader: BufferReader) -> Update? { var _1: Api.Peer? if let signature = reader.readInt32() { @@ -5224,20 +5225,6 @@ extension Api { return nil } } - static func parse_updateReadChannelInbox(_ reader: BufferReader) -> Update? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.Update.updateReadChannelInbox(channelId: _1!, maxId: _2!) - } - else { - return nil - } - } static func parse_updateDeleteChannelMessages(_ reader: BufferReader) -> Update? { var _1: Int32? _1 = reader.readInt32() @@ -5885,6 +5872,63 @@ extension Api { return nil } } + static func parse_updateReadChannelInbox(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int32? + _6 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.Update.updateReadChannelInbox(flags: _1!, folderId: _2, channelId: _3!, maxId: _4!, stillUnreadCount: _5!, pts: _6!) + } + else { + return nil + } + } + static func parse_updateReadHistoryInbox(_ reader: BufferReader) -> Update? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_2 = reader.readInt32() } + var _3: Api.Peer? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int32? + _6 = reader.readInt32() + var _7: Int32? + _7 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + let _c7 = _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.Update.updateReadHistoryInbox(flags: _1!, folderId: _2, peer: _3!, maxId: _4!, stillUnreadCount: _5!, pts: _6!, ptsCount: _7!) + } + else { + return nil + } + } } enum PopularContact: TypeConstructorDescription { diff --git a/TelegramCore/ApplyMaxReadIndexInteractively.swift b/TelegramCore/ApplyMaxReadIndexInteractively.swift index 36171dac5c..c1adcea2d1 100644 --- a/TelegramCore/ApplyMaxReadIndexInteractively.swift +++ b/TelegramCore/ApplyMaxReadIndexInteractively.swift @@ -159,8 +159,8 @@ public func clearPeerUnseenPersonalMessagesInteractively(account: Account, peerI |> ignoreValues } -public func markAllChatsAsReadInteractively(transaction: Transaction, viewTracker: AccountViewTracker) { - for peerId in transaction.getUnreadChatListPeerIds() { +public func markAllChatsAsReadInteractively(transaction: Transaction, viewTracker: AccountViewTracker, groupId: PeerGroupId) { + for peerId in transaction.getUnreadChatListPeerIds(groupId: groupId) { togglePeerUnreadMarkInteractively(transaction: transaction, viewTracker: viewTracker, peerId: peerId, setToValue: false) } } diff --git a/TelegramCore/ChatHistoryPreloadManager.swift b/TelegramCore/ChatHistoryPreloadManager.swift index f3095a4ddd..128e167b67 100644 --- a/TelegramCore/ChatHistoryPreloadManager.swift +++ b/TelegramCore/ChatHistoryPreloadManager.swift @@ -189,7 +189,7 @@ final class ChatHistoryPreloadManager { self.accountPeerId = accountPeerId self.download.set(network.background()) - self.automaticChatListDisposable = (postbox.tailChatListView(groupId: nil, count: 20, summaryComponents: ChatListEntrySummaryComponents()) + self.automaticChatListDisposable = (postbox.tailChatListView(groupId: .root, count: 20, summaryComponents: ChatListEntrySummaryComponents()) |> deliverOnMainQueue).start(next: { [weak self] view in guard let strongSelf = self else { return diff --git a/TelegramCore/FetchChatList.swift b/TelegramCore/FetchChatList.swift index 3305199048..08cc275c95 100644 --- a/TelegramCore/FetchChatList.swift +++ b/TelegramCore/FetchChatList.swift @@ -15,7 +15,7 @@ enum FetchChatListLocation { } struct ParsedDialogs { - let itemIds: [PinnedItemId] + let itemIds: [PeerId] let peers: [Peer] let peerPresences: [PeerId: PeerPresence] @@ -27,7 +27,7 @@ struct ParsedDialogs { let storeMessages: [StoreMessage] let lowerNonPinnedIndex: MessageIndex? - let referencedFolders: [PeerGroupId] + let referencedFolders: [PeerGroupId: PeerGroupUnreadCountersSummary] } private func extractDialogsData(dialogs: Api.messages.Dialogs) -> (apiDialogs: [Api.Dialog], apiMessages: [Api.Message], apiChats: [Api.Chat], apiUsers: [Api.User], apiIsAtLowestBoundary: Bool) { @@ -59,8 +59,8 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message], var storeMessages: [StoreMessage] = [] var nonPinnedDialogsTopMessageIds = Set() - var referencedFolders = Set() - var itemIds: [PinnedItemId] = [] + var referencedFolders: [PeerGroupId: PeerGroupUnreadCountersSummary] = [:] + var itemIds: [PeerId] = [] for dialog in apiDialogs { let apiPeer: Api.Peer @@ -74,7 +74,7 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message], let apiNotificationSettings: Api.PeerNotifySettings switch dialog { case let .dialog(flags, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, peerNotificationSettings, pts, _, _): - itemIds.append(.peer(peer.peerId)) + itemIds.append(peer.peerId) apiPeer = peer apiTopMessage = topMessage apiReadInboxMaxId = readInboxMaxId @@ -113,13 +113,11 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message], } notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings) - case let .dialogFolder(flags, folder, _, _, _, _, _, _): - switch folder { - case let .folder(flags, id, title, photo): - referencedFolders.insert(PeerGroupId(rawValue: id)) - break + case let .dialogFolder(dialogFolder): + switch dialogFolder.folder { + case let .folder(folder): + referencedFolders[PeerGroupId(rawValue: folder.id)] = PeerGroupUnreadCountersSummary(all: PeerGroupUnreadCounters(messageCount: dialogFolder.unreadMutedMessagesCount, chatCount: dialogFolder.unreadMutedPeersCount)) } - break } } @@ -174,11 +172,12 @@ private func parseDialogs(apiDialogs: [Api.Dialog], apiMessages: [Api.Message], storeMessages: storeMessages, lowerNonPinnedIndex: lowerNonPinnedIndex, - referencedFolders: Array(referencedFolders) + referencedFolders: referencedFolders ) } struct FetchedChatList { + let chatPeerIds: [PeerId] let peers: [Peer] let peerPresences: [PeerId: PeerPresence] let notificationSettings: [PeerId: PeerNotificationSettings] @@ -190,8 +189,8 @@ struct FetchedChatList { let lowerNonPinnedIndex: MessageIndex? - let pinnedItemIds: [PinnedItemId]? - let folders: [(PeerGroupId, MessageIndex?)] + let pinnedItemIds: [PeerId]? + let folderSummaries: [PeerGroupId: PeerGroupUnreadCountersSummary] let peerGroupIds: [PeerId: PeerGroupId] } @@ -262,9 +261,9 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo } var combinedReferencedFolders = Set() - combinedReferencedFolders.formUnion(parsedRemoteChats.referencedFolders) + combinedReferencedFolders.formUnion(parsedRemoteChats.referencedFolders.keys) if let parsedPinnedChats = parsedPinnedChats { - combinedReferencedFolders.formUnion(parsedPinnedChats.referencedFolders) + combinedReferencedFolders.formUnion(Set(parsedPinnedChats.referencedFolders.keys)) } var folderSignals: [Signal<(PeerGroupId, ParsedDialogs), NoError>] = [] @@ -316,24 +315,14 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo var peerGroupIds: [PeerId: PeerGroupId] = [:] if case let .group(groupId) = location { - for itemId in parsedRemoteChats.itemIds { - switch itemId { - case let .peer(peerId): - peerGroupIds[peerId] = groupId - case .group: - break - } + for peerId in parsedRemoteChats.itemIds { + peerGroupIds[peerId] = groupId } } for (groupId, folderChats) in folders { - for itemId in folderChats.itemIds { - switch itemId { - case let .peer(peerId): - peerGroupIds[peerId] = groupId - case .group: - break - } + for peerId in folderChats.itemIds { + peerGroupIds[peerId] = groupId } peers.append(contentsOf: folderChats.peers) peerPresences.merge(folderChats.peerPresences, uniquingKeysWith: { _, updated in updated }) @@ -344,24 +333,30 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo storeMessages.append(contentsOf: folderChats.storeMessages) } - var pinnedItemIds: [PinnedItemId]? + var pinnedItemIds: [PeerId]? if let parsedPinnedChats = parsedPinnedChats { - var array: [PinnedItemId] = [] - for itemId in parsedPinnedChats.itemIds { - switch itemId { - case let .peer(peerId): - if case let .group(groupId) = location { - peerGroupIds[peerId] = groupId - } - array.append(itemId) - case .group: - break + var array: [PeerId] = [] + for peerId in parsedPinnedChats.itemIds { + if case let .group(groupId) = location { + peerGroupIds[peerId] = groupId } + array.append(peerId) } pinnedItemIds = array } + var folderSummaries: [PeerGroupId: PeerGroupUnreadCountersSummary] = [:] + for (groupId, summary) in parsedRemoteChats.referencedFolders { + folderSummaries[groupId] = summary + } + if let parsedPinnedChats = parsedPinnedChats { + for (groupId, summary) in parsedPinnedChats.referencedFolders { + folderSummaries[groupId] = summary + } + } + return FetchedChatList( + chatPeerIds: parsedRemoteChats.itemIds + (pinnedItemIds ?? []), peers: peers, peerPresences: peerPresences, notificationSettings: notificationSettings, @@ -374,7 +369,7 @@ func fetchChatList(postbox: Postbox, network: Network, location: FetchChatListLo lowerNonPinnedIndex: parsedRemoteChats.lowerNonPinnedIndex, pinnedItemIds: pinnedItemIds, - folders: folders.map { ($0.0, $0.1.lowerNonPinnedIndex) }, + folderSummaries: folderSummaries, peerGroupIds: peerGroupIds ) } diff --git a/TelegramCore/Holes.swift b/TelegramCore/Holes.swift index ad1b3b7297..b795af9379 100644 --- a/TelegramCore/Holes.swift +++ b/TelegramCore/Holes.swift @@ -353,12 +353,13 @@ func groupBoundaryPeer(_ peerId: PeerId, accountPeerId: PeerId) -> Api.Peer { } } -func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId, groupId: PeerGroupId?, hole: ChatListHole) -> Signal { +func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId, groupId: PeerGroupId, hole: ChatListHole) -> Signal { let location: FetchChatListLocation - if let groupId = groupId { - location = .group(groupId) - } else { - location = .general + switch groupId { + case .root: + location = .general + case .group: + location = .group(groupId) } return fetchChatList(postbox: postbox, network: network, location: location, upperBound: hole.index, hash: 0, limit: 100) |> mapToSignal { fetchedChats -> Signal in @@ -381,8 +382,20 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId transaction.replaceChatListHole(groupId: groupId, index: hole.index, hole: fetchedChats.lowerNonPinnedIndex.flatMap(ChatListHole.init)) - for (peerId, groupId) in fetchedChats.peerGroupIds { - transaction.updatePeerGroupId(peerId, groupId: groupId) + for peerId in fetchedChats.chatPeerIds { + if let peer = transaction.getPeer(peerId) { + transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessagesOrOneOf(groupId: groupId, pinningIndex: nil, minTimestamp: minTimestampForPeerInclusion(peer))) + } else { + assertionFailure() + } + } + + for (peerId, peerGroupId) in fetchedChats.peerGroupIds { + if let peer = transaction.getPeer(peerId) { + transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessagesOrOneOf(groupId: peerGroupId, pinningIndex: nil, minTimestamp: minTimestampForPeerInclusion(peer))) + } else { + assertionFailure() + } } for (peerId, chatState) in fetchedChats.chatStates { @@ -398,12 +411,16 @@ func fetchChatListHole(postbox: Postbox, network: Network, accountPeerId: PeerId } if let replacePinnedItemIds = fetchedChats.pinnedItemIds { - transaction.setPinnedItemIds(groupId: groupId, itemIds: replacePinnedItemIds) + transaction.setPinnedItemIds(groupId: groupId, itemIds: replacePinnedItemIds.map(PinnedItemId.peer)) } for (peerId, summary) in fetchedChats.mentionTagSummaries { transaction.replaceMessageTagSummary(peerId: peerId, tagMask: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud, count: summary.count, maxId: summary.range.maxId) } + + for (groupId, summary) in fetchedChats.folderSummaries { + transaction.resetPeerGroupSummary(groupId: groupId, namespace: Namespaces.Message.Cloud, summary: summary) + } }) } } diff --git a/TelegramCore/ManagedServiceViews.swift b/TelegramCore/ManagedServiceViews.swift index a2dcaba14a..93fd480cbc 100644 --- a/TelegramCore/ManagedServiceViews.swift +++ b/TelegramCore/ManagedServiceViews.swift @@ -13,7 +13,7 @@ func managedServiceViews(accountPeerId: PeerId, network: Network, postbox: Postb disposable.add(managedMessageHistoryHoles(accountPeerId: accountPeerId, network: network, postbox: postbox).start()) disposable.add(managedChatListHoles(network: network, postbox: postbox, accountPeerId: accountPeerId).start()) disposable.add(managedSynchronizePeerReadStates(network: network, postbox: postbox, stateManager: stateManager).start()) - //disposable.add(managedGroupFeedReadStateSyncOperations(postbox: postbox, network: network, accountPeerId: accountPeerId, stateManager: stateManager).start()) + disposable.add(managedSynchronizeGroupMessageStats(network: network, postbox: postbox, stateManager: stateManager).start()) return disposable } diff --git a/TelegramCore/ManagedSynchronizeGroupMessageStats.swift b/TelegramCore/ManagedSynchronizeGroupMessageStats.swift new file mode 100644 index 0000000000..63f40331ef --- /dev/null +++ b/TelegramCore/ManagedSynchronizeGroupMessageStats.swift @@ -0,0 +1,104 @@ +import Foundation +#if os(macOS) +import PostboxMac +import SwiftSignalKitMac +#else +import Postbox +import SwiftSignalKit +#endif + +private final class ManagedSynchronizeGroupMessageStatsState { + private var synchronizeDisposables: [PeerGroupAndNamespace: Disposable] = [:] + + func clearDisposables() -> [Disposable] { + let disposables = Array(self.synchronizeDisposables.values) + self.synchronizeDisposables.removeAll() + return disposables + } + + func update(operations: Set) -> (removed: [Disposable], added: [(PeerGroupAndNamespace, MetaDisposable)]) { + var removed: [Disposable] = [] + var added: [(PeerGroupAndNamespace, MetaDisposable)] = [] + + for (groupAndNamespace, disposable) in self.synchronizeDisposables { + if !operations.contains(groupAndNamespace) { + removed.append(disposable) + self.synchronizeDisposables.removeValue(forKey: groupAndNamespace) + } + } + + for groupAndNamespace in operations { + if self.synchronizeDisposables[groupAndNamespace] == nil { + let disposable = MetaDisposable() + self.synchronizeDisposables[groupAndNamespace] = disposable + added.append((groupAndNamespace, disposable)) + } + } + + return (removed, added) + } +} + +func managedSynchronizeGroupMessageStats(network: Network, postbox: Postbox, stateManager: AccountStateManager) -> Signal { + return Signal { _ in + let state = Atomic(value: ManagedSynchronizeGroupMessageStatsState()) + + let disposable = postbox.combinedView(keys: [.synchronizeGroupMessageStats]).start(next: { views in + let (removed, added) = state.with { state -> (removed: [Disposable], added: [(PeerGroupAndNamespace, MetaDisposable)]) in + let view = views.views[.synchronizeGroupMessageStats] as? SynchronizeGroupMessageStatsView + return state.update(operations: view?.groupsAndNamespaces ?? Set()) + } + + for disposable in removed { + disposable.dispose() + } + + for (groupAndNamespace, disposable) in added { + let synchronizeOperation = synchronizeGroupMessageStats(postbox: postbox, network: network, groupId: groupAndNamespace.groupId, namespace: groupAndNamespace.namespace) + disposable.set(synchronizeOperation.start()) + } + }) + + return ActionDisposable { + disposable.dispose() + for disposable in state.with({ state -> [Disposable] in + state.clearDisposables() + }) { + disposable.dispose() + } + } + } +} + +private func synchronizeGroupMessageStats(postbox: Postbox, network: Network, groupId: PeerGroupId, namespace: MessageId.Namespace) -> Signal { + if namespace != Namespaces.Message.Cloud { + return postbox.transaction { transaction in + transaction.confirmSynchronizedPeerGroupMessageStats(groupId: groupId, namespace: namespace) + } + } + + return network.request(Api.functions.messages.getPeerDialogs(peers: [.inputDialogPeerFolder(folderId: groupId.rawValue)])) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> mapToSignal { result -> Signal in + return postbox.transaction { transaction in + if let result = result { + switch result { + case let .peerDialogs(peerDialogs): + for dialog in peerDialogs.dialogs { + switch dialog { + case let .dialogFolder(dialogFolder): + transaction.resetPeerGroupSummary(groupId: groupId, namespace: namespace, summary: PeerGroupUnreadCountersSummary(all: PeerGroupUnreadCounters(messageCount: dialogFolder.unreadMutedMessagesCount, chatCount: dialogFolder.unreadMutedPeersCount))) + case .dialog: + assertionFailure() + break + } + } + } + } + transaction.confirmSynchronizedPeerGroupMessageStats(groupId: groupId, namespace: namespace) + } + } +} diff --git a/TelegramCore/ManagedSynchronizeGroupedPeersOperations.swift b/TelegramCore/ManagedSynchronizeGroupedPeersOperations.swift index 56df771f21..1c306db91d 100644 --- a/TelegramCore/ManagedSynchronizeGroupedPeersOperations.swift +++ b/TelegramCore/ManagedSynchronizeGroupedPeersOperations.swift @@ -119,7 +119,7 @@ private func synchronizeGroupedPeers(transaction: Transaction, postbox: Postbox, guard let inputPeer = transaction.getPeer(operation.peerId).flatMap(apiInputPeer) else { return .complete() } - let folderPeer: Api.InputFolderPeer = Api.InputFolderPeer.inputFolderPeer(peer: inputPeer, folderId: operation.groupId?.rawValue ?? 0) + let folderPeer: Api.InputFolderPeer = Api.InputFolderPeer.inputFolderPeer(peer: inputPeer, folderId: operation.groupId.rawValue) return network.request(Api.functions.folders.editPeerFolders(folderPeers: [folderPeer])) |> map(Optional.init) |> `catch` { _ -> Signal in diff --git a/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift b/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift index fff395b4fa..58e8d69134 100644 --- a/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift +++ b/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift @@ -86,7 +86,7 @@ func managedSynchronizePinnedChatsOperations(postbox: Postbox, network: Network, let signal = withTakenOperation(postbox: postbox, peerId: entry.peerId, tagLocalIndex: entry.tagLocalIndex, { transaction, entry -> Signal in if let entry = entry { if let operation = entry.contents as? SynchronizePinnedChatsOperation { - return synchronizePinnedChats(transaction: transaction, postbox: postbox, network: network, accountPeerId: accountPeerId, stateManager: stateManager, groupId: entry.peerId.id == 0 ? nil : PeerGroupId(rawValue: entry.peerId.id), operation: operation) + return synchronizePinnedChats(transaction: transaction, postbox: postbox, network: network, accountPeerId: accountPeerId, stateManager: stateManager, groupId: PeerGroupId(rawValue: entry.peerId.id), operation: operation) } else { assertionFailure() } @@ -113,7 +113,7 @@ func managedSynchronizePinnedChatsOperations(postbox: Postbox, network: Network, } } -private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox, network: Network, accountPeerId: PeerId, stateManager: AccountStateManager, groupId: PeerGroupId?, operation: SynchronizePinnedChatsOperation) -> Signal { +private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox, network: Network, accountPeerId: PeerId, stateManager: AccountStateManager, groupId: PeerGroupId, operation: SynchronizePinnedChatsOperation) -> Signal { let initialRemoteItemIds = operation.previousItemIds let initialRemoteItemIdsWithoutSecretChats = initialRemoteItemIds.filter { item in switch item { @@ -133,7 +133,7 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox, } } - return network.request(Api.functions.messages.getPinnedDialogs(folderId: groupId?.rawValue ?? 0)) + return network.request(Api.functions.messages.getPinnedDialogs(folderId: groupId.rawValue)) |> retryRequest |> mapToSignal { dialogs -> Signal in var storeMessages: [StoreMessage] = [] @@ -270,21 +270,17 @@ private func synchronizePinnedChats(transaction: Transaction, postbox: Postbox, if let peer = transaction.getPeer(peerId), let inputPeer = apiInputPeer(peer) { inputDialogPeers.append(Api.InputDialogPeer.inputDialogPeer(peer: inputPeer)) } - case let .group(groupId): - /*feed*/ - /*inputDialogPeers.append(.inputDialogPeerFeed(feedId: groupId.rawValue))*/ - break } } - return network.request(Api.functions.messages.reorderPinnedDialogs(flags: 1 << 0, folderId: groupId?.rawValue ?? 0, order: inputDialogPeers)) - |> `catch` { _ -> Signal in - return .single(Api.Bool.boolFalse) - } - |> mapToSignal { result -> Signal in - return postbox.transaction { transaction -> Void in - } + return network.request(Api.functions.messages.reorderPinnedDialogs(flags: 1 << 0, folderId: groupId.rawValue, order: inputDialogPeers)) + |> `catch` { _ -> Signal in + return .single(Api.Bool.boolFalse) + } + |> mapToSignal { result -> Signal in + return postbox.transaction { transaction -> Void in } + } } } |> switchToLatest diff --git a/TelegramCore/RemovePeerChat.swift b/TelegramCore/RemovePeerChat.swift index 5f58f1b641..b91778ae2f 100644 --- a/TelegramCore/RemovePeerChat.swift +++ b/TelegramCore/RemovePeerChat.swift @@ -37,18 +37,18 @@ public func removePeerChat(account: Account, transaction: Transaction, mediaBox: } } clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId) - transaction.updatePeerChatListInclusion(peerId, inclusion: .never) + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue) } else { cloudChatAddRemoveChatOperation(transaction: transaction, peerId: peerId, reportChatSpam: reportChatSpam, deleteGloballyIfPossible: deleteGloballyIfPossible) if peerId.namespace == Namespaces.Peer.CloudUser { - transaction.updatePeerChatListInclusion(peerId, inclusion: .ifHasMessages) + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId) } else if peerId.namespace == Namespaces.Peer.CloudGroup { - transaction.updatePeerChatListInclusion(peerId, inclusion: .never) + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) clearHistory(transaction: transaction, mediaBox: mediaBox, peerId: peerId) } else { - transaction.updatePeerChatListInclusion(peerId, inclusion: .never) + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) } } transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.RecentlySearchedPeerIds, itemId: RecentPeerItemId(peerId).rawValue) diff --git a/TelegramCore/SynchronizeGroupedPeersOperation.swift b/TelegramCore/SynchronizeGroupedPeersOperation.swift index 89abf63a8e..51255ebd19 100644 --- a/TelegramCore/SynchronizeGroupedPeersOperation.swift +++ b/TelegramCore/SynchronizeGroupedPeersOperation.swift @@ -9,53 +9,48 @@ import Foundation final class SynchronizeGroupedPeersOperation: PostboxCoding { let peerId: PeerId - let groupId: PeerGroupId? + let groupId: PeerGroupId - init(peerId: PeerId, groupId: PeerGroupId?) { + init(peerId: PeerId, groupId: PeerGroupId) { self.peerId = peerId self.groupId = groupId } init(decoder: PostboxDecoder) { self.peerId = PeerId(decoder.decodeInt64ForKey("peerId", orElse: 0)) - self.groupId = decoder.decodeOptionalInt32ForKey("groupId").flatMap(PeerGroupId.init(rawValue:)) + self.groupId = PeerGroupId.init(rawValue: decoder.decodeInt32ForKey("groupId", orElse: 0)) } func encode(_ encoder: PostboxEncoder) { encoder.encodeInt64(self.peerId.toInt64(), forKey: "peerId") - if let groupId = self.groupId { - encoder.encodeInt32(groupId.rawValue, forKey: "groupId") - } else { - encoder.encodeNil(forKey: "groupId") - } + encoder.encodeInt32(self.groupId.rawValue, forKey: "groupId") } } -public func updatePeerGroupIdInteractively(postbox: Postbox, peerId: PeerId, groupId: PeerGroupId?) -> Signal { +public func updatePeerGroupIdInteractively(postbox: Postbox, peerId: PeerId, groupId: PeerGroupId) -> Signal { return postbox.transaction { transaction -> Void in - let previousGroupId = transaction.getPeerGroupId(peerId) - - if previousGroupId != groupId { - transaction.updatePeerGroupId(peerId, groupId: groupId) - if peerId.namespace != Namespaces.Peer.SecretChat { - addSynchronizeGroupedPeersOperation(transaction: transaction, peerId: peerId, groupId: groupId) - } - } + updatePeerGroupIdInteractively(transaction: transaction, peerId: peerId, groupId: groupId) } } -public func updatePeerGroupIdInteractively(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId?) { - let previousGroupId = transaction.getPeerGroupId(peerId) - - if previousGroupId != groupId { - transaction.updatePeerGroupId(peerId, groupId: groupId) +public func updatePeerGroupIdInteractively(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId) { + let initialInclusion = transaction.getPeerChatListInclusion(peerId) + var updatedInclusion = initialInclusion + switch initialInclusion { + case .notIncluded: + break + case let .ifHasMessagesOrOneOf(_, pinningIndex, minTimestamp): + updatedInclusion = .ifHasMessagesOrOneOf(groupId: groupId, pinningIndex: pinningIndex, minTimestamp: minTimestamp) + } + if initialInclusion != updatedInclusion { + transaction.updatePeerChatListInclusion(peerId, inclusion: updatedInclusion) if peerId.namespace != Namespaces.Peer.SecretChat { addSynchronizeGroupedPeersOperation(transaction: transaction, peerId: peerId, groupId: groupId) } } } -private func addSynchronizeGroupedPeersOperation(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId?) { +private func addSynchronizeGroupedPeersOperation(transaction: Transaction, peerId: PeerId, groupId: PeerGroupId) { let tag: PeerOperationLogTag = OperationLogTags.SynchronizeGroupedPeers let logPeerId = PeerId(namespace: 0, id: 0) diff --git a/TelegramCore/SynchronizePinnedChatsOperation.swift b/TelegramCore/SynchronizePinnedChatsOperation.swift index af949f3721..e13339665f 100644 --- a/TelegramCore/SynchronizePinnedChatsOperation.swift +++ b/TelegramCore/SynchronizePinnedChatsOperation.swift @@ -16,8 +16,6 @@ private struct PreviousPeerItemId: PostboxCoding { switch decoder.decodeInt32ForKey("_t", orElse: 0) { case 0: self.id = .peer(PeerId(decoder.decodeInt64ForKey("i", orElse: 0))) - case 1: - self.id = .group(PeerGroupId(rawValue: decoder.decodeInt32ForKey("i", orElse: 0))) default: preconditionFailure() } @@ -28,9 +26,6 @@ private struct PreviousPeerItemId: PostboxCoding { case let .peer(peerId): encoder.encodeInt32(0, forKey: "_t") encoder.encodeInt64(peerId.toInt64(), forKey: "i") - case let .group(groupId): - encoder.encodeInt32(1, forKey: "_t") - encoder.encodeInt32(groupId.rawValue, forKey: "i") } } } @@ -52,8 +47,8 @@ final class SynchronizePinnedChatsOperation: PostboxCoding { } } -func addSynchronizePinnedChatsOperation(transaction: Transaction, groupId: PeerGroupId?) { - let rawId: Int32 = groupId?.rawValue ?? 0 +func addSynchronizePinnedChatsOperation(transaction: Transaction, groupId: PeerGroupId) { + let rawId: Int32 = groupId.rawValue var previousItemIds = transaction.getPinnedItemIds(groupId: groupId) var updateLocalIndex: Int32? diff --git a/TelegramCore/TelegramUserPresence.swift b/TelegramCore/TelegramUserPresence.swift index f468585cc5..cc7e494924 100644 --- a/TelegramCore/TelegramUserPresence.swift +++ b/TelegramCore/TelegramUserPresence.swift @@ -12,41 +12,6 @@ public enum UserPresenceStatus: Comparable, PostboxCoding { case lastWeek case lastMonth - public static func ==(lhs: UserPresenceStatus, rhs: UserPresenceStatus) -> Bool { - switch lhs { - case .none: - if case .none = rhs { - return true - } else { - return false - } - case let .present(until): - if case .present(until) = rhs { - return true - } else { - return false - } - case .recently: - if case .recently = rhs { - return true - } else { - return false - } - case .lastWeek: - if case .lastWeek = rhs { - return true - } else { - return false - } - case .lastMonth: - if case .lastMonth = rhs { - return true - } else { - return false - } - } - } - public static func <(lhs: UserPresenceStatus, rhs: UserPresenceStatus) -> Bool { switch lhs { case .none: diff --git a/TelegramCore/TogglePeerChatPinned.swift b/TelegramCore/TogglePeerChatPinned.swift index edb22e3881..b2fbd239ae 100644 --- a/TelegramCore/TogglePeerChatPinned.swift +++ b/TelegramCore/TogglePeerChatPinned.swift @@ -12,7 +12,7 @@ public enum TogglePeerChatPinnedResult { case limitExceeded } -public func toggleItemPinned(postbox: Postbox, groupId: PeerGroupId?, itemId: PinnedItemId) -> Signal { +public func toggleItemPinned(postbox: Postbox, groupId: PeerGroupId, itemId: PinnedItemId) -> Signal { return postbox.transaction { transaction -> TogglePeerChatPinnedResult in var itemIds = transaction.getPinnedItemIds(groupId: groupId) let sameKind = itemIds.filter { item in @@ -23,12 +23,6 @@ public func toggleItemPinned(postbox: Postbox, groupId: PeerGroupId?, itemId: Pi } else { return false } - case let .group(lhsGroupId): - if case let .group(rhsGroupId) = item { - return lhsGroupId != rhsGroupId - } else { - return false - } } } @@ -63,7 +57,7 @@ public func toggleItemPinned(postbox: Postbox, groupId: PeerGroupId?, itemId: Pi } } -public func reorderPinnedItemIds(transaction: Transaction, groupId: PeerGroupId?, itemIds: [PinnedItemId]) -> Bool { +public func reorderPinnedItemIds(transaction: Transaction, groupId: PeerGroupId, itemIds: [PinnedItemId]) -> Bool { if transaction.getPinnedItemIds(groupId: groupId) != itemIds { transaction.setPinnedItemIds(groupId: groupId, itemIds: itemIds) addSynchronizePinnedChatsOperation(transaction: transaction, groupId: groupId) diff --git a/TelegramCore/UpdateCachedPeerData.swift b/TelegramCore/UpdateCachedPeerData.swift index 5db7b003e7..1db9f84d18 100644 --- a/TelegramCore/UpdateCachedPeerData.swift +++ b/TelegramCore/UpdateCachedPeerData.swift @@ -158,80 +158,80 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId: PeerId, network } } else if let _ = peer as? TelegramGroup { return network.request(Api.functions.messages.getFullChat(chatId: peerId.id)) - |> retryRequest - |> mapToSignal { result -> Signal in - return postbox.transaction { transaction -> Void in - switch result { - case let .chatFull(fullChat, chats, users): - switch fullChat { - case let .chatFull(chatFull): - transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: chatFull.notifySettings)]) - case .channelFull: - break - } + |> retryRequest + |> mapToSignal { result -> Signal in + return postbox.transaction { transaction -> Void in + switch result { + case let .chatFull(fullChat, chats, users): + switch fullChat { + case let .chatFull(chatFull): + transaction.updateCurrentPeerNotificationSettings([peerId: TelegramPeerNotificationSettings(apiSettings: chatFull.notifySettings)]) + case .channelFull: + break + } + + switch fullChat { + case let .chatFull(chatFull): + var botInfos: [CachedPeerBotInfo] = [] + for botInfo in chatFull.botInfo ?? [] { + switch botInfo { + case let .botInfo(userId, _, _): + let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + let parsedBotInfo = BotInfo(apiBotInfo: botInfo) + botInfos.append(CachedPeerBotInfo(peerId: peerId, botInfo: parsedBotInfo)) + } + } + let participants = CachedGroupParticipants(apiParticipants: chatFull.participants) + let exportedInvitation = ExportedInvitation(apiExportedInvite: chatFull.exportedInvite) + let pinnedMessageId = chatFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }) - switch fullChat { - case let .chatFull(chatFull): - var botInfos: [CachedPeerBotInfo] = [] - for botInfo in chatFull.botInfo ?? [] { - switch botInfo { - case let .botInfo(userId, _, _): - let peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) - let parsedBotInfo = BotInfo(apiBotInfo: botInfo) - botInfos.append(CachedPeerBotInfo(peerId: peerId, botInfo: parsedBotInfo)) - } + var peers: [Peer] = [] + var peerPresences: [PeerId: PeerPresence] = [:] + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) } - let participants = CachedGroupParticipants(apiParticipants: chatFull.participants) - let exportedInvitation = ExportedInvitation(apiExportedInvite: chatFull.exportedInvite) - let pinnedMessageId = chatFull.pinnedMsgId.flatMap({ MessageId(peerId: peerId, namespace: Namespaces.Message.Cloud, id: $0) }) + } + for user in users { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + if let presence = TelegramUserPresence(apiUser: user) { + peerPresences[telegramUser.id] = presence + } + } - 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(transaction: transaction, peers: peers, update: { _, updated -> Peer in + return updated + }) + + updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences) + + var flags = CachedGroupFlags() + if (chatFull.flags & 1 << 7) != 0 { + flags.insert(.canChangeUsername) + } + + transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current in + let previous: CachedGroupData + if let current = current as? CachedGroupData { + previous = current + } else { + previous = CachedGroupData() } - updatePeers(transaction: transaction, peers: peers, update: { _, updated -> Peer in - return updated - }) - - updatePeerPresences(transaction: transaction, accountPeerId: accountPeerId, peerPresences: peerPresences) - - var flags = CachedGroupFlags() - if (chatFull.flags & 1 << 7) != 0 { - flags.insert(.canChangeUsername) - } - - transaction.updatePeerCachedData(peerIds: [peerId], update: { _, current in - let previous: CachedGroupData - if let current = current as? CachedGroupData { - previous = current - } else { - previous = CachedGroupData() - } - - return previous.withUpdatedParticipants(participants) - .withUpdatedExportedInvitation(exportedInvitation) - .withUpdatedBotInfos(botInfos) - .withUpdatedPinnedMessageId(pinnedMessageId) - .withUpdatedAbout(chatFull.about) - .withUpdatedFlags(flags) - }) - case .channelFull: - break - } - } + return previous.withUpdatedParticipants(participants) + .withUpdatedExportedInvitation(exportedInvitation) + .withUpdatedBotInfos(botInfos) + .withUpdatedPinnedMessageId(pinnedMessageId) + .withUpdatedAbout(chatFull.about) + .withUpdatedFlags(flags) + }) + case .channelFull: + break + } } } + } } else if let inputChannel = apiInputChannel(peer) { return network.request(Api.functions.channels.getFullChannel(channel: inputChannel)) |> map(Optional.init) @@ -254,7 +254,7 @@ func fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId: PeerId, network } switch fullChat { - case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId): + case let .channelFull(flags, _, about, participantsCount, adminsCount, kickedCount, bannedCount, _, _, _, _, _, _, apiExportedInvite, apiBotInfos, migratedFromChatId, migratedFromMaxId, pinnedMsgId, stickerSet, minAvailableMsgId, folderId, pts): var channelFlags = CachedChannelFlags() if (flags & (1 << 3)) != 0 { channelFlags.insert(.canDisplayParticipants) diff --git a/TelegramCore/UpdateGroup.swift b/TelegramCore/UpdateGroup.swift index 0ead75a144..e2f829ac05 100644 --- a/TelegramCore/UpdateGroup.swift +++ b/TelegramCore/UpdateGroup.swift @@ -61,7 +61,7 @@ func apiUpdatePtsRange(_ update: Api.Update) -> (Int32, Int32)? { return (pts, ptsCount) case let .updateNewMessage(_, pts, ptsCount): return (pts, ptsCount) - case let .updateReadHistoryInbox(_, _, pts, ptsCount): + case let .updateReadHistoryInbox(_, _, _, _, _, pts, ptsCount): return (pts, ptsCount) case let .updateReadHistoryOutbox(_, _, pts, ptsCount): return (pts, ptsCount) diff --git a/TelegramCore/UpdatePeers.swift b/TelegramCore/UpdatePeers.swift index bd2795d147..794236ef3b 100644 --- a/TelegramCore/UpdatePeers.swift +++ b/TelegramCore/UpdatePeers.swift @@ -9,8 +9,18 @@ func updatePeerChatInclusionWithMinTimestamp(transaction: Transaction, id: PeerI let currentInclusion = transaction.getPeerChatListInclusion(id) var updatedInclusion: PeerChatListInclusion? switch currentInclusion { - case .ifHasMessages, .ifHasMessagesOrOneOf: - updatedInclusion = currentInclusion.withSetIfHasMessagesOrMaxMinTimestamp(minTimestamp) + case let .ifHasMessagesOrOneOf(groupId, pinningIndex, currentMinTimestamp): + let updatedMinTimestamp: Int32 + if let currentMinTimestamp = currentMinTimestamp { + if minTimestamp > currentMinTimestamp { + updatedMinTimestamp = minTimestamp + } else { + updatedMinTimestamp = currentMinTimestamp + } + } else { + updatedMinTimestamp = minTimestamp + } + updatedInclusion = .ifHasMessagesOrOneOf(groupId: groupId, pinningIndex: pinningIndex, minTimestamp: updatedMinTimestamp) default: break } @@ -19,17 +29,13 @@ func updatePeerChatInclusionWithMinTimestamp(transaction: Transaction, id: PeerI } } -func updatePeerChatInclousionWithNewMessages(transaction: Transaction, id: PeerId) { - let currentInclusion = transaction.getPeerChatListInclusion(id) - var updatedInclusion: PeerChatListInclusion? - switch currentInclusion { - case .notSpecified: - updatedInclusion = .ifHasMessages - default: - break - } - if let updatedInclusion = updatedInclusion { - transaction.updatePeerChatListInclusion(id, inclusion: updatedInclusion) +func minTimestampForPeerInclusion(_ peer: Peer) -> Int32? { + if let group = peer as? TelegramGroup { + return group.creationDate + } else if let channel = peer as? TelegramChannel { + return channel.creationDate + } else { + return nil } } @@ -37,31 +43,19 @@ public func updatePeers(transaction: Transaction, peers: [Peer], update: (Peer?, transaction.updatePeersInternal(peers, update: { previous, updated in let peerId = updated.id - let currentInclusion = transaction.getPeerChatListInclusion(peerId) - var updatedInclusion: PeerChatListInclusion? switch peerId.namespace { case Namespaces.Peer.CloudUser: - if currentInclusion == .notSpecified { - updatedInclusion = .ifHasMessages - } + break case Namespaces.Peer.CloudGroup: if let group = updated as? TelegramGroup { if group.flags.contains(.deactivated) { - updatedInclusion = .never + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) } else { switch group.membership { case .Member: - if group.creationDate != 0 { - updatedInclusion = currentInclusion.withSetIfHasMessagesOrMaxMinTimestamp(group.creationDate) - } else { - if currentInclusion == .notSpecified { - updatedInclusion = .ifHasMessages - } - } + updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: peerId, minTimestamp: group.creationDate) default: - if currentInclusion == .notSpecified { - updatedInclusion = .never - } + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) } } } else { @@ -71,30 +65,20 @@ public func updatePeers(transaction: Transaction, peers: [Peer], update: (Peer?, if let channel = updated as? TelegramChannel { switch channel.participationStatus { case .member: - if channel.creationDate != 0 { - updatedInclusion = currentInclusion.withSetIfHasMessagesOrMaxMinTimestamp(channel.creationDate) - } else { - if currentInclusion == .notSpecified { - updatedInclusion = .ifHasMessages - } - } + updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: peerId, minTimestamp: channel.creationDate) case .left: - updatedInclusion = .never + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) case .kicked where channel.creationDate == 0: - updatedInclusion = .never + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) default: - if currentInclusion == .notSpecified { - updatedInclusion = .never - } + transaction.updatePeerChatListInclusion(peerId, inclusion: .notIncluded) } } else { assertionFailure() } case Namespaces.Peer.SecretChat: if let secretChat = updated as? TelegramSecretChat { - if currentInclusion == .notSpecified { - updatedInclusion = currentInclusion.withSetIfHasMessagesOrMaxMinTimestamp(secretChat.creationDate) - } + updatePeerChatInclusionWithMinTimestamp(transaction: transaction, id: peerId, minTimestamp: secretChat.creationDate) } else { assertionFailure() } @@ -102,9 +86,7 @@ public func updatePeers(transaction: Transaction, peers: [Peer], update: (Peer?, assertionFailure() break } - if let updatedInclusion = updatedInclusion { - transaction.updatePeerChatListInclusion(peerId, inclusion: updatedInclusion) - } + return update(previous, updated) }) } diff --git a/TelegramCore/UpdatesApiUtils.swift b/TelegramCore/UpdatesApiUtils.swift index 642e8fadb1..557472cedf 100644 --- a/TelegramCore/UpdatesApiUtils.swift +++ b/TelegramCore/UpdatesApiUtils.swift @@ -290,7 +290,7 @@ extension Api.Update { return apiMessagePeerIds(message) case let .updateEditMessage(message, _, _): return apiMessagePeerIds(message) - case let .updateReadChannelInbox(channelId, _): + case let .updateReadChannelInbox(_, _, channelId, _, _, _): return [PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId)] case let .updateNotifySettings(peer, _): switch peer {