Various improvements

This commit is contained in:
Ilya Laktyushin
2022-05-23 05:36:59 +04:00
parent 585838b455
commit 04dd7a6ee0
3 changed files with 71 additions and 30 deletions

View File

@@ -154,7 +154,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
private var searchContentNode: NavigationBarSearchContentNode? private var searchContentNode: NavigationBarSearchContentNode?
private let tabContainerNode: ChatListFilterTabContainerNode private let tabContainerNode: ChatListFilterTabContainerNode
private var tabContainerData: ([ChatListFilterTabEntry], Bool)? private var tabContainerData: ([ChatListFilterTabEntry], Bool, Int32?)?
private var hasDownloads: Bool = false private var hasDownloads: Bool = false
private var activeDownloadsDisposable: Disposable? private var activeDownloadsDisposable: Disposable?
@@ -764,7 +764,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.tabContainerNode.cancelAnimations() strongSelf.tabContainerNode.cancelAnimations()
strongSelf.chatListDisplayNode.inlineTabContainerNode.cancelAnimations() strongSelf.chatListDisplayNode.inlineTabContainerNode.cancelAnimations()
} }
strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: strongSelf.isPremium, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition) strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: strongSelf.isPremium, filtersLimit: tabContainerData.2, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition)
strongSelf.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition) strongSelf.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition)
} }
self.reloadFilters() self.reloadFilters()
@@ -835,7 +835,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData))
if let layout = self.validLayout { if let layout = self.validLayout {
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate) self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, filtersLimit: self.tabContainerData?.2, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate)
self.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate) self.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate)
} }
@@ -1506,6 +1506,22 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
} }
self.chatListDisplayNode.containerNode.displayFilterLimit = { [weak self] in
guard let strongSelf = self else {
return
}
let context = strongSelf.context
var replaceImpl: ((ViewController) -> Void)?
let controller = PremiumLimitScreen(context: context, subject: .folders, count: strongSelf.tabContainerNode.filtersCount, action: {
let controller = PremiumIntroScreen(context: context, source: .folders)
replaceImpl?(controller)
})
replaceImpl = { [weak controller] c in
controller?.replace(with: c)
}
strongSelf.push(controller)
}
guard case .root = self.groupId else { guard case .root = self.groupId else {
return return
} }
@@ -1820,7 +1836,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
let navigationBarHeight = self.navigationBar?.frame.maxY ?? 0.0 let navigationBarHeight = self.navigationBar?.frame.maxY ?? 0.0
transition.updateFrame(node: self.tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 46.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 46.0))) transition.updateFrame(node: self.tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 46.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 46.0)))
self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring)) self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, filtersLimit: self.tabContainerData?.2, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring))
if let tabContainerData = self.tabContainerData { if let tabContainerData = self.tabContainerData {
self.chatListDisplayNode.inlineTabContainerNode.isHidden = !tabContainerData.1 || tabContainerData.0.count <= 1 self.chatListDisplayNode.inlineTabContainerNode.isHidden = !tabContainerData.1 || tabContainerData.0.count <= 1
} else { } else {
@@ -1957,9 +1973,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
]), ]),
filterItems, filterItems,
displayTabsAtBottom, displayTabsAtBottom,
self.context.account.postbox.peerView(id: self.context.account.peerId) self.context.account.postbox.peerView(id: self.context.account.peerId),
self.context.engine.data.get(TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false))
) )
|> deliverOnMainQueue).start(next: { [weak self] _, countAndFilterItems, displayTabsAtBottom, peerView in |> deliverOnMainQueue).start(next: { [weak self] _, countAndFilterItems, displayTabsAtBottom, peerView, limits in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
@@ -1973,7 +1990,11 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
for (filter, unreadCount, hasUnmutedUnread) in items { for (filter, unreadCount, hasUnmutedUnread) in items {
switch filter { switch filter {
case .allChats: case .allChats:
filterItems.append(.all(unreadCount: 0)) if !isPremium && filterItems.count > 0 {
filterItems.insert(.all(unreadCount: 0), at: 0)
} else {
filterItems.append(.all(unreadCount: 0))
}
case let .filter(id, title, _, _): case let .filter(id, title, _, _):
filterItems.append(.filter(id: id, text: title, unread: ChatListFilterTabEntryUnreadCount(value: unreadCount, hasUnmuted: hasUnmutedUnread))) filterItems.append(.filter(id: id, text: title, unread: ChatListFilterTabEntryUnreadCount(value: unreadCount, hasUnmuted: hasUnmutedUnread)))
} }
@@ -2022,14 +2043,19 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
selectedEntryId = .all selectedEntryId = .all
} }
} }
strongSelf.tabContainerData = (resolvedItems, displayTabsAtBottom) let filtersLimit = !isPremium ? limits.maxFoldersCount : nil
strongSelf.tabContainerData = (resolvedItems, displayTabsAtBottom, filtersLimit)
var availableFilters: [ChatListContainerNodeFilter] = [] var availableFilters: [ChatListContainerNodeFilter] = []
var hasAllChats = false var hasAllChats = false
for item in items { for item in items {
switch item.0 { switch item.0 {
case .allChats: case .allChats:
hasAllChats = true hasAllChats = true
availableFilters.append(.all) if !isPremium && availableFilters.count > 0 {
availableFilters.insert(.all, at: 0)
} else {
availableFilters.append(.all)
}
case .filter: case .filter:
availableFilters.append(.filter(item.0)) availableFilters.append(.filter(item.0))
} }
@@ -2037,7 +2063,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
if !hasAllChats { if !hasAllChats {
availableFilters.insert(.all, at: 0) availableFilters.insert(.all, at: 0)
} }
strongSelf.chatListDisplayNode.containerNode.updateAvailableFilters(availableFilters) strongSelf.chatListDisplayNode.containerNode.updateAvailableFilters(availableFilters, limit: filtersLimit)
if !strongSelf.initializedFilters && selectedEntryId != strongSelf.chatListDisplayNode.containerNode.currentItemFilter { if !strongSelf.initializedFilters && selectedEntryId != strongSelf.chatListDisplayNode.containerNode.currentItemFilter {
strongSelf.chatListDisplayNode.containerNode.switchToFilter(id: selectedEntryId, animated: false, completion: nil) strongSelf.chatListDisplayNode.containerNode.switchToFilter(id: selectedEntryId, animated: false, completion: nil)
@@ -2062,7 +2088,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
strongSelf.containerLayoutUpdated(layout, transition: transition) strongSelf.containerLayoutUpdated(layout, transition: transition)
(strongSelf.parent as? TabBarController)?.updateLayout(transition: transition) (strongSelf.parent as? TabBarController)?.updateLayout(transition: transition)
} else { } else {
strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: isPremium, transitionFraction: strongSelf.chatListDisplayNode.containerNode.transitionFraction, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring)) strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: isPremium, filtersLimit: filtersLimit, transitionFraction: strongSelf.chatListDisplayNode.containerNode.transitionFraction, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring))
strongSelf.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: strongSelf.chatListDisplayNode.containerNode.transitionFraction, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring)) strongSelf.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: resolvedItems, selectedFilter: selectedEntryId, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: strongSelf.chatListDisplayNode.containerNode.transitionFraction, presentationData: strongSelf.presentationData, transition: .animated(duration: 0.4, curve: .spring))
} }
} }
@@ -2185,7 +2211,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
let tabsIsEmpty: Bool let tabsIsEmpty: Bool
if let (resolvedItems, displayTabsAtBottom) = strongSelf.tabContainerData { if let (resolvedItems, displayTabsAtBottom, _) = strongSelf.tabContainerData {
tabsIsEmpty = resolvedItems.count <= 1 || displayTabsAtBottom tabsIsEmpty = resolvedItems.count <= 1 || displayTabsAtBottom
} else { } else {
tabsIsEmpty = true tabsIsEmpty = true
@@ -2259,7 +2285,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController
} }
let tabsIsEmpty: Bool let tabsIsEmpty: Bool
if let (resolvedItems, displayTabsAtBottom) = self.tabContainerData { if let (resolvedItems, displayTabsAtBottom, _) = self.tabContainerData {
tabsIsEmpty = resolvedItems.count <= 1 || displayTabsAtBottom tabsIsEmpty = resolvedItems.count <= 1 || displayTabsAtBottom
} else { } else {
tabsIsEmpty = true tabsIsEmpty = true

View File

@@ -432,6 +432,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
private var itemNodes: [ChatListFilterTabEntryId: ChatListContainerItemNode] = [:] private var itemNodes: [ChatListFilterTabEntryId: ChatListContainerItemNode] = [:]
private var pendingItemNode: (ChatListFilterTabEntryId, ChatListContainerItemNode, Disposable)? private var pendingItemNode: (ChatListFilterTabEntryId, ChatListContainerItemNode, Disposable)?
private var availableFilters: [ChatListContainerNodeFilter] = [.all] private var availableFilters: [ChatListContainerNodeFilter] = [.all]
private var filtersLimit: Int32? = nil
private var selectedId: ChatListFilterTabEntryId private var selectedId: ChatListFilterTabEntryId
private(set) var transitionFraction: CGFloat = 0.0 private(set) var transitionFraction: CGFloat = 0.0
@@ -578,6 +579,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
var activateChatPreview: ((ChatListItem, ASDisplayNode, ContextGesture?) -> Void)? var activateChatPreview: ((ChatListItem, ASDisplayNode, ContextGesture?) -> Void)?
var addedVisibleChatsWithPeerIds: (([EnginePeer.Id]) -> Void)? var addedVisibleChatsWithPeerIds: (([EnginePeer.Id]) -> Void)?
var didBeginSelectingChats: (() -> Void)? var didBeginSelectingChats: (() -> Void)?
var displayFilterLimit: (() -> Void)?
init(context: AccountContext, groupId: EngineChatList.Group, previewing: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, filterBecameEmpty: @escaping (ChatListFilter?) -> Void, filterEmptyAction: @escaping (ChatListFilter?) -> Void) { init(context: AccountContext, groupId: EngineChatList.Group, previewing: Bool, controlsHistoryPreload: Bool, presentationData: PresentationData, filterBecameEmpty: @escaping (ChatListFilter?) -> Void, filterEmptyAction: @escaping (ChatListFilter?) -> Void) {
self.context = context self.context = context
@@ -649,6 +651,8 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
} }
@objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) {
let filtersLimit = self.filtersLimit.flatMap({ $0 + 1 }) ?? Int32(self.availableFilters.count)
switch recognizer.state { switch recognizer.state {
case .began: case .began:
self.onFilterSwitch?() self.onFilterSwitch?()
@@ -688,9 +692,18 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
let overscroll = translation.x let overscroll = translation.x
transitionFraction = rubberBandingOffset(offset: overscroll, bandingStart: 0.0) / layout.size.width transitionFraction = rubberBandingOffset(offset: overscroll, bandingStart: 0.0) / layout.size.width
} }
if selectedIndex >= self.availableFilters.count - 1 && translation.x < 0.0 {
if selectedIndex >= filtersLimit - 1 && translation.x < 0.0 {
let overscroll = -translation.x let overscroll = -translation.x
transitionFraction = -rubberBandingOffset(offset: overscroll, bandingStart: 0.0) / layout.size.width transitionFraction = -rubberBandingOffset(offset: overscroll, bandingStart: 0.0) / layout.size.width
if self.filtersLimit != nil {
transitionFraction = 0.0
recognizer.isEnabled = false
recognizer.isEnabled = true
self.displayFilterLimit?()
}
} }
self.transitionFraction = transitionFraction + self.transitionFractionOffset self.transitionFraction = transitionFraction + self.transitionFractionOffset
if let currentItemNode = self.currentItemNodeValue { if let currentItemNode = self.currentItemNodeValue {
@@ -731,7 +744,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
if let directionIsToRight = directionIsToRight { if let directionIsToRight = directionIsToRight {
var updatedIndex = selectedIndex var updatedIndex = selectedIndex
if directionIsToRight { if directionIsToRight {
updatedIndex = min(updatedIndex + 1, self.availableFilters.count - 1) updatedIndex = min(updatedIndex + 1, Int(filtersLimit) - 1)
} else { } else {
updatedIndex = max(updatedIndex - 1, 0) updatedIndex = max(updatedIndex - 1, 0)
} }
@@ -807,13 +820,14 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate {
} }
} }
func updateAvailableFilters(_ availableFilters: [ChatListContainerNodeFilter]) { func updateAvailableFilters(_ availableFilters: [ChatListContainerNodeFilter], limit: Int32?) {
if self.availableFilters != availableFilters { if self.availableFilters != availableFilters {
let apply: () -> Void = { [weak self] in let apply: () -> Void = { [weak self] in
guard let strongSelf = self else { guard let strongSelf = self else {
return return
} }
strongSelf.availableFilters = availableFilters strongSelf.availableFilters = availableFilters
strongSelf.filtersLimit = limit
if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = strongSelf.validLayout { if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = strongSelf.validLayout {
strongSelf.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) strongSelf.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate)
} }

View File

@@ -476,7 +476,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
private var reorderedItemIds: [ChatListFilterTabEntryId]? private var reorderedItemIds: [ChatListFilterTabEntryId]?
private lazy var hapticFeedback = { HapticFeedback() }() private lazy var hapticFeedback = { HapticFeedback() }()
private var currentParams: (size: CGSize, sideInset: CGFloat, filters: [ChatListFilterTabEntry], selectedFilter: ChatListFilterTabEntryId?, isReordering: Bool, isEditing: Bool, canReorderAllChats: Bool, transitionFraction: CGFloat, presentationData: PresentationData)? private var currentParams: (size: CGSize, sideInset: CGFloat, filters: [ChatListFilterTabEntry], selectedFilter: ChatListFilterTabEntryId?, isReordering: Bool, isEditing: Bool, canReorderAllChats: Bool, filtersLimit: Int32?, transitionFraction: CGFloat, presentationData: PresentationData)?
var reorderedFilterIds: [Int32]? { var reorderedFilterIds: [Int32]? {
return self.reorderedItemIds.flatMap { return self.reorderedItemIds.flatMap {
@@ -492,7 +492,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
} }
var filtersCount: Int32 { var filtersCount: Int32 {
if let (_, _, filters, _, _, _, _, _, _) = self.currentParams { if let (_, _, filters, _, _, _, _, _, _, _) = self.currentParams {
let filters = filters.filter { filter in let filters = filters.filter { filter in
if case .all = filter { if case .all = filter {
return false return false
@@ -570,8 +570,8 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
strongSelf.addSubnode(itemNode) strongSelf.addSubnode(itemNode)
strongSelf.reorderingItemPosition = (itemNode.frame.minX, 0.0) strongSelf.reorderingItemPosition = (itemNode.frame.minX, 0.0)
if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, transitionFraction, presentationData) = strongSelf.currentParams { if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, filtersLimit, transitionFraction, presentationData) = strongSelf.currentParams {
strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, transitionFraction: transitionFraction, presentationData: presentationData, transition: .animated(duration: 0.25, curve: .easeInOut)) strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, filtersLimit: filtersLimit, transitionFraction: transitionFraction, presentationData: presentationData, transition: .animated(duration: 0.25, curve: .easeInOut))
} }
return return
} }
@@ -590,8 +590,8 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
strongSelf.reorderingItemPosition = nil strongSelf.reorderingItemPosition = nil
strongSelf.reorderingAutoScrollAnimator?.invalidate() strongSelf.reorderingAutoScrollAnimator?.invalidate()
strongSelf.reorderingAutoScrollAnimator = nil strongSelf.reorderingAutoScrollAnimator = nil
if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, transitionFraction, presentationData) = strongSelf.currentParams { if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, filtersLimit, transitionFraction, presentationData) = strongSelf.currentParams {
strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, transitionFraction: transitionFraction, presentationData: presentationData, transition: .animated(duration: 0.25, curve: .easeInOut)) strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, filtersLimit: filtersLimit, transitionFraction: transitionFraction, presentationData: presentationData, transition: .animated(duration: 0.25, curve: .easeInOut))
} }
}, moved: { [weak self] offset in }, moved: { [weak self] offset in
guard let strongSelf = self, let reorderingItem = strongSelf.reorderingItem else { guard let strongSelf = self, let reorderingItem = strongSelf.reorderingItem else {
@@ -626,8 +626,8 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
updatedReorderedItemIds.insert(reorderingItem, at: targetIndex) updatedReorderedItemIds.insert(reorderingItem, at: targetIndex)
} }
strongSelf.reorderedItemIds = updatedReorderedItemIds strongSelf.reorderedItemIds = updatedReorderedItemIds
if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, transitionFraction, presentationData) = strongSelf.currentParams { if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, filtersLimit, transitionFraction, presentationData) = strongSelf.currentParams {
strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, transitionFraction: transitionFraction, presentationData: presentationData, transition: .animated(duration: 0.25, curve: .easeInOut)) strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, filtersLimit: filtersLimit, transitionFraction: transitionFraction, presentationData: presentationData, transition: .animated(duration: 0.25, curve: .easeInOut))
} }
} }
break break
@@ -637,8 +637,8 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
strongSelf.reorderingItemPosition = (initial, offset) strongSelf.reorderingItemPosition = (initial, offset)
} }
if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, transitionFraction, presentationData) = strongSelf.currentParams { if let (size, sideInset, filters, selectedFilter, isReordering, isEditing, canReorderAllChats, filtersLimit, transitionFraction, presentationData) = strongSelf.currentParams {
strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, transitionFraction: transitionFraction, presentationData: presentationData, transition: .immediate) strongSelf.update(size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering: isReordering, isEditing: isEditing, canReorderAllChats: canReorderAllChats, filtersLimit: filtersLimit, transitionFraction: transitionFraction, presentationData: presentationData, transition: .immediate)
} }
}) })
self.reorderingGesture = reorderingGesture self.reorderingGesture = reorderingGesture
@@ -654,7 +654,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
self.scrollNode.layer.removeAllAnimations() self.scrollNode.layer.removeAllAnimations()
} }
func update(size: CGSize, sideInset: CGFloat, filters: [ChatListFilterTabEntry], selectedFilter: ChatListFilterTabEntryId?, isReordering: Bool, isEditing: Bool, canReorderAllChats: Bool, transitionFraction: CGFloat, presentationData: PresentationData, transition proposedTransition: ContainedViewLayoutTransition) { func update(size: CGSize, sideInset: CGFloat, filters: [ChatListFilterTabEntry], selectedFilter: ChatListFilterTabEntryId?, isReordering: Bool, isEditing: Bool, canReorderAllChats: Bool, filtersLimit: Int32?, transitionFraction: CGFloat, presentationData: PresentationData, transition proposedTransition: ContainedViewLayoutTransition) {
let isFirstTime = self.currentParams == nil let isFirstTime = self.currentParams == nil
let transition: ContainedViewLayoutTransition = isFirstTime ? .immediate : proposedTransition let transition: ContainedViewLayoutTransition = isFirstTime ? .immediate : proposedTransition
@@ -699,7 +699,7 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
self.reorderedItemIds = nil self.reorderedItemIds = nil
} }
self.currentParams = (size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering, isEditing, canReorderAllChats, transitionFraction, presentationData: presentationData) self.currentParams = (size: size, sideInset: sideInset, filters: filters, selectedFilter: selectedFilter, isReordering, isEditing, canReorderAllChats, filtersLimit, transitionFraction, presentationData: presentationData)
self.reorderingGesture?.isEnabled = isReordering self.reorderingGesture?.isEnabled = isReordering
@@ -723,7 +723,6 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
} }
} }
let folderLimit: Int = 4
var folderIndex = 0 var folderIndex = 0
for i in 0 ..< reorderedFilters.count { for i in 0 ..< reorderedFilters.count {
let filter = reorderedFilters[i] let filter = reorderedFilters[i]
@@ -769,7 +768,9 @@ final class ChatListFilterTabContainerNode: ASDisplayNode {
unreadCount = unread.value unreadCount = unread.value
unreadHasUnmuted = unread.hasUnmuted unreadHasUnmuted = unread.hasUnmuted
isDisabled = !canReorderAllChats && folderIndex >= folderLimit if let filtersLimit = filtersLimit {
isDisabled = !canReorderAllChats && folderIndex >= filtersLimit
}
folderIndex += 1 folderIndex += 1
} }
if !wasAdded && (itemNode.unreadCount != 0) != (unreadCount != 0) { if !wasAdded && (itemNode.unreadCount != 0) != (unreadCount != 0) {