From da9cdbf433704df5fb13a2048be6306e7ec50fb2 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 13 Sep 2020 08:15:22 +0300 Subject: [PATCH] Search filters improvements --- .../Sources/ChatListController.swift | 21 +++--- .../Sources/ChatListControllerNode.swift | 6 +- .../Sources/ChatListSearchContainerNode.swift | 64 +++++++++++++----- .../ChatListSearchFiltersContainerNode.swift | 16 +++-- .../SearchBarNode/Sources/SearchBarNode.swift | 25 ++++--- .../Search/Channel.imageset/Contents.json | 12 ++++ .../Channel.imageset/ic_search_channel.pdf | Bin 0 -> 4451 bytes .../Search/Group.imageset/Contents.json | 12 ++++ .../Search/Group.imageset/ic_search_group.pdf | Bin 0 -> 4719 bytes 9 files changed, 112 insertions(+), 44 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat List/Search/Channel.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat List/Search/Channel.imageset/ic_search_channel.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat List/Search/Group.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat List/Search/Group.imageset/ic_search_group.pdf diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 3c596ca0b3..bfd25cf94f 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -1683,10 +1683,10 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } if let searchContentNode = strongSelf.searchContentNode { - var updatedSearchOptionsImpl: ((ChatListSearchOptions?, Bool) -> Void)? + var updatedDisplayFiltersPanelImpl: ((Bool) -> Void)? - if let filterContainerNodeAndActivate = strongSelf.chatListDisplayNode.activateSearch(placeholderNode: searchContentNode.placeholderNode, navigationController: strongSelf.navigationController as? NavigationController, updatedSearchOptions: { options, hasDate in - updatedSearchOptionsImpl?(options, hasDate) + if let filterContainerNodeAndActivate = strongSelf.chatListDisplayNode.activateSearch(placeholderNode: searchContentNode.placeholderNode, navigationController: strongSelf.navigationController as? NavigationController, updatedDisplayFiltersPanel: { display in + updatedDisplayFiltersPanelImpl?(display) }) { let (filterContainerNode, activate) = filterContainerNodeAndActivate strongSelf.navigationBar?.setSecondaryContentNode(filterContainerNode, animated: false) @@ -1695,20 +1695,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController, } activate() - var currentHasSuggestions = true - updatedSearchOptionsImpl = { [weak self, weak filterContainerNode] options, hasSuggestions in + var currentDisplay = true + updatedDisplayFiltersPanelImpl = { [weak self, weak filterContainerNode] display in guard let strongSelf = self, let strongFilterContainerNode = filterContainerNode else { return } - if currentHasSuggestions != hasSuggestions { - currentHasSuggestions = hasSuggestions + if currentDisplay != display { + currentDisplay = display - var node: ASDisplayNode? - if let options = options, options.messageTags != nil && !hasSuggestions { - } else { - node = strongFilterContainerNode - } - + let node = display ? strongFilterContainerNode : nil strongSelf.navigationBar?.setSecondaryContentNode(node, animated: false) if let parentController = strongSelf.parent as? TabBarController { parentController.navigationBar?.setSecondaryContentNode(node, animated: true) diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index f66e5f0318..a700fbc752 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -1147,7 +1147,7 @@ final class ChatListControllerNode: ASDisplayNode { } } - func activateSearch(placeholderNode: SearchBarPlaceholderNode, navigationController: NavigationController?, updatedSearchOptions: ((ChatListSearchOptions?, Bool) -> Void)?) -> (ASDisplayNode, () -> Void)? { + func activateSearch(placeholderNode: SearchBarPlaceholderNode, navigationController: NavigationController?, updatedDisplayFiltersPanel: ((Bool) -> Void)?) -> (ASDisplayNode, () -> Void)? { guard let (containerLayout, _, _, cleanNavigationBarHeight) = self.containerLayout, let navigationBar = self.navigationBar, self.searchDisplayController == nil else { return nil } @@ -1169,8 +1169,8 @@ final class ChatListControllerNode: ASDisplayNode { self?.controller?.present(c, in: .window(.root), with: a) }, presentInGlobalOverlay: { [weak self] c, a in self?.controller?.presentInGlobalOverlay(c, with: a) - }, navigationController: navigationController, updatedSearchOptions: { options, hasDate in - updatedSearchOptions?(options, hasDate) + }, navigationController: navigationController, updatedDisplayFiltersPanel: { display in + updatedDisplayFiltersPanel?(display) }) self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, contentNode: contentNode, cancel: { [weak self] in diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 0a5714d4d3..5b3f0459cc 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -657,13 +657,17 @@ public enum ChatListSearchContextActionSource { } public struct ChatListSearchOptions { - let peer: (PeerId, String)? + let peer: (PeerId, Bool, String)? let minDate: (Int32, String)? let maxDate: (Int32, String)? let messageTags: MessageTags? - func withUpdatedPeer(_ peerIdAndName: (PeerId, String)?) -> ChatListSearchOptions { - return ChatListSearchOptions(peer: peerIdAndName, minDate: self.minDate, maxDate: self.maxDate, messageTags: self.messageTags) + var isEmpty: Bool { + return self.peer == nil && self.minDate == nil && self.maxDate == nil && self.messageTags == nil + } + + func withUpdatedPeer(_ peerIdIsGroupAndName: (PeerId, Bool, String)?) -> ChatListSearchOptions { + return ChatListSearchOptions(peer: peerIdIsGroupAndName, minDate: self.minDate, maxDate: self.maxDate, messageTags: self.messageTags) } func withUpdatedMinDate(_ minDateAndTitle: (Int32, String)?) -> ChatListSearchOptions { @@ -734,19 +738,19 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo private var mediaAccessoryPanel: (MediaNavigationAccessoryPanel, MediaManagerPlayerType)? private var dismissingPanel: ASDisplayNode? - private let updatedSearchOptions: ((ChatListSearchOptions?, Bool) -> Void)? + private let updatedDisplayFiltersPanel: ((Bool) -> Void)? private let emptyResultsTitleNode: ImmediateTextNode private let emptyResultsTextNode: ImmediateTextNode private let emptyResultsAnimationNode: AnimatedStickerNode private var animationSize: CGSize = CGSize() - public init(context: AccountContext, filter: ChatListNodePeersFilter, groupId: PeerGroupId, openPeer originalOpenPeer: @escaping (Peer, Bool) -> Void, openDisabledPeer: @escaping (Peer) -> Void, openRecentPeerOptions: @escaping (Peer) -> Void, openMessage originalOpenMessage: @escaping (Peer, MessageId) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, navigationController: NavigationController?, updatedSearchOptions: ((ChatListSearchOptions?, Bool) -> Void)? = nil) { + public init(context: AccountContext, filter: ChatListNodePeersFilter, groupId: PeerGroupId, openPeer originalOpenPeer: @escaping (Peer, Bool) -> Void, openDisabledPeer: @escaping (Peer) -> Void, openRecentPeerOptions: @escaping (Peer) -> Void, openMessage originalOpenMessage: @escaping (Peer, MessageId) -> Void, addContact: ((String) -> Void)?, peerContextAction: ((Peer, ChatListSearchContextActionSource, ASDisplayNode, ContextGesture?) -> Void)?, present: @escaping (ViewController, Any?) -> Void, presentInGlobalOverlay: @escaping (ViewController, Any?) -> Void, navigationController: NavigationController?, updatedDisplayFiltersPanel: ((Bool) -> Void)? = nil) { self.context = context self.peersFilter = filter self.dimNode = ASDisplayNode() self.navigationController = navigationController - self.updatedSearchOptions = updatedSearchOptions + self.updatedDisplayFiltersPanel = updatedDisplayFiltersPanel self.present = present self.presentInGlobalOverlay = presentInGlobalOverlay @@ -910,7 +914,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } let location: SearchMessagesLocation if let options = options { - if let (peerId, _) = options.peer { + if let (peerId, _, _) = options.peer { location = .peer(peerId: peerId, fromId: nil, tags: options.messageTags, topMsgId: nil, minDate: options.minDate?.0, maxDate: options.maxDate?.0) } else { @@ -1555,7 +1559,15 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo guard let strongSelf = self else { return } - strongSelf.updateSearchOptions(strongSelf.currentSearchOptions.withUpdatedPeer((peer.id, peer.compactDisplayTitle)), clearQuery: true) + let isGroup: Bool + if let channel = peer as? TelegramChannel, case .group = channel.info { + isGroup = true + } else if peer.id.namespace == Namespaces.Peer.CloudGroup { + isGroup = true + } else { + isGroup = false + } + strongSelf.updateSearchOptions(strongSelf.currentSearchOptions.withUpdatedPeer((peer.id, isGroup, peer.compactDisplayTitle)), clearQuery: true) strongSelf.dismissInput?() }, searchResults: newEntries.compactMap { entry -> Message? in if case let .message(message, _, _, _, _, _, _) = entry { @@ -1574,7 +1586,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo let previousPossiblePeers = strongSelf.possiblePeers strongSelf.possiblePeers = Array(peers.prefix(10)) - strongSelf.updatedSearchOptions?(strongSelf.searchOptionsValue, strongSelf.hasSuggestions) + strongSelf.updatedDisplayFiltersPanel?(strongSelf.searchOptionsValue?.messageTags == nil || strongSelf.hasSuggestions) if let (layout, navigationBarHeight) = strongSelf.validLayout { strongSelf.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate) } @@ -1639,8 +1651,8 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo case let .date(date, title): maxDate = (date, title) clearQuery = true - case let .peer(id, name): - peer = (id, name) + case let .peer(id, isGroup, _, compactDisplayTitle): + peer = (id, isGroup, compactDisplayTitle) clearQuery = true } strongSelf.updateSearchOptions(strongSelf.currentSearchOptions.withUpdatedMessageTags(messageTags).withUpdatedMaxDate(maxDate).withUpdatedPeer(peer), clearQuery: clearQuery) @@ -1735,6 +1747,10 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } private func updateSearchOptions(_ options: ChatListSearchOptions?, clearQuery: Bool = false) { + var options = options + if options?.isEmpty ?? true { + options = nil + } self.searchOptionsValue = options self.searchOptions.set(.single(options)) @@ -1764,8 +1780,16 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } } - if let (_, peerName) = options?.peer { - tokens.append(SearchBarToken(id: ChatListTokenId.peer.rawValue, icon: UIImage(bundleImageName: "Chat List/Search/User"), title: peerName)) + if let (peerId, isGroup, peerName) = options?.peer { + let image: UIImage? + if isGroup { + image = UIImage(bundleImageName: "Chat List/Search/Group") + } else if peerId.namespace == Namespaces.Peer.CloudChannel { + image = UIImage(bundleImageName: "Chat List/Search/Channel") + } else { + image = UIImage(bundleImageName: "Chat List/Search/User") + } + tokens.append(SearchBarToken(id: ChatListTokenId.peer.rawValue, icon:image, title: peerName)) } if let (_, dateTitle) = options?.maxDate { @@ -1780,7 +1804,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo self.setQuery?(nil, tokens, self.searchQueryValue ?? "") } - self.updatedSearchOptions?(options, self.hasSuggestions) + self.updatedDisplayFiltersPanel?(options?.messageTags == nil || self.hasSuggestions) } private func updateTheme(theme: PresentationTheme) { @@ -1832,7 +1856,7 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo self.possibleDates = suggestDates(for: text, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat) if previousPossibleDate.isEmpty != self.possibleDates.isEmpty { - self.updatedSearchOptions?(self.searchOptionsValue, self.hasSuggestions) + self.updatedDisplayFiltersPanel?(self.searchOptionsValue?.messageTags == nil || self.hasSuggestions) if let (layout, navigationBarHeight) = self.validLayout { self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .immediate) } @@ -2202,7 +2226,15 @@ public final class ChatListSearchContainerNode: SearchDisplayControllerContentNo } if !self.possiblePeers.isEmpty && self.searchOptionsValue?.peer == nil { for peer in self.possiblePeers { - customFilters.append(.peer(peer.id, peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder))) + let isGroup: Bool + if let channel = peer as? TelegramChannel, case .group = channel.info { + isGroup = true + } else if peer.id.namespace == Namespaces.Peer.CloudGroup { + isGroup = true + } else { + isGroup = false + } + customFilters.append(.peer(peer.id, isGroup, peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), peer.compactDisplayTitle)) } } diff --git a/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift index 0023b47b7b..3063bf34ce 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchFiltersContainerNode.swift @@ -13,7 +13,7 @@ enum ChatListSearchFilter: Equatable { case files case music case voice - case peer(PeerId, String) + case peer(PeerId, Bool, String, String) case date(Int32, String) var id: Int32 { @@ -28,7 +28,7 @@ enum ChatListSearchFilter: Equatable { return 3 case .voice: return 4 - case let .peer(peerId, _): + case let .peer(peerId, _, _, _): return peerId.id case let .date(date, _): return date @@ -116,9 +116,17 @@ private final class ItemNode: ASDisplayNode { case .voice: title = presentationData.strings.ChatList_Search_FilterVoice icon = generateTintedImage(image: UIImage(bundleImageName: "Chat List/Search/Voice"), color: color) - case let .peer(_, displayTitle): + case let .peer(peerId, isGroup, displayTitle, _): title = displayTitle - icon = generateTintedImage(image: UIImage(bundleImageName: "Chat List/Search/User"), color: color) + let image: UIImage? + if isGroup { + image = UIImage(bundleImageName: "Chat List/Search/Group") + } else if peerId.namespace == Namespaces.Peer.CloudChannel { + image = UIImage(bundleImageName: "Chat List/Search/Channel") + } else { + image = UIImage(bundleImageName: "Chat List/Search/User") + } + icon = generateTintedImage(image: image, color: color) case let .date(_, displayTitle): title = displayTitle icon = generateTintedImage(image: UIImage(bundleImageName: "Chat List/Search/Calendar"), color: color) diff --git a/submodules/SearchBarNode/Sources/SearchBarNode.swift b/submodules/SearchBarNode/Sources/SearchBarNode.swift index 139d3a74b7..b6900adf64 100644 --- a/submodules/SearchBarNode/Sources/SearchBarNode.swift +++ b/submodules/SearchBarNode/Sources/SearchBarNode.swift @@ -168,7 +168,7 @@ private final class TokenNode: ASDisplayNode { } private class SearchBarTextField: UITextField { - public var didDeleteBackwardWhileEmpty: (() -> Void)? + public var didDeleteBackward: (() -> Bool)? let placeholderLabel: ImmediateTextNode var placeholderString: NSAttributedString? { @@ -228,6 +228,7 @@ private class SearchBarTextField: UITextField { var theme: SearchBarNodeTheme fileprivate func layoutTokens(transition: ContainedViewLayoutTransition = .immediate) { + var hasSelected = false for i in 0 ..< self.tokens.count { let token = self.tokens[i] @@ -243,7 +244,10 @@ private class SearchBarTextField: UITextField { self?.becomeFirstResponder() } let isSelected = i == self.selectedTokenIndex - let isCollapsed = !isSelected && (i < self.tokens.count - 1 || !(self.text?.isEmpty ?? true)) + if i < self.tokens.count - 1 && isSelected { + hasSelected = true + } + let isCollapsed = !isSelected && (i < self.tokens.count - 1 || hasSelected) tokenNode.update(theme: self.theme, token: token, isSelected: isSelected, isCollapsed: isCollapsed) } var removeKeys: [AnyHashable] = [] @@ -450,10 +454,12 @@ private class SearchBarTextField: UITextField { } } - if !processed && (self.text == nil || self.text!.isEmpty) { - self.didDeleteBackwardWhileEmpty?() + if !processed { + processed = self.didDeleteBackward?() ?? false + } + if !processed { + super.deleteBackward() } - super.deleteBackward() } } @@ -718,16 +724,19 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate { self.textField.delegate = self self.textField.addTarget(self, action: #selector(self.textFieldDidChange(_:)), for: .editingChanged) - self.textField.didDeleteBackwardWhileEmpty = { [weak self] in + self.textField.didDeleteBackward = { [weak self] in guard let strongSelf = self else { - return + return false } if let index = strongSelf.textField.selectedTokenIndex { strongSelf.tokens.remove(at: index) strongSelf.tokensUpdated?(strongSelf.tokens) - } else { + return true + } else if strongSelf.text.isEmpty { strongSelf.clearPressed() + return true } + return false } self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside) diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/Search/Channel.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Channel.imageset/Contents.json new file mode 100644 index 0000000000..666f3c4bdc --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Channel.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_search_channel.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/Search/Channel.imageset/ic_search_channel.pdf b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Channel.imageset/ic_search_channel.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b44f5524a8ad5bdb834d7fba3111813da4a6da23 GIT binary patch literal 4451 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 W?jGb?{#a-!h>R3iP*6=z9sEBj!KSMK literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/Search/Group.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Group.imageset/Contents.json new file mode 100644 index 0000000000..9c53dcea52 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Group.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_search_group.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/Search/Group.imageset/ic_search_group.pdf b/submodules/TelegramUI/Images.xcassets/Chat List/Search/Group.imageset/ic_search_group.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1dcc97eb8e7f793a004a0627ecd4f444961b8160 GIT binary patch literal 4719 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 literal 0 HcmV?d00001