diff --git a/submodules/HashtagSearchUI/BUILD b/submodules/HashtagSearchUI/BUILD index ad68a8953b..3f24ed0255 100644 --- a/submodules/HashtagSearchUI/BUILD +++ b/submodules/HashtagSearchUI/BUILD @@ -20,6 +20,7 @@ swift_library( "//submodules/ChatListUI:ChatListUI", "//submodules/SegmentedControlNode:SegmentedControlNode", "//submodules/ListMessageItem:ListMessageItem", + "//submodules/ChatListSearchItemHeader:ChatListSearchItemHeader", ], visibility = [ "//visibility:public", diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift index a569b6ce2a..41ceb62c87 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchController.swift @@ -19,6 +19,7 @@ public final class HashtagSearchController: TelegramBaseController { private let openMessageFromSearchDisposable = MetaDisposable() private var presentationData: PresentationData + private var presentationDataDisposable: Disposable? private var controllerNode: HashtagSearchControllerNode { return self.displayNode as! HashtagSearchControllerNode @@ -38,12 +39,12 @@ public final class HashtagSearchController: TelegramBaseController { self.title = query self.navigationItem.backBarButtonItem = UIBarButtonItem(title: self.presentationData.strings.Common_Back, style: .plain, target: nil, action: nil) - let chatListPresentationData = ChatListPresentationData(theme: self.presentationData.theme, fontSize: self.presentationData.listsFontSize, strings: self.presentationData.strings, dateTimeFormat: self.presentationData.dateTimeFormat, nameSortOrder: self.presentationData.nameSortOrder, nameDisplayOrder: self.presentationData.nameDisplayOrder, disableAnimations: true) - let location: SearchMessagesLocation = .general(tags: nil, minDate: nil, maxDate: nil) let search = context.engine.messages.searchMessages(location: location, query: query, state: nil) - let foundMessages: Signal<[ChatListSearchEntry], NoError> = search - |> map { result, _ in + let foundMessages: Signal<[ChatListSearchEntry], NoError> = combineLatest(search, self.context.sharedContext.presentationData) + |> map { result, presentationData in + let result = result.0 + let chatListPresentationData = ChatListPresentationData(theme: presentationData.theme, fontSize: presentationData.listsFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameSortOrder: presentationData.nameSortOrder, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true) return result.messages.map({ .message(EngineMessage($0), EngineRenderedPeer(message: EngineMessage($0)), result.readStates[$0.id.peerId].flatMap(EnginePeerReadCounters.init), chatListPresentationData, result.totalCount, nil, false) }) } let interaction = ChatListNodeInteraction(activateSearch: { @@ -101,6 +102,24 @@ public final class HashtagSearchController: TelegramBaseController { strongSelf.controllerNode.enqueueTransition(transition, firstTime: firstTime) } }) + + self.presentationDataDisposable = (self.context.sharedContext.presentationData + |> deliverOnMainQueue).start(next: { [weak self] presentationData in + if let strongSelf = self { + let previousTheme = strongSelf.presentationData.theme + let previousStrings = strongSelf.presentationData.strings + + strongSelf.presentationData = presentationData + + if previousTheme !== presentationData.theme || previousStrings !== presentationData.strings { + strongSelf.updateThemeAndStrings() + } + } + }) + + self.scrollToTop = { [weak self] in + self?.controllerNode.scrollToTop() + } } required public init(coder aDecoder: NSCoder) { @@ -109,11 +128,12 @@ public final class HashtagSearchController: TelegramBaseController { deinit { self.transitionDisposable?.dispose() + self.presentationDataDisposable?.dispose() self.openMessageFromSearchDisposable.dispose() } override public func loadDisplayNode() { - self.displayNode = HashtagSearchControllerNode(context: self.context, peer: self.peer, query: self.query, theme: self.presentationData.theme, strings: self.presentationData.strings, navigationBar: self.navigationBar, navigationController: self.navigationController as? NavigationController) + self.displayNode = HashtagSearchControllerNode(context: self.context, peer: self.peer, query: self.query, navigationBar: self.navigationBar, navigationController: self.navigationController as? NavigationController) if let chatController = self.controllerNode.chatController { chatController.parentController = self } @@ -124,6 +144,14 @@ public final class HashtagSearchController: TelegramBaseController { private var suspendNavigationBarLayout: Bool = false private var suspendedNavigationBarLayout: ContainerViewLayout? private var additionalNavigationBarBackgroundHeight: CGFloat = 0.0 + + private func updateThemeAndStrings() { + self.statusBar.statusBarStyle = self.presentationData.theme.rootController.statusBarStyle.style + + self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) + + self.controllerNode.updateThemeAndStrings(theme: self.presentationData.theme, strings: self.presentationData.strings) + } override public func updateNavigationBarLayout(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { if self.suspendNavigationBarLayout { diff --git a/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift b/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift index 3fc8cca797..bed199dda9 100644 --- a/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift +++ b/submodules/HashtagSearchUI/Sources/HashtagSearchControllerNode.swift @@ -6,12 +6,11 @@ import TelegramPresentationData import AccountContext import ChatListUI import SegmentedControlNode +import ChatListSearchItemHeader final class HashtagSearchControllerNode: ASDisplayNode { private let navigationBar: NavigationBar? - private let toolbarBackgroundNode: NavigationBackgroundNode - private let toolbarSeparatorNode: ASDisplayNode private let segmentedControlNode: SegmentedControlNode let listNode: ListView @@ -24,23 +23,18 @@ final class HashtagSearchControllerNode: ASDisplayNode { private var enqueuedTransitions: [(ChatListSearchContainerTransition, Bool)] = [] private var hasValidLayout = false - init(context: AccountContext, peer: EnginePeer?, query: String, theme: PresentationTheme, strings: PresentationStrings, navigationBar: NavigationBar?, navigationController: NavigationController?) { - self.navigationBar = navigationBar - + init(context: AccountContext, peer: EnginePeer?, query: String, navigationBar: NavigationBar?, navigationController: NavigationController?) { self.context = context self.query = query - self.listNode = ListView() - self.listNode.accessibilityPageScrolledString = { row, count in - return strings.VoiceOver_ScrollStatus(row, count).string - } - - self.toolbarBackgroundNode = NavigationBackgroundNode(color: theme.rootController.navigationBar.blurredBackgroundColor) - - self.toolbarSeparatorNode = ASDisplayNode() - self.toolbarSeparatorNode.backgroundColor = theme.rootController.navigationBar.separatorColor + self.navigationBar = navigationBar let presentationData = context.sharedContext.currentPresentationData.with { $0 } + self.listNode = ListView() + self.listNode.accessibilityPageScrolledString = { row, count in + return presentationData.strings.VoiceOver_ScrollStatus(row, count).string + } + var items: [String] = [] if peer?.id == context.account.peerId { items.append(presentationData.strings.Conversation_SavedMessages) @@ -49,8 +43,8 @@ final class HashtagSearchControllerNode: ASDisplayNode { } else { items.append(peer?.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) ?? "") } - items.append(strings.HashtagSearch_AllChats) - self.segmentedControlNode = SegmentedControlNode(theme: SegmentedControlTheme(theme: theme), items: items.map { SegmentedControlItem(title: $0) }, selectedIndex: 0) + items.append(presentationData.strings.HashtagSearch_AllChats) + self.segmentedControlNode = SegmentedControlNode(theme: SegmentedControlTheme(theme: presentationData.theme), items: items.map { SegmentedControlItem(title: $0) }, selectedIndex: 0) if let peer = peer { self.chatController = context.sharedContext.makeChatController(context: context, chatLocation: .peer(peer.id), subject: nil, botStart: nil, mode: .inline(navigationController)) @@ -64,7 +58,7 @@ final class HashtagSearchControllerNode: ASDisplayNode { return UITracingLayerView() }) - self.backgroundColor = theme.chatList.backgroundColor + self.backgroundColor = presentationData.theme.chatList.backgroundColor self.addSubnode(self.listNode) self.listNode.isHidden = true @@ -82,6 +76,18 @@ final class HashtagSearchControllerNode: ASDisplayNode { } } + func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) { + self.backgroundColor = theme.chatList.backgroundColor + + self.segmentedControlNode.updateTheme(SegmentedControlTheme(theme: theme)) + + self.listNode.forEachItemHeaderNode({ itemHeaderNode in + if let itemHeaderNode = itemHeaderNode as? ChatListSearchItemHeaderNode { + itemHeaderNode.updateTheme(theme: theme) + } + }) + } + func enqueueTransition(_ transition: ChatListSearchContainerTransition, firstTime: Bool) { self.enqueuedTransitions.append((transition, firstTime)) @@ -101,12 +107,18 @@ final class HashtagSearchControllerNode: ASDisplayNode { } } + func scrollToTop() { + if self.segmentedControlNode.selectedIndex == 0 { + self.chatController?.scrollToTop?() + } else { + self.listNode.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 }) + } + } + func containerLayoutUpdated(_ layout: ContainerViewLayout, navigationBarHeight: CGFloat, transition: ContainedViewLayoutTransition) -> CGFloat { self.containerLayout = (layout, navigationBarHeight) - if self.chatController != nil && self.toolbarSeparatorNode.supernode == nil { - //self.addSubnode(self.toolbarBackgroundNode) - self.navigationBar?.additionalContentNode.addSubnode(self.toolbarSeparatorNode) + if self.chatController != nil && self.segmentedControlNode.supernode == nil { self.navigationBar?.additionalContentNode.addSubnode(self.segmentedControlNode) } @@ -116,10 +128,6 @@ final class HashtagSearchControllerNode: ASDisplayNode { let toolbarHeight: CGFloat = 40.0 let panelY: CGFloat = insets.top - UIScreenPixel - 4.0 - transition.updateFrame(node: self.toolbarBackgroundNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelY), size: CGSize(width: layout.size.width, height: toolbarHeight))) - self.toolbarBackgroundNode.update(size: self.toolbarBackgroundNode.bounds.size, transition: transition) - transition.updateFrame(node: self.toolbarSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: panelY), size: CGSize(width: layout.size.width, height: UIScreenPixel))) - let controlSize = self.segmentedControlNode.updateLayout(.stretchToFill(width: layout.size.width - 14.0 * 2.0), transition: transition) transition.updateFrame(node: self.segmentedControlNode, frame: CGRect(origin: CGPoint(x: floor((layout.size.width - controlSize.width) / 2.0), y: panelY + 2.0 + floor((toolbarHeight - controlSize.height) / 2.0)), size: controlSize)) @@ -141,6 +149,8 @@ final class HashtagSearchControllerNode: ASDisplayNode { self.listNode.bounds = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: layout.size.height) self.listNode.position = CGPoint(x: layout.size.width / 2.0, y: layout.size.height / 2.0) + insets.top += 4.0 + let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) let updateSizeAndInsets = ListViewUpdateSizeAndInsets(size: layout.size, insets: insets, duration: duration, curve: curve) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index e983cfe2dc..5d36a6bc7e 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1970,7 +1970,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if let strongSelf = self, strongSelf.isNodeLoaded, let message = strongSelf.chatDisplayNode.historyNode.messageInCurrentHistoryView(message.id) { strongSelf.chatDisplayNode.dismissInput() openChatTheme(context: strongSelf.context, message: message, pushController: { [weak self] c in - (self?.navigationController as? NavigationController)?.pushViewController(c) + self?.effectiveNavigationController?.pushViewController(c) }, present: { [weak self] c, a in self?.present(c, in: .window(.root), with: a, blockInteraction: true) }) @@ -12417,7 +12417,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } private func openMessageReplies(messageId: MessageId, displayProgressInMessage: MessageId?, isChannelPost: Bool, atMessage atMessageId: MessageId?, displayModalProgress: Bool) { - guard let navigationController = self.navigationController as? NavigationController else { + guard let navigationController = self.effectiveNavigationController else { return }