diff --git a/TelegramCore/AccountStateManagementUtils.swift b/TelegramCore/AccountStateManagementUtils.swift index f4265df6f1..52b6131b0e 100644 --- a/TelegramCore/AccountStateManagementUtils.swift +++ b/TelegramCore/AccountStateManagementUtils.swift @@ -1320,7 +1320,14 @@ private func resetChannels(_ account: Account, peers: [Peer], state: AccountMuta } } return account.network.request(Api.functions.messages.getPeerDialogs(peers: inputPeers)) - |> retryRequest + |> map(Optional.init) + |> `catch` { error -> Signal in + if error.errorDescription == "CHANNEL_PRIVATE" && inputPeers.count == 1 { + return .single(nil) + } else { + return .single(nil) + } + } |> map { result -> AccountMutableState in var updatedState = state @@ -1333,74 +1340,76 @@ private func resetChannels(_ account: Account, peers: [Peer], state: AccountMuta var channelStates: [PeerId: ChannelState] = [:] var notificationSettings: [PeerId: PeerNotificationSettings] = [:] - switch result { - case let .peerDialogs(dialogs, messages, chats, users, _): - dialogsChats.append(contentsOf: chats) - dialogsUsers.append(contentsOf: users) - - loop: for dialog in dialogs { - let apiPeer: Api.Peer - let apiReadInboxMaxId: Int32 - let apiReadOutboxMaxId: Int32 - let apiTopMessage: Int32 - let apiUnreadCount: Int32 - let apiUnreadMentionsCount: Int32 - var apiChannelPts: Int32? - let apiNotificationSettings: Api.PeerNotifySettings - switch dialog { - case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, peerNotificationSettings, pts, _): - apiPeer = peer - apiTopMessage = topMessage - apiReadInboxMaxId = readInboxMaxId - apiReadOutboxMaxId = readOutboxMaxId - apiUnreadCount = unreadCount - apiUnreadMentionsCount = unreadMentionsCount - apiNotificationSettings = peerNotificationSettings - apiChannelPts = pts - case .dialogFeed: - assertionFailure() - continue loop - } + if let result = result { + switch result { + case let .peerDialogs(dialogs, messages, chats, users, _): + dialogsChats.append(contentsOf: chats) + dialogsUsers.append(contentsOf: users) - let peerId: PeerId - switch apiPeer { - case let .peerUser(userId): - peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) - case let .peerChat(chatId): - peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) - case let .peerChannel(channelId): - peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) - } - - if readStates[peerId] == nil { - readStates[peerId] = [:] - } - readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount) - - if apiTopMessage != 0 { - mentionTagSummaries[peerId] = MessageHistoryTagNamespaceSummary(version: 1, count: apiUnreadMentionsCount, range: MessageHistoryTagNamespaceCountValidityRange(maxId: apiTopMessage)) - } - - if let apiChannelPts = apiChannelPts { - channelStates[peerId] = ChannelState(pts: apiChannelPts, invalidatedPts: apiChannelPts) - } - - notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings) - } - - 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) - } + loop: for dialog in dialogs { + let apiPeer: Api.Peer + let apiReadInboxMaxId: Int32 + let apiReadOutboxMaxId: Int32 + let apiTopMessage: Int32 + let apiUnreadCount: Int32 + let apiUnreadMentionsCount: Int32 + var apiChannelPts: Int32? + let apiNotificationSettings: Api.PeerNotifySettings + switch dialog { + case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, peerNotificationSettings, pts, _): + apiPeer = peer + apiTopMessage = topMessage + apiReadInboxMaxId = readInboxMaxId + apiReadOutboxMaxId = readOutboxMaxId + apiUnreadCount = unreadCount + apiUnreadMentionsCount = unreadMentionsCount + apiNotificationSettings = peerNotificationSettings + apiChannelPts = pts + case .dialogFeed: + assertionFailure() + continue loop } - storeMessages.append(updatedStoreMessage) + + let peerId: PeerId + switch apiPeer { + case let .peerUser(userId): + peerId = PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + case let .peerChat(chatId): + peerId = PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) + case let .peerChannel(channelId): + peerId = PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + } + + if readStates[peerId] == nil { + readStates[peerId] = [:] + } + readStates[peerId]![Namespaces.Message.Cloud] = .idBased(maxIncomingReadId: apiReadInboxMaxId, maxOutgoingReadId: apiReadOutboxMaxId, maxKnownId: apiTopMessage, count: apiUnreadCount) + + if apiTopMessage != 0 { + mentionTagSummaries[peerId] = MessageHistoryTagNamespaceSummary(version: 1, count: apiUnreadMentionsCount, range: MessageHistoryTagNamespaceCountValidityRange(maxId: apiTopMessage)) + } + + if let apiChannelPts = apiChannelPts { + channelStates[peerId] = ChannelState(pts: apiChannelPts, invalidatedPts: apiChannelPts) + } + + notificationSettings[peerId] = TelegramPeerNotificationSettings(apiSettings: apiNotificationSettings) } - } + + 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) + } + } + } } updatedState.mergeChats(dialogsChats) @@ -1776,10 +1785,16 @@ func replayFinalState(accountPeerId: PeerId, mediaBox: MediaBox, modifier: Modif modifier.deleteMessagesInRange(peerId: id.peerId, namespace: id.namespace, minId: 1, maxId: id.id) case let .EditMessage(id, message): modifier.updateMessage(id, update: { previousMessage in + var updatedFlags = message.flags var updatedLocalTags = message.localTags if previousMessage.localTags.contains(.OutgoingLiveLocation) { updatedLocalTags.insert(.OutgoingLiveLocation) } + if message.flags.contains(.Incoming) { + updatedFlags.insert(.Incoming) + } else { + updatedFlags.remove(.Incoming) + } return .update(message.withUpdatedLocalTags(updatedLocalTags)) }) case let .UpdateMedia(id, media): diff --git a/TelegramCore/ChannelAdminEventLogs.swift b/TelegramCore/ChannelAdminEventLogs.swift index 8a5944f6cb..7877236a3c 100644 --- a/TelegramCore/ChannelAdminEventLogs.swift +++ b/TelegramCore/ChannelAdminEventLogs.swift @@ -10,15 +10,15 @@ public typealias AdminLogEventId = Int64 public struct AdminLogEvent { public let id: AdminLogEventId - public let peerId:PeerId - public let date:Int32 + public let peerId: PeerId + public let date: Int32 public let action: AdminLogEventAction } public struct AdminLogEventsResult { public let peerId: PeerId - public let peers:[PeerId: Peer] - public let events:[AdminLogEvent] + public let peers: [PeerId: Peer] + public let events: [AdminLogEvent] } public enum AdminLogEventAction { @@ -29,7 +29,7 @@ public enum AdminLogEventAction { case toggleInvites(Bool) case toggleSignatures(Bool) case updatePinned(Message?) - case editMessage(prev: Message, new:Message) + case editMessage(prev: Message, new: Message) case deleteMessage(Message) case participantJoin case participantLeave @@ -69,24 +69,24 @@ public struct AdminLogEventsFlags : OptionSet { public static let editMessages = AdminLogEventsFlags(rawValue: 1 << 12) public static let deleteMessages = AdminLogEventsFlags(rawValue: 1 << 13) - public static var all:[AdminLogEventsFlags] { + public static var all: [AdminLogEventsFlags] { return [.join, .leave, .invite, .ban, .unban, .kick, .unkick, .promote, .demote, .info, .settings, .pinnedMessages, .editMessages, .deleteMessages] } - public static var flags:AdminLogEventsFlags { + public static var flags: AdminLogEventsFlags { return [.join, .leave, .invite, .ban, .unban, .kick, .unkick, .promote, .demote, .info, .settings, .pinnedMessages, .editMessages, .deleteMessages] } } private func boolFromApiValue(_ value: Api.Bool) -> Bool { switch value { - case .boolFalse: - return false - case .boolTrue: - return true + case .boolFalse: + return false + case .boolTrue: + return true } } -public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId:AdminLogEventId, minId:AdminLogEventId, limit:Int32 = 100, query:String? = nil, filter:AdminLogEventsFlags? = nil, admins:[PeerId]? = nil) -> Signal { +public func channelAdminLogEvents(_ account:Account, peerId:PeerId, maxId: AdminLogEventId, minId: AdminLogEventId, limit: Int32 = 100, query: String? = nil, filter: AdminLogEventsFlags? = nil, admins: [PeerId]? = nil) -> Signal { return account.postbox.modify { modifier -> (Peer?, [Peer]?) in return (modifier.getPeer(peerId), admins?.flatMap {modifier.getPeer($0)}) diff --git a/TelegramCore/HistoryViewChannelStateValidation.swift b/TelegramCore/HistoryViewChannelStateValidation.swift index 6fad7c9873..9df16c6de2 100644 --- a/TelegramCore/HistoryViewChannelStateValidation.swift +++ b/TelegramCore/HistoryViewChannelStateValidation.swift @@ -132,7 +132,7 @@ final class HistoryViewChannelStateValidationContexts { } } - if !addedRanges.isEmpty && addedRanges[rangesToInvalidate.count - 1].isEmpty { + if !addedRanges.isEmpty && addedRanges[addedRanges.count - 1].isEmpty { addedRanges.removeLast() } @@ -318,7 +318,7 @@ private func validateBatch(postbox: Postbox, network: Network, messageIds: [Mess } } attributes.append(ChannelMessageStateVersionAttribute(pts: validatePts)) - return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: [.Failed], tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) + return .update(StoreMessage(id: currentMessage.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) }) } return @@ -380,7 +380,7 @@ private func validateBatch(postbox: Postbox, network: Network, messageIds: [Mess } attributes.append(ChannelMessageStateVersionAttribute(pts: channelPts)) } - return .update(StoreMessage(id: message.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: [.Failed], tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) + return .update(StoreMessage(id: message.id, globallyUniqueId: currentMessage.globallyUniqueId, groupingKey: currentMessage.groupingKey, timestamp: currentMessage.timestamp, flags: StoreMessageFlags(currentMessage.flags), tags: currentMessage.tags, globalTags: currentMessage.globalTags, localTags: currentMessage.localTags, forwardInfo: storeForwardInfo, authorId: currentMessage.author?.id, text: currentMessage.text, attributes: attributes, media: currentMessage.media)) } }) } diff --git a/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift b/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift index 4055e80c56..a548513889 100644 --- a/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift +++ b/TelegramCore/ManagedSynchronizePinnedChatsOperations.swift @@ -119,8 +119,8 @@ private func synchronizePinnedChats(modifier: Modifier, postbox: Postbox, networ switch item { case let .peer(peerId): return peerId.namespace != Namespaces.Peer.SecretChat - case .group: - return false + default: + return true } } let localItemIds = modifier.getPinnedItemIds() @@ -128,17 +128,14 @@ private func synchronizePinnedChats(modifier: Modifier, postbox: Postbox, networ switch item { case let .peer(peerId): return peerId.namespace != Namespaces.Peer.SecretChat - case .group: - return false + default: + return true } } return network.request(Api.functions.messages.getPinnedDialogs()) |> retryRequest |> mapToSignal { dialogs -> Signal in - let dialogsChats: [Api.Chat] - let dialogsUsers: [Api.User] - var storeMessages: [StoreMessage] = [] var readStates: [PeerId: [MessageId.Namespace: PeerReadState]] = [:] var chatStates: [PeerId: PeerChatState] = [:] @@ -146,10 +143,27 @@ private func synchronizePinnedChats(modifier: Modifier, postbox: Postbox, networ var remoteItemIds: [PinnedItemId] = [] + var peers: [Peer] = [] + var peerPresences: [PeerId: PeerPresence] = [:] + switch dialogs { case let .peerDialogs(dialogs, messages, chats, users, _): - dialogsChats = chats - dialogsUsers = users + var channelGroupIds: [PeerId: PeerGroupId] = [:] + for chat in chats { + if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { + peers.append(groupOrChannel) + if let channel = groupOrChannel as? TelegramChannel, let peerGroupId = channel.peerGroupId { + channelGroupIds[channel.id] = peerGroupId + } + } + } + for user in users { + let telegramUser = TelegramUser(user: user) + peers.append(telegramUser) + if let presence = TelegramUserPresence(apiUser: user) { + peerPresences[telegramUser.id] = presence + } + } loop: for dialog in dialogs { let apiPeer: Api.Peer @@ -161,6 +175,9 @@ private func synchronizePinnedChats(modifier: Modifier, postbox: Postbox, networ let apiNotificationSettings: Api.PeerNotifySettings switch dialog { case let .dialog(_, peer, topMessage, readInboxMaxId, readOutboxMaxId, unreadCount, unreadMentionsCount, peerNotificationSettings, pts, _): + if channelGroupIds[peer.peerId] != nil { + continue loop + } apiPeer = peer apiTopMessage = topMessage apiReadInboxMaxId = readInboxMaxId @@ -204,21 +221,6 @@ private func synchronizePinnedChats(modifier: Modifier, postbox: Postbox, networ } } - var peers: [Peer] = [] - var peerPresences: [PeerId: PeerPresence] = [:] - for chat in dialogsChats { - if let groupOrChannel = parseTelegramGroupOrChannel(chat: chat) { - peers.append(groupOrChannel) - } - } - for user in dialogsUsers { - let telegramUser = TelegramUser(user: user) - peers.append(telegramUser) - if let presence = TelegramUserPresence(apiUser: user) { - peerPresences[telegramUser.id] = presence - } - } - let locallyRemovedFromRemoteItemIds = Set(initialRemoteItemIdsWithoutSecretChats).subtracting(Set(localItemIdsWithoutSecretChats)) let remotelyRemovedItemIds = Set(initialRemoteItemIdsWithoutSecretChats).subtracting(Set(remoteItemIds))