From 6f08efd8ae6008e5a40b3ed82e820382423dc7bb Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 7 Nov 2022 17:34:04 +0400 Subject: [PATCH] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 3 + .../Sources/ChatListController.swift | 79 +++++++----- .../Sources/ChatListControllerNode.swift | 82 ++++++------- .../Sources/Node/ChatListItem.swift | 2 +- .../SearchBarNode/Sources/SearchBarNode.swift | 115 ++++++++++++------ .../Sources/SearchDisplayController.swift | 4 +- .../ChatTitleView/Sources/ChatTitleView.swift | 2 +- .../Sources/EmojiTextAttachmentView.swift | 4 +- .../Sources/EmojiPagerContentComponent.swift | 5 +- .../ChatChannelSubscriberInputPanelNode.swift | 6 +- .../TelegramUI/Sources/ChatController.swift | 2 +- .../TelegramUI/Sources/ChatEmptyNode.swift | 4 +- .../Sources/ChatHistoryListNode.swift | 2 +- .../ChatInterfaceStateInputPanels.swift | 4 +- .../Sources/ChatMessageBubbleItemNode.swift | 14 +-- 15 files changed, 186 insertions(+), 142 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 20084fa97d..5fa6325af7 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8241,3 +8241,6 @@ Sorry for the inconvenience."; "Attachment.DiscardPasteboardAlertText" = "Discard pasted items?"; "Undo.DeletedTopic" = "Topic Deleted"; + +"EmojiSearch.SearchTopicIconsPlaceholder" = "Search Topic Icons"; +"EmojiSearch.SearchTopicIconsEmptyResult" = "No emoji found"; diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 89aa2c0196..df1c9737ad 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -524,9 +524,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController default: let actionTitle: String if channel.flags.contains(.requestToJoin) { - actionTitle = strongSelf.presentationData.strings.Channel_JoinChannel - } else { actionTitle = strongSelf.presentationData.strings.Group_ApplyToJoin + } else { + actionTitle = strongSelf.presentationData.strings.Channel_JoinChannel } strongSelf.setToolbar(Toolbar(leftAction: nil, rightAction: nil, middleAction: ToolbarAction(title: actionTitle, isEnabled: true)), transition: .animated(duration: 0.4, curve: .spring)) } @@ -1871,10 +1871,18 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController } self.tabContainerNode.presentPremiumTip = { [weak self] in if let strongSelf = self { - let context = strongSelf.context strongSelf.present(UndoOverlayController(presentationData: strongSelf.presentationData, content: .universal(animation: "anim_reorder", scale: 0.05, colors: [:], title: nil, text: strongSelf.presentationData.strings.ChatListFolderSettings_SubscribeToMoveAll, customUndoText: strongSelf.presentationData.strings.ChatListFolderSettings_SubscribeToMoveAllAction), elevatedLayout: false, position: .top, animateInAsReplacement: false, action: { action in if case .undo = action { - strongSelf.push(PremiumIntroScreen(context: context, source: .folders)) + let context = strongSelf.context + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: context, subject: .advancedChatManagement, action: { + let controller = PremiumIntroScreen(context: context, source: .folders) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + strongSelf.push(controller) } return false }), in: .current) } @@ -2980,6 +2988,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController displaySearchFilters = false } + if !tabsIsEmpty, let snapshotView = strongSelf.tabContainerNode.view.snapshotView(afterScreenUpdates: false) { + snapshotView.frame = strongSelf.tabContainerNode.frame + strongSelf.tabContainerNode.view.superview?.addSubview(snapshotView) + + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + } + if let searchContentNode = strongSelf.searchContentNode { if let filterContainerNodeAndActivate = strongSelf.chatListDisplayNode.activateSearch(placeholderNode: searchContentNode.placeholderNode, displaySearchFilters: displaySearchFilters, hasDownloads: strongSelf.hasDownloads, initialFilter: filter, navigationController: strongSelf.navigationController as? NavigationController) { let (filterContainerNode, activate) = filterContainerNodeAndActivate @@ -2996,13 +3013,9 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController searchContentNode.search(filter: filter, query: query) } - if !tabsIsEmpty { - Queue.mainQueue().after(0.01) { - filterContainerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: 38.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) - filterContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) - - strongSelf.tabContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -64.0), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) - } + Queue.mainQueue().justDispatch { + filterContainerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: 30.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + filterContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) } } } @@ -3033,15 +3046,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController if !self.displayNavigationBar { var completion: (() -> Void)? - var filterContainerNode: ASDisplayNode? - if animated, let searchContentNode = self.chatListDisplayNode.searchDisplayController?.contentNode as? ChatListSearchContainerNode { - filterContainerNode = searchContentNode.filterContainerNode - } - - if let searchContentNode = self.searchContentNode { - completion = self.chatListDisplayNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode, animated: animated) - } - let tabsIsEmpty: Bool if let (resolvedItems, displayTabsAtBottom, _) = self.tabContainerData { tabsIsEmpty = resolvedItems.count <= 1 || displayTabsAtBottom @@ -3049,6 +3053,33 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController tabsIsEmpty = true } + + var filterContainerNode: ASDisplayNode? + if animated, let searchContentNode = self.chatListDisplayNode.searchDisplayController?.contentNode as? ChatListSearchContainerNode { + filterContainerNode = searchContentNode.filterContainerNode + + if let filterContainerNode = filterContainerNode, let snapshotView = filterContainerNode.view.snapshotView(afterScreenUpdates: false) { + snapshotView.frame = filterContainerNode.frame + filterContainerNode.view.superview?.addSubview(snapshotView) + + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.3, removeOnCompletion: false, completion: { [weak snapshotView] _ in + snapshotView?.removeFromSuperview() + }) + + if !tabsIsEmpty { + Queue.mainQueue().after(0.01) { + self.tabContainerNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3) + self.tabContainerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -74.0), to: .zero, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) + } + } + } + } + + if let searchContentNode = self.searchContentNode { + completion = self.chatListDisplayNode.deactivateSearch(placeholderNode: searchContentNode.placeholderNode, animated: animated) + } + + self.navigationBar?.setSecondaryContentNode(tabsIsEmpty ? nil : self.tabContainerNode, animated: false) if let parentController = self.parent as? TabBarController { parentController.navigationBar?.setSecondaryContentNode(tabsIsEmpty ? nil : self.tabContainerNode, animated: animated) @@ -3061,14 +3092,6 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController (self.parent as? TabBarController)?.updateIsTabBarHidden(false, transition: .animated(duration: 0.4, curve: .spring)) - if let filterContainerNode = filterContainerNode { - filterContainerNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: -44.0), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true) - - if !tabsIsEmpty { - self.tabContainerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -64.0), to: CGPoint(), duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) - } - } - self.isSearchActive = false if let navigationController = self.navigationController as? NavigationController { for controller in navigationController.globalOverlayControllers { diff --git a/submodules/ChatListUI/Sources/ChatListControllerNode.swift b/submodules/ChatListUI/Sources/ChatListControllerNode.swift index 7d359f0160..65508cd3de 100644 --- a/submodules/ChatListUI/Sources/ChatListControllerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListControllerNode.swift @@ -473,7 +473,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { private(set) var transitionFraction: CGFloat = 0.0 private var transitionFractionOffset: CGFloat = 0.0 private var disableItemNodeOperationsWhileAnimating: Bool = false - private var validLayout: (layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, isReorderingFilters: Bool, isEditing: Bool)? + private var validLayout: (layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, insets: UIEdgeInsets, isReorderingFilters: Bool, isEditing: Bool)? private var enableAdjacentFilterLoading: Bool = false @@ -714,7 +714,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { self.onFilterSwitch?() self.transitionFractionOffset = 0.0 - if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout, let itemNode = self.itemNodes[self.selectedId] { + if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = self.validLayout, let itemNode = self.itemNodes[self.selectedId] { for (id, itemNode) in self.itemNodes { if id != selectedId { itemNode.emptyNode?.restartAnimation() @@ -727,13 +727,13 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { for (_, itemNode) in self.itemNodes { itemNode.layer.removeAllAnimations() } - self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) + self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, .immediate, true) } } } case .changed: - if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) { + if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) { let translation = recognizer.translation(in: self.view) var transitionFraction = translation.x / layout.size.width @@ -770,11 +770,11 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { } } } - self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) + self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, .immediate, false) } case .cancelled, .ended: - if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) { + if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = self.validLayout, let selectedIndex = self.availableFilters.firstIndex(where: { $0.id == self.selectedId }) { let translation = recognizer.translation(in: self.view) let velocity = recognizer.velocity(in: self.view) var directionIsToRight: Bool? @@ -813,12 +813,12 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { self.transitionFraction = 0.0 let transition: ContainedViewLayoutTransition = .animated(duration: 0.45, curve: .spring) self.disableItemNodeOperationsWhileAnimating = true - self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: transition) + self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: transition) self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, transition, false) DispatchQueue.main.async { self.disableItemNodeOperationsWhileAnimating = false - if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout { - self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) + if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = self.validLayout { + self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) } } } @@ -884,8 +884,8 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { } strongSelf.availableFilters = availableFilters strongSelf.filtersLimit = limit - 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) + if let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = strongSelf.validLayout { + strongSelf.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) } } if !availableFilters.contains(where: { $0.id == self.selectedId }) { @@ -902,8 +902,8 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { if value != self.enableAdjacentFilterLoading { self.enableAdjacentFilterLoading = value - if self.enableAdjacentFilterLoading, let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout { - self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) + if self.enableAdjacentFilterLoading, let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = self.validLayout { + self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) } } } @@ -912,7 +912,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { self.onFilterSwitch?() if id != self.selectedId, let index = self.availableFilters.firstIndex(where: { $0.id == id }) { if let itemNode = self.itemNodes[id] { - guard let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = self.validLayout else { + guard let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = self.validLayout else { return } self.selectedId = id @@ -921,7 +921,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { } self.applyItemNodeAsCurrent(id: id, itemNode: itemNode) let transition: ContainedViewLayoutTransition = .animated(duration: 0.35, curve: .spring) - self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: transition) + self.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: transition) self.currentItemFilterUpdated?(self.currentItemFilter, self.transitionFraction, transition, false) itemNode.emptyNode?.restartAnimation() completion?() @@ -951,7 +951,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { strongSelf.pendingItemNode = nil - guard let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) = strongSelf.validLayout else { + guard let (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) = strongSelf.validLayout else { strongSelf.itemNodes[id] = itemNode strongSelf.addSubnode(itemNode) @@ -999,13 +999,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { itemNode.frame = itemFrame transition.animatePositionAdditive(node: itemNode, offset: CGPoint(x: -offset, y: 0.0)) - - var insets = layout.insets(options: [.input]) - insets.top += navigationBarHeight - - insets.left += layout.safeInsets.left - insets.right += layout.safeInsets.right - + itemNode.updateLayout(size: layout.size, insets: insets, visualNavigationHeight: visualNavigationHeight, transition: .immediate) strongSelf.selectedId = id @@ -1014,7 +1008,7 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { } strongSelf.applyItemNodeAsCurrent(id: id, itemNode: itemNode) - 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, insets: insets, isReorderingFilters: isReorderingFilters, isEditing: isEditing, transition: .immediate) strongSelf.currentItemFilterUpdated?(strongSelf.currentItemFilter, strongSelf.transitionFraction, transition, false) } @@ -1025,25 +1019,11 @@ final class ChatListContainerNode: ASDisplayNode, UIGestureRecognizerDelegate { } } - func update(layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, isReorderingFilters: Bool, isEditing: Bool, transition: ContainedViewLayoutTransition) { - self.validLayout = (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, isReorderingFilters, isEditing) + func update(layout: ContainerViewLayout, navigationBarHeight: CGFloat, visualNavigationHeight: CGFloat, cleanNavigationBarHeight: CGFloat, insets: UIEdgeInsets, isReorderingFilters: Bool, isEditing: Bool, transition: ContainedViewLayoutTransition) { + self.validLayout = (layout, navigationBarHeight, visualNavigationHeight, cleanNavigationBarHeight, insets, isReorderingFilters, isEditing) self._validLayoutReady.set(.single(true)) - var insets = layout.insets(options: [.input]) - insets.top += navigationBarHeight - - insets.left += layout.safeInsets.left - insets.right += layout.safeInsets.right - - if isEditing { - if !layout.safeInsets.left.isZero { - insets.bottom += 34.0 - } else { - insets.bottom += 49.0 - } - } - transition.updateAlpha(node: self, alpha: isReorderingFilters ? 0.5 : 1.0) self.isUserInteractionEnabled = !isReorderingFilters @@ -1264,20 +1244,26 @@ final class ChatListControllerNode: ASDisplayNode { if layout.metrics.widthClass == .regular { options.insert(.input) } + + var heightInset: CGFloat = 0.0 + if case .forum = self.location { + heightInset = 4.0 + } + let bottomInset: CGFloat = layout.insets(options: options).bottom if !layout.safeInsets.left.isZero { tabBarHeight = 34.0 + bottomInset insets.bottom += 34.0 } else { - tabBarHeight = 49.0 + bottomInset - insets.bottom += 49.0 + tabBarHeight = 49.0 - heightInset + bottomInset + insets.bottom += 49.0 - heightInset } - let tabBarFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - tabBarHeight), size: CGSize(width: layout.size.width, height: tabBarHeight)) + let toolbarFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - tabBarHeight), size: CGSize(width: layout.size.width, height: tabBarHeight)) if let toolbarNode = self.toolbarNode { - transition.updateFrame(node: toolbarNode, frame: tabBarFrame) - toolbarNode.updateLayout(size: tabBarFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, bottomInset: bottomInset, toolbar: toolbar, transition: transition) + transition.updateFrame(node: toolbarNode, frame: toolbarFrame) + toolbarNode.updateLayout(size: toolbarFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, bottomInset: bottomInset, toolbar: toolbar, transition: transition) } else { let toolbarNode = ToolbarNode(theme: ToolbarTheme(rootControllerTheme: self.presentationData.theme), displaySeparator: true, left: { [weak self] in self?.toolbarActionSelected?(.left) @@ -1286,8 +1272,8 @@ final class ChatListControllerNode: ASDisplayNode { }, middle: { [weak self] in self?.toolbarActionSelected?(.middle) }) - toolbarNode.frame = tabBarFrame - toolbarNode.updateLayout(size: tabBarFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, bottomInset: bottomInset, toolbar: toolbar, transition: .immediate) + toolbarNode.frame = toolbarFrame + toolbarNode.updateLayout(size: toolbarFrame.size, leftInset: layout.safeInsets.left, rightInset: layout.safeInsets.right, additionalSideInsets: layout.additionalInsets, bottomInset: bottomInset, toolbar: toolbar, transition: .immediate) self.addSubnode(toolbarNode) self.toolbarNode = toolbarNode if transition.isAnimated { @@ -1306,7 +1292,7 @@ final class ChatListControllerNode: ASDisplayNode { self.controller?.presentationContext.containerLayoutUpdated(childrenLayout, transition: transition) transition.updateFrame(node: self.containerNode, frame: CGRect(origin: CGPoint(), size: layout.size)) - self.containerNode.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, transition: transition) + self.containerNode.update(layout: layout, navigationBarHeight: navigationBarHeight, visualNavigationHeight: visualNavigationHeight, cleanNavigationBarHeight: cleanNavigationBarHeight, insets: insets, isReorderingFilters: self.isReorderingFilters, isEditing: self.isEditing, transition: transition) transition.updateFrame(node: self.inlineTabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - layout.intrinsicInsets.bottom - 8.0 - 40.0), size: CGSize(width: layout.size.width, height: 40.0))) diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index e45a1d9459..ccc802aefe 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -2211,7 +2211,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { let avatarIconContent: EmojiStatusComponent.Content if let fileId = threadInfo.info.icon, fileId != 0 { - avatarIconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .forever) + avatarIconContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, themeColor: item.presentationData.theme.list.itemAccentColor, loopMode: .count(2)) } else { avatarIconContent = .topic(title: String(threadInfo.info.title.prefix(1)), color: threadInfo.info.iconColor, size: CGSize(width: 32.0, height: 32.0)) } diff --git a/submodules/SearchBarNode/Sources/SearchBarNode.swift b/submodules/SearchBarNode/Sources/SearchBarNode.swift index 8eb1c5dba0..24114f7d95 100644 --- a/submodules/SearchBarNode/Sources/SearchBarNode.swift +++ b/submodules/SearchBarNode/Sources/SearchBarNode.swift @@ -407,7 +407,7 @@ private class SearchBarTextField: UITextField, UIScrollViewDelegate { } } - private var tokensWidth: CGFloat = 0.0 + fileprivate var tokensWidth: CGFloat = 0.0 private let measurePrefixLabel: ImmediateTextNode let prefixLabel: ImmediateTextNode @@ -569,19 +569,24 @@ private class SearchBarTextField: UITextField, UIScrollViewDelegate { textOffset += 2.0 } - var placeholderOffset: CGFloat = 0.0 + var placeholderXOffset: CGFloat = 0.0 + if self.tokensWidth > 0.0, self.scrollView?.superview != nil { + placeholderXOffset = self.tokensWidth + 8.0 + } + + var placeholderYOffset: CGFloat = 0.0 if #available(iOS 14.0, *) { - placeholderOffset = 1.0 + placeholderYOffset = 1.0 } else { } let textRect = self.textRect(forBounds: bounds) let labelSize = self.placeholderLabel.updateLayout(textRect.size) - self.placeholderLabel.frame = CGRect(origin: CGPoint(x: textRect.minX, y: textRect.minY + textOffset + placeholderOffset), size: labelSize) - + self.placeholderLabel.frame = CGRect(origin: CGPoint(x: textRect.minX + placeholderXOffset, y: textRect.minY + textOffset + placeholderYOffset), size: labelSize) + let prefixSize = self.prefixLabel.updateLayout(CGSize(width: floor(bounds.size.width * 0.7), height: bounds.size.height)) let prefixBounds = bounds.insetBy(dx: 4.0, dy: 4.0) - self.prefixLabel.frame = CGRect(origin: CGPoint(x: prefixBounds.minX, y: prefixBounds.minY + textOffset + placeholderOffset), size: prefixSize) + self.prefixLabel.frame = CGRect(origin: CGPoint(x: prefixBounds.minX, y: prefixBounds.minY + textOffset + placeholderYOffset), size: prefixSize) } override func deleteBackward() { @@ -1027,7 +1032,12 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate { self.textBackgroundNode.layer.animateFrame(from: initialTextBackgroundFrame, to: self.textBackgroundNode.frame, duration: duration, timingFunction: timingFunction) let textFieldFrame = self.textField.frame - let initialLabelNodeFrame = CGRect(origin: node.labelNode.frame.offsetBy(dx: initialTextBackgroundFrame.origin.x - 7.0, dy: initialTextBackgroundFrame.origin.y - 8.0).origin, size: textFieldFrame.size) + var tokensWidth = self.textField.tokensWidth + if tokensWidth > 0.0 { + tokensWidth += 8.0 + } + + let initialLabelNodeFrame = CGRect(origin: node.labelNode.frame.offsetBy(dx: initialTextBackgroundFrame.origin.x - 7.0 - tokensWidth, dy: initialTextBackgroundFrame.origin.y - 8.0).origin, size: textFieldFrame.size) self.textField.layer.animateFrame(from: initialLabelNodeFrame, to: self.textField.frame, duration: duration, timingFunction: timingFunction) let iconFrame = self.iconNode.frame @@ -1056,13 +1066,54 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate { let timingFunction = kCAMediaTimingFunctionSpring node.isHidden = true - self.clearButton.isHidden = true + + if !self.clearButton.isHidden { + let xOffset = targetTextBackgroundFrame.width - self.textBackgroundNode.frame.width + if !xOffset.isZero { + self.clearButton.layer.animatePosition(from: .zero, to: CGPoint(x: xOffset, y: 0.0), duration: duration, timingFunction: timingFunction, additive: true) + } + self.clearButton.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { _ in + self.clearButton.isHidden = true + }) + } + self.activityIndicator?.isHidden = true self.iconNode.isHidden = false + + var tokensWidth = self.textField.tokensWidth + if tokensWidth > 0.0 { + tokensWidth += 8.0 + } + + let textFieldFrame = self.textField.frame + let targetLabelNodeFrame = CGRect(origin: CGPoint(x: node.labelNode.frame.minX + targetTextBackgroundFrame.origin.x - 7.0 - tokensWidth, y: targetTextBackgroundFrame.minY + floorToScreenPixels((targetTextBackgroundFrame.size.height - textFieldFrame.size.height) / 2.0) - UIScreenPixel), size: textFieldFrame.size) + + self.textField.layer.animateFrame(from: textFieldFrame, to: targetLabelNodeFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) + + if !self.textField.tokenNodes.isEmpty { + for node in self.textField.tokenNodes.values { + node.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false) + } + } + + var hasText = false + if !(self.textField.text ?? "").isEmpty, let snapshotView = self.textField.snapshotView(afterScreenUpdates: false) { + hasText = true + snapshotView.frame = self.textField.frame + self.textField.superview?.addSubview(snapshotView) + snapshotView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { _ in + snapshotView.removeFromSuperview() + }) + + snapshotView.layer.animatePosition(from: .zero, to: CGPoint(x: targetLabelNodeFrame.minX - textFieldFrame.minX, y: 0.0), duration: duration, timingFunction: timingFunction, removeOnCompletion: false, additive: true) + + self.textField.placeholderLabel.alpha = 0.0 + } + self.textField.prefixString = nil self.textField.text = "" self.textField.layoutSubviews() - + var backgroundCompleted = false var separatorCompleted = false var textBackgroundCompleted = false @@ -1123,34 +1174,18 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate { transitionBackgroundNode.backgroundColor = node.backgroundNode.backgroundColor transitionBackgroundNode.cornerRadius = node.backgroundNode.cornerRadius self.insertSubnode(transitionBackgroundNode, aboveSubnode: self.textBackgroundNode) - //transitionBackgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration / 2.0, removeOnCompletion: false) - transitionBackgroundNode.layer.animateFrame(from: self.textBackgroundNode.frame, to: targetTextBackgroundFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) - let textFieldFrame = self.textField.frame - let targetLabelNodeFrame = CGRect(origin: CGPoint(x: node.labelNode.frame.minX + targetTextBackgroundFrame.origin.x - 7.0, y: targetTextBackgroundFrame.minY + floorToScreenPixels((targetTextBackgroundFrame.size.height - textFieldFrame.size.height) / 2.0) - UIScreenPixel), size: textFieldFrame.size) - self.textField.layer.animateFrame(from: self.textField.frame, to: targetLabelNodeFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) - if #available(iOSApplicationExtension 10.0, iOS 10.0, *) { - if let snapshot = node.labelNode.layer.snapshotContentTree() { - snapshot.frame = CGRect(origin: self.textField.placeholderLabel.frame.origin.offsetBy(dx: 0.0, dy: UIScreenPixel), size: node.labelNode.frame.size) - self.textField.layer.addSublayer(snapshot) - snapshot.animateAlpha(from: 0.0, to: 1.0, duration: duration * 2.0 / 3.0, timingFunction: CAMediaTimingFunctionName.linear.rawValue) + transitionBackgroundNode.layer.animateFrame(from: self.textBackgroundNode.frame, to: targetTextBackgroundFrame, duration: duration, timingFunction: timingFunction, removeOnCompletion: false) + + if let snapshot = node.labelNode.layer.snapshotContentTree() { + snapshot.frame = CGRect(origin: self.textField.placeholderLabel.frame.origin.offsetBy(dx: 0.0, dy: UIScreenPixel), size: node.labelNode.frame.size) + self.textField.layer.addSublayer(snapshot) + snapshot.animateAlpha(from: 0.0, to: 1.0, duration: duration * 2.0 / 3.0, timingFunction: CAMediaTimingFunctionName.linear.rawValue) + if !hasText { self.textField.placeholderLabel.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, timingFunction: CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: false) } - } else if let cachedLayout = node.labelNode.cachedLayout { - let labelNode = TextNode() - labelNode.isOpaque = false - labelNode.isUserInteractionEnabled = false - let labelLayout = TextNode.asyncLayout(labelNode) - let (labelLayoutResult, labelApply) = labelLayout(TextNodeLayoutArguments(attributedString: self.placeholderString, backgroundColor: .clear, maximumNumberOfLines: 1, truncationType: .end, constrainedSize: cachedLayout.size, alignment: .natural, cutout: nil, insets: UIEdgeInsets())) - let _ = labelApply() - - self.textField.addSubnode(labelNode) - labelNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration * 2.0 / 3.0, timingFunction: CAMediaTimingFunctionName.linear.rawValue) - labelNode.frame = CGRect(origin: self.textField.placeholderLabel.frame.origin.offsetBy(dx: 0.0, dy: UIScreenPixel), size: labelLayoutResult.size) - self.textField.placeholderLabel.layer.animateAlpha(from: 1.0, to: 0.0, duration: duration, timingFunction: CAMediaTimingFunctionName.linear.rawValue, removeOnCompletion: false, completion: { _ in - labelNode.removeFromSupernode() - }) } + let iconFrame = self.iconNode.frame let targetIconFrame = CGRect(origin: node.iconNode.frame.offsetBy(dx: targetTextBackgroundFrame.origin.x, dy: targetTextBackgroundFrame.origin.y).origin, size: iconFrame.size) self.iconNode.image = node.iconNode.image @@ -1216,13 +1251,6 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate { } private func updateIsEmpty(animated: Bool = false) { - let textIsEmpty = (self.textField.text?.isEmpty ?? true) - let isEmpty = textIsEmpty && self.tokens.isEmpty - - let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .spring) : .immediate - let placeholderTransition = !isEmpty ? .immediate : transition - placeholderTransition.updateAlpha(node: self.textField.placeholderLabel, alpha: isEmpty ? 1.0 : 0.0) - var tokensEmpty = true for token in self.tokens { if !token.permanent { @@ -1230,6 +1258,13 @@ public class SearchBarNode: ASDisplayNode, UITextFieldDelegate { } } + let textIsEmpty = (self.textField.text?.isEmpty ?? true) + let isEmpty = textIsEmpty && tokensEmpty + + let transition: ContainedViewLayoutTransition = animated ? .animated(duration: 0.3, curve: .spring) : .immediate + let placeholderTransition = !isEmpty ? .immediate : transition + placeholderTransition.updateAlpha(node: self.textField.placeholderLabel, alpha: isEmpty ? 1.0 : 0.0) + let clearIsHidden = (textIsEmpty && tokensEmpty) && self.prefixString == nil transition.updateAlpha(node: self.clearButton.imageNode, alpha: clearIsHidden ? 0.0 : 1.0) transition.updateTransformScale(node: self.clearButton, scale: clearIsHidden ? 0.2 : 1.0) diff --git a/submodules/SearchUI/Sources/SearchDisplayController.swift b/submodules/SearchUI/Sources/SearchDisplayController.swift index 8a0cddbde0..9da8055e06 100644 --- a/submodules/SearchUI/Sources/SearchDisplayController.swift +++ b/submodules/SearchUI/Sources/SearchDisplayController.swift @@ -200,7 +200,7 @@ public final class SearchDisplayController { if !self.contentNode.hasDim { self.backgroundNode.alpha = 1.0 - self.backgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, timingFunction: CAMediaTimingFunctionName.easeOut.rawValue) + self.backgroundNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2, timingFunction: CAMediaTimingFunctionName.linear.rawValue) self.backgroundNode.layer.animateScale(from: 0.85, to: 1.0, duration: 0.5, timingFunction: kCAMediaTimingFunctionSpring) } @@ -259,7 +259,7 @@ public final class SearchDisplayController { } public func deactivate(placeholder: SearchBarPlaceholderNode?, animated: Bool = true) { - self.searchBar.deactivate() + self.searchBar.deactivate(clear: false) let searchBar = self.searchBar if let placeholder = placeholder { diff --git a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift index 71ce323559..e5ededafdc 100644 --- a/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Components/ChatTitleView/Sources/ChatTitleView.swift @@ -718,7 +718,7 @@ public final class ChatTitleView: UIView, NavigationBarTitleView { if self.titleRightIconNode.supernode == nil { self.titleTextNode.addSubnode(self.titleRightIconNode) } - rightIconWidth = image.size.width + 3.0 + rightIconWidth = max(24.0, image.size.width) + 3.0 } else if self.titleRightIconNode.supernode != nil { self.titleRightIconNode.removeFromSupernode() } diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index 0dca01f208..4c748f9fca 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -63,9 +63,9 @@ public func generateTopicIcon(title: String, backgroundColors: [UIColor], stroke let attributedString = NSAttributedString(string: title, attributes: [NSAttributedString.Key.font: Font.with(size: fontSize, design: .round, weight: .bold), NSAttributedString.Key.foregroundColor: UIColor.white]) let line = CTLineCreateWithAttributedString(attributedString) - let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds) + let lineBounds = CTLineGetBoundsWithOptions(line, [.useOpticalBounds]) - let lineOffset = CGPoint(x: title == "B" ? 1.0 : 0.0, y: floorToScreenPixels(realSize.height * 0.05)) + let lineOffset = CGPoint(x: 1.0 - UIScreenPixel, y: floorToScreenPixels(realSize.height * 0.05)) let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (realSize.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (realSize.height - lineBounds.size.height) / 2.0) + lineOffset.y) context.translateBy(x: realSize.width / 2.0, y: realSize.height / 2.0) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index e0f31706fc..15f0ac595b 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -6916,6 +6916,8 @@ public final class EmojiPagerContentComponent: Component { displaySearchWithPlaceholder = strings.EmojiSearch_SearchReactionsPlaceholder } else if isStatusSelection { displaySearchWithPlaceholder = strings.EmojiSearch_SearchStatusesPlaceholder + } else if isTopicIconSelection { + displaySearchWithPlaceholder = strings.EmojiSearch_SearchTopicIconsPlaceholder } return EmojiPagerContentComponent( @@ -7014,8 +7016,7 @@ func generateTopicIcon(backgroundColors: [UIColor], strokeColors: [UIColor], tit let line = CTLineCreateWithAttributedString(attributedString) let lineBounds = CTLineGetBoundsWithOptions(line, .useGlyphPathBounds) - let lineOffset = CGPoint(x: title == "B" ? 1.0 : 0.0, y: 0.0) - let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (size.width - lineBounds.size.width) / 2.0) + lineOffset.x, y: floorToScreenPixels(-lineBounds.origin.y + (size.height - lineBounds.size.height) / 2.0) + 1.0) + let lineOrigin = CGPoint(x: floorToScreenPixels(-lineBounds.origin.x + (size.width - lineBounds.size.width) / 2.0), y: floorToScreenPixels(-lineBounds.origin.y + (size.height - lineBounds.size.height) / 2.0) + 1.0) context.translateBy(x: size.width / 2.0, y: size.height / 2.0) context.scaleBy(x: 1.0, y: -1.0) diff --git a/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift index 161f511c5d..b5c158d70a 100644 --- a/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatChannelSubscriberInputPanelNode.swift @@ -85,7 +85,11 @@ private func actionForPeer(peer: Peer, interfaceState: ChatPresentationInterface if channel.flags.contains(.requestToJoin) { return .applyToJoin } else { - return .joinGroup + if channel.flags.contains(.isForum) { + return .join + } else { + return .joinGroup + } } } else { return .join diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index aad6535a8e..9ac9d6e617 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -4924,7 +4924,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G let avatarContent: EmojiStatusComponent.Content if let fileId = threadInfo.icon { - avatarContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: strongSelf.presentationData.theme.list.mediaPlaceholderColor, themeColor: strongSelf.presentationData.theme.list.itemAccentColor, loopMode: .count(2)) + avatarContent = .animation(content: .customEmoji(fileId: fileId), size: CGSize(width: 48.0, height: 48.0), placeholderColor: strongSelf.presentationData.theme.list.mediaPlaceholderColor, themeColor: strongSelf.presentationData.theme.list.itemAccentColor, loopMode: .count(1)) } else { avatarContent = .topic(title: String(threadInfo.title.prefix(1)), color: threadInfo.iconColor, size: CGSize(width: 32.0, height: 32.0)) } diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index 69203ec817..0bf253cfba 100644 --- a/submodules/TelegramUI/Sources/ChatEmptyNode.swift +++ b/submodules/TelegramUI/Sources/ChatEmptyNode.swift @@ -896,7 +896,7 @@ private enum ChatEmptyNodeContentType: Equatable { case cloud case peerNearby case greeting - case topic(Int64?) + case topic } final class ChatEmptyNode: ASDisplayNode { @@ -973,7 +973,7 @@ final class ChatEmptyNode: ASDisplayNode { let contentType: ChatEmptyNodeContentType if case .replyThread = interfaceState.chatLocation { if case .topic = emptyType { - contentType = .topic(nil) + contentType = .topic } else { contentType = .regular } diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index d499b6df55..fe404530e8 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -2765,7 +2765,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { } else if action.action == .historyCleared { emptyType = .clearedHistory break - } else if case .topicCreated = action.action { + } else if case .topicCreated = action.action, firstEntry.message.author?.id == strongSelf.context.account.peerId { emptyType = .topic break } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift index c3fe327cdc..f3acc29e43 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateInputPanels.swift @@ -152,13 +152,13 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState isMember = true case .left: if case .replyThread = chatPresentationInterfaceState.chatLocation { - if !channel.flags.contains(.joinToSend) { + if !channel.flags.contains(.joinToSend) && !channel.flags.contains(.isForum) { isMember = true } } } - if channel.flags.contains(.isForum) { + if channel.flags.contains(.isForum) && isMember { if let threadData = chatPresentationInterfaceState.threadData { if threadData.isClosed { var canManage = false diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index e74f736ce1..82fc983f3b 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -1396,17 +1396,9 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode } authorRank = attributes.rank } - - var enableAutoRank = false - if let authorRank = authorRank, case .admin = authorRank { - enableAutoRank = true - } else if authorRank == nil { - enableAutoRank = true - } - if enableAutoRank { - if let topicAuthorId = item.associatedData.topicAuthorId, topicAuthorId == message.author?.id { - authorRank = .custom(item.presentationData.strings.Chat_Message_TopicAuthorBadge) - } + + if authorRank == nil, let topicAuthorId = item.associatedData.topicAuthorId, topicAuthorId == message.author?.id { + authorRank = .custom(item.presentationData.strings.Chat_Message_TopicAuthorBadge) } case .group: break