diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift index 16aa80cbfb..e6ba424e59 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersSearchContainerNode.swift @@ -17,7 +17,7 @@ import ContactsPeerItem import ChatListSearchItemHeader import ItemListUI -enum ChannelMembersSearchMode { +public enum ChannelMembersSearchMode { case searchMembers case searchAdmins case searchBanned @@ -239,10 +239,10 @@ private struct GroupMembersSearchContextState { var members: [RenderedChannelParticipant] = [] } -final class GroupMembersSearchContext { +public final class GroupMembersSearchContext { fileprivate let state = Promise() - init(context: AccountContext, peerId: PeerId) { + public init(context: AccountContext, peerId: PeerId) { assert(Queue.mainQueue().isCurrent()) let combinedSignal = combineLatest(queue: .mainQueue(), categorySignal(context: context, peerId: peerId, category: .contacts), categorySignal(context: context, peerId: peerId, category: .bots), categorySignal(context: context, peerId: peerId, category: .admins), categorySignal(context: context, peerId: peerId, category: .members)) @@ -275,7 +275,7 @@ private struct ChannelMembersSearchContainerState: Equatable { var removingParticipantIds = Set() } -final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNode { +public final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNode { private let context: AccountContext private let openPeer: (Peer, RenderedChannelParticipant?) -> Void private let mode: ChannelMembersSearchMode @@ -298,7 +298,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod private let presentationDataPromise: Promise - init(context: AccountContext, peerId: PeerId, mode: ChannelMembersSearchMode, filters: [ChannelMembersSearchFilter], searchContext: GroupMembersSearchContext?, openPeer: @escaping (Peer, RenderedChannelParticipant?) -> Void, updateActivity: @escaping (Bool) -> Void, pushController: @escaping (ViewController) -> Void) { + public init(context: AccountContext, peerId: PeerId, mode: ChannelMembersSearchMode, filters: [ChannelMembersSearchFilter], searchContext: GroupMembersSearchContext?, openPeer: @escaping (Peer, RenderedChannelParticipant?) -> Void, updateActivity: @escaping (Bool) -> Void, pushController: @escaping (ViewController) -> Void) { self.context = context self.openPeer = openPeer self.mode = mode @@ -1170,7 +1170,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod self.removeMemberDisposable.dispose() } - override func didLoad() { + override public func didLoad() { super.didLoad() } @@ -1179,7 +1179,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod self.listNode.backgroundColor = theme.chatList.backgroundColor } - override func searchTextUpdated(text: String) { + override public func searchTextUpdated(text: String) { if text.isEmpty { self.searchQuery.set(.single(nil)) } else { @@ -1244,7 +1244,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod } } - override func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) { super.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: transition) let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) @@ -1268,7 +1268,7 @@ final class ChannelMembersSearchContainerNode: SearchDisplayControllerContentNod } } - override func scrollToTop() { + override public func scrollToTop() { if self.listNode.isHidden { self.emptyQueryListNode.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous, .LowLatency], scrollToItem: ListViewScrollToItem(index: 0, position: .top(0.0), animated: true, curve: .Default(duration: nil), directionHint: .Up), updateSizeAndInsets: nil, stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) } else { diff --git a/submodules/PeerInfoUI/Sources/ChannelMembersSearchController.swift b/submodules/PeerInfoUI/Sources/ChannelMembersSearchController.swift index a9350d7aba..4125fbe79c 100644 --- a/submodules/PeerInfoUI/Sources/ChannelMembersSearchController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelMembersSearchController.swift @@ -14,7 +14,7 @@ enum ChannelMembersSearchControllerMode { case ban } -enum ChannelMembersSearchFilter { +public enum ChannelMembersSearchFilter { case exclude([PeerId]) case disable([PeerId]) } diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 478b46d720..018c87d2d6 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -813,7 +813,7 @@ public enum ChannelVisibilityControllerMode { case privateLink } -public func channelVisibilityController(context: AccountContext, peerId: PeerId, mode: ChannelVisibilityControllerMode, upgradedToSupergroup: @escaping (PeerId, @escaping () -> Void) -> Void) -> ViewController { +public func channelVisibilityController(context: AccountContext, peerId: PeerId, mode: ChannelVisibilityControllerMode, upgradedToSupergroup: @escaping (PeerId, @escaping () -> Void) -> Void, onDismissRemoveController: ViewController? = nil) -> ViewController { let statePromise = ValuePromise(ChannelVisibilityControllerState(), ignoreRepeated: true) let stateValue = Atomic(value: ChannelVisibilityControllerState()) let updateState: ((ChannelVisibilityControllerState) -> ChannelVisibilityControllerState) -> Void = { f in @@ -1231,9 +1231,22 @@ public func channelVisibilityController(context: AccountContext, peerId: PeerId, } let controller = ItemListController(context: context, state: signal) - dismissImpl = { [weak controller] in - controller?.view.endEditing(true) - controller?.dismiss() + dismissImpl = { [weak controller, weak onDismissRemoveController] in + guard let controller = controller else { + return + } + controller.view.endEditing(true) + if let onDismissRemoveController = onDismissRemoveController, let navigationController = controller.navigationController { + navigationController.setViewControllers(navigationController.viewControllers.filter { c in + if c === controller || c === onDismissRemoveController { + return false + } else { + return true + } + }, animated: true) + } else { + controller.dismiss() + } } dismissInputImpl = { [weak controller] in controller?.view.endEditing(true) diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift index a7733e39d9..8f901e2cd8 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/Panes/PeerInfoVisualMediaPaneNode.swift @@ -87,7 +87,11 @@ private final class VisualMediaItemNode: ASDisplayNode { override func didLoad() { super.didLoad() - self.view.addGestureRecognizer(TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + let recognizer = TapLongTapOrDoubleTapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:))) + recognizer.tapActionAtPoint = { _ in + return .waitForSingleTap + } + self.imageNode.view.addGestureRecognizer(recognizer) } @objc func tapGesture(_ recognizer: TapLongTapOrDoubleTapGestureRecognizer) { @@ -375,6 +379,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro self.itemInteraction.selectedMessageIds = chatControllerInteraction.selectionState.flatMap { $0.selectedIds } self.scrollNode.view.delaysContentTouches = false + self.scrollNode.view.canCancelContentTouches = true self.scrollNode.view.showsVerticalScrollIndicator = false if #available(iOS 11.0, *) { self.scrollNode.view.contentInsetAdjustmentBehavior = .never diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift index 39d84c0a23..f7c9aadc5d 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoHeaderNode.swift @@ -1099,30 +1099,135 @@ final class PeerInfoHeaderSingleLineTextFieldNode: ASDisplayNode, PeerInfoHeader } } -/*final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode { - private let textNode: TextFieldNode +final class PeerInfoHeaderMultiLineTextFieldNode: ASDisplayNode, PeerInfoHeaderTextFieldNode, ASEditableTextNodeDelegate { + private let textNode: EditableTextNode + private let textNodeContainer: ASDisplayNode + private let measureTextNode: ImmediateTextNode private let topSeparator: ASDisplayNode - override init() { - self.textNode = TextFieldNode() + private let requestUpdateHeight: () -> Void + + private var theme: PresentationTheme? + private var currentParams: (width: CGFloat, safeInset: CGFloat)? + private var currentMeasuredHeight: CGFloat? + + var text: String { + return self.textNode.attributedText?.string ?? "" + } + + init(requestUpdateHeight: @escaping () -> Void) { + self.requestUpdateHeight = requestUpdateHeight + + self.textNode = EditableTextNode() + self.textNodeContainer = ASDisplayNode() + self.measureTextNode = ImmediateTextNode() + self.measureTextNode.maximumNumberOfLines = 0 self.topSeparator = ASDisplayNode() super.init() + + self.textNodeContainer.addSubnode(self.textNode) + self.addSubnode(self.textNodeContainer) + self.addSubnode(self.topSeparator) } - func update(width: CGFloat, safeInset: CGFloat) -> CGFloat { - return 44.0 + func update(width: CGFloat, safeInset: CGFloat, hasPrevious: Bool, placeholder: String, isEnabled: Bool, presentationData: PresentationData, updateText: String?) -> CGFloat { + self.currentParams = (width, safeInset) + + if self.theme !== presentationData.theme { + self.theme = presentationData.theme + let textColor = presentationData.theme.list.itemPrimaryTextColor + self.textNode.typingAttributes = [NSAttributedString.Key.font.rawValue: Font.regular(17.0), NSAttributedString.Key.foregroundColor.rawValue: textColor] + + self.textNode.clipsToBounds = true + self.textNode.delegate = self + self.textNode.hitTestSlop = UIEdgeInsets(top: -5.0, left: -5.0, bottom: -5.0, right: -5.0) + } + + self.topSeparator.backgroundColor = presentationData.theme.list.itemBlocksSeparatorColor + self.topSeparator.frame = CGRect(origin: CGPoint(x: safeInset + (hasPrevious ? 16.0 : 0.0), y: 0.0), size: CGSize(width: width, height: UIScreenPixel)) + + let attributedPlaceholderText = NSAttributedString(string: placeholder, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPlaceholderTextColor) + if self.textNode.attributedPlaceholderText == nil || !self.textNode.attributedPlaceholderText!.isEqual(to: attributedPlaceholderText) { + self.textNode.attributedPlaceholderText = attributedPlaceholderText + } + + if let updateText = updateText { + let attributedText = NSAttributedString(string: updateText, font: Font.regular(17.0), textColor: presentationData.theme.list.itemPrimaryTextColor) + self.textNode.attributedText = attributedText + } + + var measureText = self.textNode.attributedText?.string ?? "" + if measureText.hasSuffix("\n") || measureText.isEmpty { + measureText += "|" + } + let attributedMeasureText = NSAttributedString(string: measureText, font: Font.regular(17.0), textColor: .black) + self.measureTextNode.attributedText = attributedMeasureText + let measureTextSize = self.measureTextNode.updateLayout(CGSize(width: width - safeInset * 2.0 - 16 * 2.0, height: .greatestFiniteMagnitude)) + self.currentMeasuredHeight = measureTextSize.height + + let height = measureTextSize.height + 22.0 + + let textNodeFrame = CGRect(origin: CGPoint(x: safeInset + 16.0, y: 10.0), size: CGSize(width: width - safeInset * 2.0 - 16.0 * 2.0, height: max(height, 1000.0))) + self.textNodeContainer.frame = textNodeFrame + self.textNode.frame = CGRect(origin: CGPoint(), size: textNodeFrame.size) + + return height } -}*/ + + func editableTextNode(_ editableTextNode: ASEditableTextNode, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { + guard let theme = self.theme else { + return true + } + let updatedText = (editableTextNode.textView.text as NSString).replacingCharacters(in: range, with: text) + if updatedText.count > 255 { + let attributedText = NSAttributedString(string: String(updatedText[updatedText.startIndex.. 0.1 { + self.requestUpdateHeight() + } + } + } + + func editableTextNodeShouldPaste(_ editableTextNode: ASEditableTextNode) -> Bool { + let text: String? = UIPasteboard.general.string + if let _ = text { + return true + } else { + return false + } + } +} final class PeerInfoHeaderEditingContentNode: ASDisplayNode { private let context: AccountContext + private let requestUpdateLayout: () -> Void + let avatarNode: PeerInfoEditingAvatarNode var itemNodes: [PeerInfoHeaderTextFieldNodeKey: PeerInfoHeaderTextFieldNode] = [:] - init(context: AccountContext) { + init(context: AccountContext, requestUpdateLayout: @escaping () -> Void) { self.context = context + self.requestUpdateLayout = requestUpdateLayout + self.avatarNode = PeerInfoEditingAvatarNode(context: context) super.init() @@ -1167,6 +1272,7 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode { if let current = self.itemNodes[key] { itemNode = current } else { + var isMultiline = false switch key { case .firstName: updateText = (peer as? TelegramUser)?.firstName ?? "" @@ -1175,6 +1281,7 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode { case .title: updateText = peer?.debugDisplayTitle ?? "" case .description: + isMultiline = true if let cachedData = cachedData as? CachedChannelData { updateText = cachedData.about ?? "" } else if let cachedData = cachedData as? CachedGroupData { @@ -1183,7 +1290,13 @@ final class PeerInfoHeaderEditingContentNode: ASDisplayNode { updateText = "" } } - itemNode = PeerInfoHeaderSingleLineTextFieldNode() + if isMultiline { + itemNode = PeerInfoHeaderMultiLineTextFieldNode(requestUpdateHeight: { [weak self] in + self?.requestUpdateLayout() + }) + } else { + itemNode = PeerInfoHeaderSingleLineTextFieldNode() + } self.itemNodes[key] = itemNode self.addSubnode(itemNode) } @@ -1256,6 +1369,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { var performButtonAction: ((PeerInfoHeaderButtonKey) -> Void)? var requestAvatarExpansion: (([AvatarGalleryEntry], (ASDisplayNode, CGRect, () -> (UIView?, UIView?))) -> Void)? var requestOpenAvatarForEditing: (() -> Void)? + var requestUpdateLayout: (() -> Void)? var navigationTransition: PeerInfoHeaderNavigationTransition? @@ -1282,7 +1396,10 @@ final class PeerInfoHeaderNode: ASDisplayNode { self.subtitleNode.displaysAsynchronously = false self.regularContentNode = PeerInfoHeaderRegularContentNode() - self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context) + var requestUpdateLayoutImpl: (() -> Void)? + self.editingContentNode = PeerInfoHeaderEditingContentNode(context: context, requestUpdateLayout: { + requestUpdateLayoutImpl?() + }) self.editingContentNode.alpha = 0.0 self.navigationButtonContainer = PeerInfoHeaderNavigationButtonContainerNode() @@ -1297,6 +1414,10 @@ final class PeerInfoHeaderNode: ASDisplayNode { super.init() + requestUpdateLayoutImpl = { [weak self] in + self?.requestUpdateLayout?() + } + self.addSubnode(self.backgroundNode) self.addSubnode(self.expandedBackgroundNode) self.addSubnode(self.separatorNode) @@ -1650,7 +1771,14 @@ final class PeerInfoHeaderNode: ASDisplayNode { let buttonsAlpha: CGFloat let apparentButtonSize: CGFloat let buttonsVerticalOffset: CGFloat + + var buttonsAlphaTransition = transition + if self.navigationTransition != nil { + if case let .animated(duration, curve) = transition, transitionFraction >= 1.0 - CGFloat.ulpOfOne { + buttonsAlphaTransition = .animated(duration: duration * 0.6, curve: curve) + } + if self.isAvatarExpanded { apparentButtonSize = expandedButtonSize } else { @@ -1736,7 +1864,7 @@ final class PeerInfoHeaderNode: ASDisplayNode { if wasAdded { buttonNode.alpha = 0.0 } - transition.updateAlpha(node: buttonNode, alpha: buttonsAlpha) + buttonsAlphaTransition.updateAlpha(node: buttonNode, alpha: buttonsAlpha) let hiddenWhileExpanded: Bool switch self.keepExpandedButtons { diff --git a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift index 7dcead0b6c..b0e57aa3b3 100644 --- a/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/TelegramUI/PeerInfo/PeerInfoScreen.swift @@ -601,25 +601,26 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese interaction.openAddContact() })) } - if let cachedData = data.cachedData as? CachedUserData { - if cachedData.isBlocked { - items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? presentationData.strings.Bot_Unblock : presentationData.strings.Conversation_Unblock, action: { - interaction.updateBlocked(false) - })) + } + if let cachedData = data.cachedData as? CachedUserData { + if cachedData.isBlocked { + items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? presentationData.strings.Bot_Unblock : presentationData.strings.Conversation_Unblock, action: { + interaction.updateBlocked(false) + })) + } else { + if user.flags.contains(.isSupport) { } else { - if user.flags.contains(.isSupport) { - } else { - items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? presentationData.strings.Bot_Stop : presentationData.strings.Conversation_BlockUser, color: .destructive, action: { - interaction.updateBlocked(true) - })) - } + items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 4, text: user.botInfo != nil ? presentationData.strings.Bot_Stop : presentationData.strings.Conversation_BlockUser, color: .destructive, action: { + interaction.updateBlocked(true) + })) } } - if user.botInfo != nil, !user.isVerified { - items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 5, text: presentationData.strings.ReportPeer_Report, action: { - interaction.openReport() - })) - } + } + + if user.botInfo != nil, !user.isVerified { + items[.peerInfo]!.append(PeerInfoScreenActionItem(id: 5, text: presentationData.strings.ReportPeer_Report, action: { + interaction.openReport() + })) } } else if let channel = data.peer as? TelegramChannel { let ItemUsername = 1 @@ -1170,14 +1171,15 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } })) } - - items.append( ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuMore, color: .accent, action: { [weak actionSheet] in - actionSheet?.dismissAnimated() - if let strongSelf = self { - strongSelf.chatInterfaceInteraction.toggleMessagesSelection([message.id], true) - strongSelf.expandTabs() - } - })) + if strongSelf.searchDisplayController == nil { + items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_ContextMenuMore, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + strongSelf.chatInterfaceInteraction.toggleMessagesSelection([message.id], true) + strongSelf.expandTabs() + } + })) + } actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in actionSheet?.dismissAnimated() @@ -1575,6 +1577,15 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD self?.openAvatarForEditing() } + self.headerNode.requestUpdateLayout = { [weak self] in + guard let strongSelf = self else { + return + } + if let (layout, navigationHeight) = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: .immediate, additive: false) + } + } + self.headerNode.navigationButtonContainer.performAction = { [weak self] key in guard let strongSelf = self else { return @@ -1646,7 +1657,36 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } } else if let group = data.peer as? TelegramGroup, canEditPeerInfo(peer: group) { let title = strongSelf.headerNode.editingContentNode.editingTextForKey(.title) ?? "" + let description = strongSelf.headerNode.editingContentNode.editingTextForKey(.description) ?? "" + var updateDataSignals: [Signal] = [] + + if title != group.title { + updateDataSignals.append( + updatePeerTitle(account: strongSelf.context.account, peerId: group.id, title: title) + |> ignoreValues + |> mapError { _ in return Void() } + ) + } + if description != (data.cachedData as? CachedGroupData)?.about { + updateDataSignals.append( + updatePeerDescription(account: strongSelf.context.account, peerId: group.id, description: description.isEmpty ? nil : description) + |> ignoreValues + |> mapError { _ in return Void() } + ) + } + strongSelf.activeActionDisposable.set((combineLatest(updateDataSignals) + |> deliverOnMainQueue).start(error: { _ in + guard let strongSelf = self else { + return + } + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + }, completed: { + guard let strongSelf = self else { + return + } + strongSelf.headerNode.navigationButtonContainer.performAction?(.cancel) + })) } else if let channel = data.peer as? TelegramChannel, canEditPeerInfo(peer: channel) { let title = strongSelf.headerNode.editingContentNode.editingTextForKey(.title) ?? "" let description = strongSelf.headerNode.editingContentNode.editingTextForKey(.description) ?? "" @@ -3106,17 +3146,19 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD } else { mode = .privateLink } - let visibilityController = channelVisibilityController(context: strongSelf.context, peerId: groupPeer.id, mode: mode, upgradedToSupergroup: { _, f in f() }) - visibilityController.navigationPresentation = .modal + let visibilityController = channelVisibilityController(context: strongSelf.context, peerId: groupPeer.id, mode: mode, upgradedToSupergroup: { _, f in f() }, onDismissRemoveController: contactsController) + //visibilityController.navigationPresentation = .modal - if let navigationController = strongSelf.controller?.navigationController as? NavigationController { + contactsController?.push(visibilityController) + + /*if let navigationController = strongSelf.controller?.navigationController as? NavigationController { var controllers = navigationController.viewControllers if let contactsController = contactsController { controllers.removeAll(where: { $0 === contactsController }) } controllers.append(visibilityController) navigationController.setViewControllers(controllers, animated: true) - } + }*/ } strongSelf.controller?.push(contactsController) @@ -3312,21 +3354,33 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD return } - var tagMask: MessageTags = .file - if let currentPaneKey = self.paneContainerNode.currentPaneKey { - switch currentPaneKey { - case .links: - tagMask = .webPage - case .music: - tagMask = .music - default: - break + if let currentPaneKey = self.paneContainerNode.currentPaneKey, case .members = currentPaneKey { + self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, contentNode: ChannelMembersSearchContainerNode(context: self.context, peerId: self.peerId, mode: .searchMembers, filters: [], searchContext: nil, openPeer: { [weak self] peer, participant in + self?.openPeer(peerId: peer.id, navigation: .info) + }, updateActivity: { _ in + }, pushController: { [weak self] c in + self?.controller?.push(c) + }), cancel: { [weak self] in + self?.deactivateSearch() + }) + } else { + var tagMask: MessageTags = .file + if let currentPaneKey = self.paneContainerNode.currentPaneKey { + switch currentPaneKey { + case .links: + tagMask = .webPage + case .music: + tagMask = .music + default: + break + } } + + self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.peerId, tagMask: tagMask, interfaceInteraction: self.chatInterfaceInteraction), cancel: { [weak self] in + self?.deactivateSearch() + }) } - self.searchDisplayController = SearchDisplayController(presentationData: self.presentationData, mode: .list, placeholder: self.presentationData.strings.Common_Search, contentNode: ChatHistorySearchContainerNode(context: self.context, peerId: self.peerId, tagMask: tagMask, interfaceInteraction: self.chatInterfaceInteraction), cancel: { [weak self] in - self?.deactivateSearch() - }) let transition: ContainedViewLayoutTransition = .animated(duration: 0.2, curve: .easeInOut) if let navigationBar = self.controller?.navigationBar { transition.updateAlpha(node: navigationBar, alpha: 0.0) @@ -3653,7 +3707,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD if self.state.selectedMessageIds == nil { if let currentPaneKey = self.paneContainerNode.currentPaneKey { switch currentPaneKey { - case .files, .music, .links: + case .files, .music, .links, .members: navigationButtons.append(PeerInfoHeaderNavigationButtonSpec(key: .search, isForExpandedView: true)) default: break