diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 9c32fa5203..8df0117579 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -544,7 +544,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, }) }) }))) - if let filter = filters.first(where: { $0.id == id }), filter.data.includePeers.count < 100 { + if let filter = filters.first(where: { $0.id == id }), filter.data.includePeers.peers.count < 100 { items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.ChatList_AddChatsToFolder, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Add"), color: theme.contextMenu.primaryColor) }, action: { c, f in diff --git a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift index 150dcafa14..5b66db60ee 100644 --- a/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift +++ b/submodules/ChatListUI/Sources/ChatListFilterPresetController.swift @@ -543,7 +543,7 @@ private func internalChatListFilterAddChatsController(context: AccountContext, f } } - let controller = context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: context, mode: .chatSelection(title: presentationData.strings.ChatListFolder_IncludeChatsTitle, selectedChats: Set(filter.data.includePeers), additionalCategories: ContactMultiselectionControllerAdditionalCategories(categories: additionalCategories, selectedCategories: selectedCategories)), options: [], alwaysEnabled: true)) + let controller = context.sharedContext.makeContactMultiselectionController(ContactMultiselectionControllerParams(context: context, mode: .chatSelection(title: presentationData.strings.ChatListFolder_IncludeChatsTitle, selectedChats: Set(filter.data.includePeers.peers), additionalCategories: ContactMultiselectionControllerAdditionalCategories(categories: additionalCategories, selectedCategories: selectedCategories)), options: [], alwaysEnabled: true)) controller.navigationPresentation = .modal let _ = (controller.result |> take(1) @@ -579,8 +579,8 @@ private func internalChatListFilterAddChatsController(context: AccountContext, f for i in 0 ..< filters.count { if filters[i].id == filter.id { filters[i].data.categories = categories - filters[i].data.includePeers = includePeers - filters[i].data.excludePeers = filters[i].data.excludePeers.filter { !filters[i].data.includePeers.contains($0) } + filters[i].data.includePeers.setPeers(includePeers) + filters[i].data.excludePeers = filters[i].data.excludePeers.filter { !filters[i].data.includePeers.peers.contains($0) } } } return filters @@ -591,8 +591,8 @@ private func internalChatListFilterAddChatsController(context: AccountContext, f } else { var filter = filter filter.data.categories = categories - filter.data.includePeers = includePeers - filter.data.excludePeers = filter.data.excludePeers.filter { !filter.data.includePeers.contains($0) } + filter.data.includePeers.setPeers(includePeers) + filter.data.excludePeers = filter.data.excludePeers.filter { !filter.data.includePeers.peers.contains($0) } updated(filter) controller?.dismiss() } @@ -660,7 +660,7 @@ private func internalChatListFilterExcludeChatsController(context: AccountContex filters[i].data.excludeRead = additionalCategoryIds.contains(AdditionalExcludeCategoryId.read.rawValue) filters[i].data.excludeArchived = additionalCategoryIds.contains(AdditionalExcludeCategoryId.archived.rawValue) filters[i].data.excludePeers = excludePeers - filters[i].data.includePeers = filters[i].data.includePeers.filter { !filters[i].data.excludePeers.contains($0) } + filters[i].data.includePeers.setPeers(filters[i].data.includePeers.peers.filter { !filters[i].data.excludePeers.contains($0) }) } } return filters @@ -674,7 +674,7 @@ private func internalChatListFilterExcludeChatsController(context: AccountContex filter.data.excludeRead = additionalCategoryIds.contains(AdditionalExcludeCategoryId.read.rawValue) filter.data.excludeArchived = additionalCategoryIds.contains(AdditionalExcludeCategoryId.archived.rawValue) filter.data.excludePeers = excludePeers - filter.data.includePeers = filter.data.includePeers.filter { !filter.data.excludePeers.contains($0) } + filter.data.includePeers.setPeers(filter.data.includePeers.peers.filter { !filter.data.excludePeers.contains($0) }) updated(filter) controller?.dismiss() } @@ -695,7 +695,7 @@ enum ChatListFilterType { func chatListFilterType(_ filter: ChatListFilter) -> ChatListFilterType { let filterType: ChatListFilterType - if filter.data.includePeers.isEmpty { + if filter.data.includePeers.peers.isEmpty { if filter.data.categories == .all { if filter.data.excludeRead { filterType = .unread @@ -732,7 +732,7 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat } else { initialName = "" } - let initialState = ChatListFilterPresetControllerState(name: initialName, changedName: currentPreset != nil, includeCategories: currentPreset?.data.categories ?? [], excludeMuted: currentPreset?.data.excludeMuted ?? false, excludeRead: currentPreset?.data.excludeRead ?? false, excludeArchived: currentPreset?.data.excludeArchived ?? false, additionallyIncludePeers: currentPreset?.data.includePeers ?? [], additionallyExcludePeers: currentPreset?.data.excludePeers ?? []) + let initialState = ChatListFilterPresetControllerState(name: initialName, changedName: currentPreset != nil, includeCategories: currentPreset?.data.categories ?? [], excludeMuted: currentPreset?.data.excludeMuted ?? false, excludeRead: currentPreset?.data.excludeRead ?? false, excludeArchived: currentPreset?.data.excludeArchived ?? false, additionallyIncludePeers: currentPreset?.data.includePeers.peers ?? [], additionallyExcludePeers: currentPreset?.data.excludePeers ?? []) let stateValue = Atomic(value: initialState) let statePromise = ValuePromise(initialState, ignoreRepeated: true) let updateState: ((ChatListFilterPresetControllerState) -> ChatListFilterPresetControllerState) -> Void = { f in @@ -740,7 +740,9 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat var state = f(current) if !state.changedName { let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: state.additionallyIncludePeers, excludePeers: state.additionallyExcludePeers, pinnedPeers: currentPreset?.data.pinnedPeers ?? [])) + var includePeers = ChatListFilterIncludePeers() + includePeers.setPeers(state.additionallyIncludePeers) + let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) switch chatListFilterType(filter) { case .generic: state.name = initialName @@ -781,13 +783,15 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat }, openAddIncludePeer: { let state = stateValue.with { $0 } - let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: state.additionallyIncludePeers, excludePeers: state.additionallyExcludePeers, pinnedPeers: currentPreset?.data.pinnedPeers ?? [])) + var includePeers = ChatListFilterIncludePeers() + includePeers.setPeers(state.additionallyIncludePeers) + let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) let controller = internalChatListFilterAddChatsController(context: context, filter: filter, applyAutomatically: false, updated: { filter in skipStateAnimation = true updateState { state in var state = state - state.additionallyIncludePeers = filter.data.includePeers + state.additionallyIncludePeers = filter.data.includePeers.peers state.additionallyExcludePeers = filter.data.excludePeers state.includeCategories = filter.data.categories return state @@ -797,13 +801,15 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat }, openAddExcludePeer: { let state = stateValue.with { $0 } - let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: state.additionallyIncludePeers, excludePeers: state.additionallyExcludePeers, pinnedPeers: currentPreset?.data.pinnedPeers ?? [])) + var includePeers = ChatListFilterIncludePeers() + includePeers.setPeers(state.additionallyIncludePeers) + let filter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) let controller = internalChatListFilterExcludeChatsController(context: context, filter: filter, applyAutomatically: false, updated: { filter in skipStateAnimation = true updateState { state in var state = state - state.additionallyIncludePeers = filter.data.includePeers + state.additionallyIncludePeers = filter.data.includePeers.peers state.additionallyExcludePeers = filter.data.excludePeers state.includeCategories = filter.data.categories state.excludeRead = filter.data.excludeRead @@ -918,32 +924,36 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat var attemptNavigationImpl: (() -> Bool)? var applyImpl: (() -> Void)? = { let state = stateValue.with { $0 } - let preset = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: state.additionallyIncludePeers, excludePeers: state.additionallyExcludePeers, pinnedPeers: currentPreset?.data.pinnedPeers ?? [])) let _ = (updateChatListFiltersInteractively(postbox: context.account.postbox, { filters in - var preset = preset + var includePeers = ChatListFilterIncludePeers() + includePeers.setPeers(state.additionallyIncludePeers) + var updatedFilter = ChatListFilter(id: currentPreset?.id ?? -1, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) if currentPreset == nil { - preset.id = max(2, filters.map({ $0.id + 1 }).max() ?? 2) + updatedFilter.id = max(2, filters.map({ $0.id + 1 }).max() ?? 2) } var filters = filters if let _ = currentPreset { var found = false for i in 0 ..< filters.count { - if filters[i].id == preset.id { - filters[i] = preset + if filters[i].id == updatedFilter.id { + var includePeers = filters[i].data.includePeers + includePeers.setPeers(state.additionallyIncludePeers) + updatedFilter.data.includePeers = includePeers + filters[i] = updatedFilter found = true } } if !found { filters = filters.filter { listFilter in - if listFilter.title == preset.title && listFilter.data == preset.data { + if listFilter.title == updatedFilter.title && listFilter.data == updatedFilter.data { return false } return true } - filters.append(preset) + filters.append(updatedFilter) } } else { - filters.append(preset) + filters.append(updatedFilter) } return filters }) @@ -1013,8 +1023,15 @@ func chatListFilterPresetController(context: AccountContext, currentPreset: Chat attemptNavigationImpl = { let state = stateValue.with { $0 } if let currentPreset = currentPreset { - let filter = ChatListFilter(id: currentPreset.id, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: state.additionallyIncludePeers, excludePeers: state.additionallyExcludePeers, pinnedPeers: currentPreset.data.pinnedPeers)) - if currentPreset != filter { + var currentPresetWithoutPinnerPeers = currentPreset + var currentIncludePeers = ChatListFilterIncludePeers() + currentIncludePeers.setPeers(currentPresetWithoutPinnerPeers.data.includePeers.peers) + currentPresetWithoutPinnerPeers.data.includePeers = currentIncludePeers + + var includePeers = ChatListFilterIncludePeers() + includePeers.setPeers(state.additionallyIncludePeers) + let filter = ChatListFilter(id: currentPreset.id, title: state.name, data: ChatListFilterData(categories: state.includeCategories, excludeMuted: state.excludeMuted, excludeRead: state.excludeRead, excludeArchived: state.excludeArchived, includePeers: includePeers, excludePeers: state.additionallyExcludePeers)) + if currentPresetWithoutPinnerPeers != filter { displaySaveAlert() return false } diff --git a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift index aa1f93f5d9..2563a1f4d2 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNodeLocation.swift @@ -30,12 +30,12 @@ struct ChatListNodeViewUpdate { } func chatListFilterPredicate(filter: ChatListFilterData) -> ChatListFilterPredicate { - var includePeers = Set(filter.includePeers) + var includePeers = Set(filter.includePeers.peers) var excludePeers = Set(filter.excludePeers) - if !filter.pinnedPeers.isEmpty { - includePeers.subtract(filter.pinnedPeers) - excludePeers.subtract(filter.pinnedPeers) + if !filter.includePeers.pinnedPeers.isEmpty { + includePeers.subtract(filter.includePeers.pinnedPeers) + excludePeers.subtract(filter.includePeers.pinnedPeers) } var includeAdditionalPeerGroupIds: [PeerGroupId] = [] @@ -47,7 +47,7 @@ func chatListFilterPredicate(filter: ChatListFilterData) -> ChatListFilterPredic if filter.excludeRead { messageTagSummary = ChatListMessageTagSummaryResultCalculation(addCount: ChatListMessageTagSummaryResultComponent(tag: .unseenPersonalMessage, namespace: Namespaces.Message.Cloud), subtractCount: ChatListMessageTagActionsSummaryResultComponent(type: PendingMessageActionType.consumeUnseenPersonalMessage, namespace: Namespaces.Message.Cloud)) } - return ChatListFilterPredicate(includePeerIds: includePeers, excludePeerIds: excludePeers, pinnedPeerIds: filter.pinnedPeers, messageTagSummary: messageTagSummary, includeAdditionalPeerGroupIds: includeAdditionalPeerGroupIds, include: { peer, isMuted, isUnread, isContact, messageTagSummaryResult in + return ChatListFilterPredicate(includePeerIds: includePeers, excludePeerIds: excludePeers, pinnedPeerIds: filter.includePeers.pinnedPeers, messageTagSummary: messageTagSummary, includeAdditionalPeerGroupIds: includeAdditionalPeerGroupIds, include: { peer, isMuted, isUnread, isContact, messageTagSummaryResult in if filter.excludeRead { var effectiveUnread = isUnread if let messageTagSummaryResult = messageTagSummaryResult, messageTagSummaryResult { diff --git a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift index 5d3afcdd2a..45aa92b7db 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListViewTransition.swift @@ -189,11 +189,10 @@ func preparedChatListNodeViewTransition(from fromView: ChatListNodeView?, to toV } } else if fromView.filteredEntries.isEmpty || fromView.filter != toView.filter { var updateEmpty = true - if !fromView.filteredEntries.isEmpty, let fromFilter = fromView.filter, let toFilter = toView.filter, fromFilter.data.pinnedPeers != toFilter.data.pinnedPeers { + if !fromView.filteredEntries.isEmpty, let fromFilter = fromView.filter, let toFilter = toView.filter, fromFilter.data.includePeers.pinnedPeers != toFilter.data.includePeers.pinnedPeers { var fromData = fromFilter.data - var toData = toFilter.data - fromData.pinnedPeers = [] - toData.pinnedPeers = [] + let toData = toFilter.data + fromData.includePeers = toData.includePeers if fromData == toData { options.insert(.AnimateInsertion) updateEmpty = false diff --git a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift index 0c469181cc..e8ad3f2e61 100644 --- a/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift +++ b/submodules/ChatListUI/Sources/TabBarChatListFilterController.swift @@ -19,7 +19,7 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt var additionalPeerIds = Set() var additionalGroupIds = Set() for filter in filters { - additionalPeerIds.formUnion(filter.data.includePeers) + additionalPeerIds.formUnion(filter.data.includePeers.peers) additionalPeerIds.formUnion(filter.data.excludePeers) if !filter.data.excludeArchived { additionalGroupIds.insert(Namespaces.PeerGroup.archive) @@ -146,7 +146,7 @@ func chatListFilterItems(context: AccountContext) -> Signal<(Int, [(ChatListFilt } } } - for peerId in filter.data.includePeers { + for peerId in filter.data.includePeers.peers { if let (tag, peerCount, hasUnmuted) = peerTagAndCount[peerId] { if !tags.contains(tag) { if peerCount != 0 { diff --git a/submodules/TelegramCore/Sources/ChatListFiltering.swift b/submodules/TelegramCore/Sources/ChatListFiltering.swift index 734d4ed0fd..e714c898c7 100644 --- a/submodules/TelegramCore/Sources/ChatListFiltering.swift +++ b/submodules/TelegramCore/Sources/ChatListFiltering.swift @@ -96,23 +96,78 @@ extension ChatListFilterPeerCategories { } } +public struct ChatListFilterIncludePeers: Equatable, Hashable { + public private(set) var peers: [PeerId] + public private(set) var pinnedPeers: [PeerId] + + public init() { + self.peers = [] + self.pinnedPeers = [] + } + + init(peers: [PeerId], pinnedPeers: [PeerId]) { + self.peers = peers + self.pinnedPeers = pinnedPeers + } + + public mutating func reorderPinnedPeers(_ pinnedPeers: [PeerId]) { + if Set(self.pinnedPeers) == Set(pinnedPeers) { + self.pinnedPeers = pinnedPeers + } + } + + public mutating func addPinnedPeer(_ peerId: PeerId) -> Bool { + if self.pinnedPeers.contains(peerId) { + return false + } + if self.peers.contains(peerId) { + self.pinnedPeers.insert(peerId, at: 0) + return true + } else { + if self.peers.count < 100 { + self.peers.insert(peerId, at: 0) + self.pinnedPeers.insert(peerId, at: 0) + return true + } else { + return false + } + } + } + + public mutating func removePinnedPeer(_ peerId: PeerId) { + if self.pinnedPeers.contains(peerId) { + self.pinnedPeers.removeAll(where: { $0 == peerId }) + } + } + + public mutating func setPeers(_ peers: [PeerId]) { + self.peers = peers + self.pinnedPeers = self.pinnedPeers.filter { peers.contains($0) } + } +} + +extension ChatListFilterIncludePeers { + init(rawPeers: [PeerId], rawPinnedPeers: [PeerId]) { + self.peers = rawPinnedPeers + rawPeers.filter { !rawPinnedPeers.contains($0) } + self.pinnedPeers = rawPinnedPeers + } +} + public struct ChatListFilterData: Equatable, Hashable { public var categories: ChatListFilterPeerCategories public var excludeMuted: Bool public var excludeRead: Bool public var excludeArchived: Bool - public var includePeers: [PeerId] + public var includePeers: ChatListFilterIncludePeers public var excludePeers: [PeerId] - public var pinnedPeers: [PeerId] public init( categories: ChatListFilterPeerCategories, excludeMuted: Bool, excludeRead: Bool, excludeArchived: Bool, - includePeers: [PeerId], - excludePeers: [PeerId], - pinnedPeers: [PeerId] + includePeers: ChatListFilterIncludePeers, + excludePeers: [PeerId] ) { self.categories = categories self.excludeMuted = excludeMuted @@ -120,7 +175,6 @@ public struct ChatListFilterData: Equatable, Hashable { self.excludeArchived = excludeArchived self.includePeers = includePeers self.excludePeers = excludePeers - self.pinnedPeers = pinnedPeers } } @@ -147,9 +201,8 @@ public struct ChatListFilter: PostboxCoding, Equatable { excludeMuted: decoder.decodeInt32ForKey("excludeMuted", orElse: 0) != 0, excludeRead: decoder.decodeInt32ForKey("excludeRead", orElse: 0) != 0, excludeArchived: decoder.decodeInt32ForKey("excludeArchived", orElse: 0) != 0, - includePeers: decoder.decodeInt64ArrayForKey("includePeers").map(PeerId.init), - excludePeers: decoder.decodeInt64ArrayForKey("excludePeers").map(PeerId.init), - pinnedPeers: decoder.decodeInt64ArrayForKey("pinnedPeers").map(PeerId.init) + includePeers: ChatListFilterIncludePeers(peers: decoder.decodeInt64ArrayForKey("includePeers").map(PeerId.init), pinnedPeers: decoder.decodeInt64ArrayForKey("pinnedPeers").map(PeerId.init)), + excludePeers: decoder.decodeInt64ArrayForKey("excludePeers").map(PeerId.init) ) } @@ -160,9 +213,9 @@ public struct ChatListFilter: PostboxCoding, Equatable { encoder.encodeInt32(self.data.excludeMuted ? 1 : 0, forKey: "excludeMuted") encoder.encodeInt32(self.data.excludeRead ? 1 : 0, forKey: "excludeRead") encoder.encodeInt32(self.data.excludeArchived ? 1 : 0, forKey: "excludeArchived") - encoder.encodeInt64Array(self.data.includePeers.map { $0.toInt64() }, forKey: "includePeers") + encoder.encodeInt64Array(self.data.includePeers.peers.map { $0.toInt64() }, forKey: "includePeers") + encoder.encodeInt64Array(self.data.includePeers.pinnedPeers.map { $0.toInt64() }, forKey: "pinnedPeers") encoder.encodeInt64Array(self.data.excludePeers.map { $0.toInt64() }, forKey: "excludePeers") - encoder.encodeInt64Array(self.data.pinnedPeers.map { $0.toInt64() }, forKey: "pinnedPeers") } } @@ -178,7 +231,7 @@ extension ChatListFilter { excludeMuted: (flags & (1 << 11)) != 0, excludeRead: (flags & (1 << 12)) != 0, excludeArchived: (flags & (1 << 13)) != 0, - includePeers: includePeers.compactMap { peer -> PeerId? in + includePeers: ChatListFilterIncludePeers(rawPeers: includePeers.compactMap { peer -> PeerId? in switch peer { case let .inputPeerUser(userId, _): return PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) @@ -189,7 +242,18 @@ extension ChatListFilter { default: return nil } - }, + }, rawPinnedPeers: pinnedPeers.compactMap { peer -> PeerId? in + switch peer { + case let .inputPeerUser(userId, _): + return PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) + case let .inputPeerChat(chatId): + return PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) + case let .inputPeerChannel(channelId, _): + return PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) + default: + return nil + } + }), excludePeers: excludePeers.compactMap { peer -> PeerId? in switch peer { case let .inputPeerUser(userId, _): @@ -201,18 +265,6 @@ extension ChatListFilter { default: return nil } - }, - pinnedPeers: pinnedPeers.compactMap { peer -> PeerId? in - switch peer { - case let .inputPeerUser(userId, _): - return PeerId(namespace: Namespaces.Peer.CloudUser, id: userId) - case let .inputPeerChat(chatId): - return PeerId(namespace: Namespaces.Peer.CloudGroup, id: chatId) - case let .inputPeerChannel(channelId, _): - return PeerId(namespace: Namespaces.Peer.CloudChannel, id: channelId) - default: - return nil - } } ) ) @@ -231,9 +283,12 @@ extension ChatListFilter { flags |= 1 << 13 } flags |= self.data.categories.apiFlags - return .dialogFilter(flags: flags, id: self.id, title: self.title, pinnedPeers: self.data.pinnedPeers.compactMap { peerId -> Api.InputPeer? in + return .dialogFilter(flags: flags, id: self.id, title: self.title, pinnedPeers: self.data.includePeers.pinnedPeers.compactMap { peerId -> Api.InputPeer? in return transaction.getPeer(peerId).flatMap(apiInputPeer) - }, includePeers: self.data.includePeers.compactMap { peerId -> Api.InputPeer? in + }, includePeers: self.data.includePeers.peers.compactMap { peerId -> Api.InputPeer? in + if self.data.includePeers.pinnedPeers.contains(peerId) { + return nil + } return transaction.getPeer(peerId).flatMap(apiInputPeer) }, excludePeers: self.data.excludePeers.compactMap { peerId -> Api.InputPeer? in return transaction.getPeer(peerId).flatMap(apiInputPeer) @@ -436,7 +491,9 @@ private func requestChatListFilters(postbox: Postbox, network: Network) -> Signa ) |> castError(RequestChatListFiltersError.self) |> mapToSignal { _ -> Signal<[ChatListFilter], RequestChatListFiltersError> in + #if swift(<5) return .complete() + #endif } |> then( .single(filters) @@ -593,9 +650,8 @@ public struct ChatListFeaturedFilter: PostboxCoding, Equatable { excludeMuted: decoder.decodeInt32ForKey("excludeMuted", orElse: 0) != 0, excludeRead: decoder.decodeInt32ForKey("excludeRead", orElse: 0) != 0, excludeArchived: decoder.decodeInt32ForKey("excludeArchived", orElse: 0) != 0, - includePeers: decoder.decodeInt64ArrayForKey("includePeers").map(PeerId.init), - excludePeers: decoder.decodeInt64ArrayForKey("excludePeers").map(PeerId.init), - pinnedPeers: decoder.decodeInt64ArrayForKey("pinnedPeers").map(PeerId.init) + includePeers: ChatListFilterIncludePeers(peers: decoder.decodeInt64ArrayForKey("includePeers").map(PeerId.init), pinnedPeers: decoder.decodeInt64ArrayForKey("pinnedPeers").map(PeerId.init)), + excludePeers: decoder.decodeInt64ArrayForKey("excludePeers").map(PeerId.init) ) } @@ -606,9 +662,9 @@ public struct ChatListFeaturedFilter: PostboxCoding, Equatable { encoder.encodeInt32(self.data.excludeMuted ? 1 : 0, forKey: "excludeMuted") encoder.encodeInt32(self.data.excludeRead ? 1 : 0, forKey: "excludeRead") encoder.encodeInt32(self.data.excludeArchived ? 1 : 0, forKey: "excludeArchived") - encoder.encodeInt64Array(self.data.includePeers.map { $0.toInt64() }, forKey: "includePeers") + encoder.encodeInt64Array(self.data.includePeers.peers.map { $0.toInt64() }, forKey: "includePeers") + encoder.encodeInt64Array(self.data.includePeers.pinnedPeers.map { $0.toInt64() }, forKey: "pinnedPeers") encoder.encodeInt64Array(self.data.excludePeers.map { $0.toInt64() }, forKey: "excludePeers") - encoder.encodeInt64Array(self.data.pinnedPeers.map { $0.toInt64() }, forKey: "pinnedPeers") } } diff --git a/submodules/TelegramCore/Sources/TogglePeerChatPinned.swift b/submodules/TelegramCore/Sources/TogglePeerChatPinned.swift index d149ead231..ab3a0de39e 100644 --- a/submodules/TelegramCore/Sources/TogglePeerChatPinned.swift +++ b/submodules/TelegramCore/Sources/TogglePeerChatPinned.swift @@ -65,12 +65,10 @@ public func toggleItemPinned(postbox: Postbox, location: TogglePeerChatPinnedLoc if let index = filters.firstIndex(where: { $0.id == filterId }) { switch itemId { case let .peer(peerId): - if filters[index].data.pinnedPeers.contains(peerId) { - filters[index].data.pinnedPeers.removeAll(where: { $0 == peerId }) + if filters[index].data.includePeers.pinnedPeers.contains(peerId) { + filters[index].data.includePeers.removePinnedPeer(peerId) } else { - if filters[index].data.pinnedPeers.count < 100 { - filters[index].data.pinnedPeers.insert(peerId, at: 0) - } else { + if !filters[index].data.includePeers.addPinnedPeer(peerId) { result = .limitExceeded(100) } } @@ -91,7 +89,7 @@ public func getPinnedItemIds(transaction: Transaction, location: TogglePeerChatP var itemIds: [PinnedItemId] = [] let _ = updateChatListFiltersInteractively(transaction: transaction, { filters in if let index = filters.firstIndex(where: { $0.id == filterId }) { - itemIds = filters[index].data.pinnedPeers.map { peerId in + itemIds = filters[index].data.includePeers.pinnedPeers.map { peerId in return .peer(peerId) } } @@ -123,8 +121,8 @@ public func reorderPinnedItemIds(transaction: Transaction, location: TogglePeerC } } - if filters[index].data.pinnedPeers != peerIds { - filters[index].data.pinnedPeers = peerIds + if filters[index].data.includePeers.pinnedPeers != peerIds { + filters[index].data.includePeers.reorderPinnedPeers(peerIds) result = true } }