diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 22e8723a27..c28ea26dda 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -8155,3 +8155,7 @@ Sorry for the inconvenience."; "ChatList.SelectedTopics_1" = "%@ Topic Selected"; "ChatList.SelectedTopics_any" = "%@ Topics Selected"; + +"ChatList.EmptyTopicsTitle" = "No topics here yet"; +"ChatList.EmptyTopicsCreate" = "Create New Topic"; +"ChatList.EmptyTopicsShowAsMessages" = "Show as Messages"; diff --git a/submodules/ChatListUI/Sources/ChatListEmptyNode.swift b/submodules/ChatListUI/Sources/ChatListEmptyNode.swift index c83e113635..50ce74a103 100644 --- a/submodules/ChatListUI/Sources/ChatListEmptyNode.swift +++ b/submodules/ChatListUI/Sources/ChatListEmptyNode.swift @@ -29,6 +29,7 @@ final class ChatListEmptyNode: ASDisplayNode { private let activityIndicator: ActivityIndicator private var animationSize: CGSize = CGSize() + private var buttonIsHidden: Bool private var validLayout: CGSize? @@ -65,6 +66,16 @@ final class ChatListEmptyNode: ASDisplayNode { self.activityIndicator = ActivityIndicator(type: .custom(theme.list.itemAccentColor, 22.0, 1.0, false)) + var buttonIsHidden = false + let animationName: String + if case let .filter(showEdit) = subject { + animationName = "ChatListFilterEmpty" + buttonIsHidden = !showEdit + } else { + animationName = "ChatListEmpty" + } + self.buttonIsHidden = buttonIsHidden + super.init() self.addSubnode(self.animationNode) @@ -73,15 +84,7 @@ final class ChatListEmptyNode: ASDisplayNode { self.addSubnode(self.buttonNode) self.addSubnode(self.secondaryButtonNode) self.addSubnode(self.activityIndicator) - - let animationName: String - if case let .filter(showEdit) = subject { - animationName = "ChatListFilterEmpty" - self.buttonNode.isHidden = !showEdit - } else { - animationName = "ChatListEmpty" - } - + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 248, height: 248, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) self.animationSize = CGSize(width: 124.0, height: 124.0) self.animationNode.visibility = true @@ -89,7 +92,7 @@ final class ChatListEmptyNode: ASDisplayNode { self.animationNode.isHidden = self.isLoading self.textNode.isHidden = self.isLoading self.descriptionNode.isHidden = self.isLoading - self.buttonNode.isHidden = self.isLoading + self.buttonNode.isHidden = self.buttonIsHidden || self.isLoading self.activityIndicator.isHidden = !self.isLoading self.buttonNode.hitTestSlop = UIEdgeInsets(top: -10.0, left: -10.0, bottom: -10.0, right: -10.0) @@ -138,9 +141,9 @@ final class ChatListEmptyNode: ASDisplayNode { descriptionText = strings.ChatList_EmptyChatListFilterText buttonText = strings.ChatList_EmptyChatListEditFilter case .forum: - text = "No topics here yet" - buttonText = "Create New Topic" - secondaryButtonText = "Show as Messages" + text = strings.ChatList_EmptyTopicsTitle + buttonText = strings.ChatList_EmptyTopicsCreate + secondaryButtonText = strings.ChatList_EmptyTopicsShowAsMessages } let string = NSMutableAttributedString(string: text, font: Font.medium(17.0), textColor: theme.list.itemPrimaryTextColor) let descriptionString = NSAttributedString(string: descriptionText, font: Font.regular(14.0), textColor: theme.list.itemSecondaryTextColor) @@ -167,7 +170,7 @@ final class ChatListEmptyNode: ASDisplayNode { self.animationNode.isHidden = self.isLoading self.textNode.isHidden = self.isLoading self.descriptionNode.isHidden = self.isLoading - self.buttonNode.isHidden = self.isLoading + self.buttonNode.isHidden = self.buttonIsHidden || self.isLoading self.activityIndicator.isHidden = !self.isLoading } diff --git a/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift b/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift index 435df4d5bc..6fe0092fb2 100644 --- a/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift +++ b/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift @@ -284,6 +284,7 @@ public final class SelectablePeerNode: ASDisplayNode { self.checkNode = nil checkNode.setSelected(false, animated: animated) } + self.setNeedsLayout() } } diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index d1b9fa5a7f..e77b9eea85 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -307,8 +307,14 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate strongSelf.peersContentNode?.updateSelectedPeers(animated: false) strongSelf.updateButton() + + if let peersContentNode = strongSelf.peersContentNode, strongSelf.contentNode !== peersContentNode { + strongSelf.transitionToContentNode(peersContentNode, animated: true) + peersContentNode.prepareForAnimateIn() + } + Queue.mainQueue().after(0.01, { - strongSelf.closePeerTopics(peer.peerId) + strongSelf.closePeerTopics(peer.peerId, selected: true) }) } }) @@ -387,7 +393,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate ) topicsContentNode.backPressed = { [weak self] in if let strongSelf = self { - strongSelf.closePeerTopics(peer.peerId) + strongSelf.closePeerTopics(peer.peerId, selected: false) } } strongSelf.topicsContentNode = topicsContentNode @@ -415,21 +421,23 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate self?.contentNodeOffsetUpdated(contentOffset, transition: transition) }) strongSelf.contentNodeOffsetUpdated(topicsContentNode.contentGridNode.scrollView.contentOffset.y, transition: .animated(duration: 0.4, curve: .spring)) + + strongSelf.view.endEditing(true) }) } - func closePeerTopics(_ peerId: EnginePeer.Id) { + func closePeerTopics(_ peerId: EnginePeer.Id, selected: Bool) { guard let topicsContentNode = self.topicsContentNode else { return } topicsContentNode.setContentOffsetUpdated(nil) - + if let searchContentNode = self.contentNode as? ShareSearchContainerNode { topicsContentNode.supernode?.insertSubnode(topicsContentNode, belowSubnode: searchContentNode) } else if let peersContentNode = self.peersContentNode { topicsContentNode.supernode?.insertSubnode(topicsContentNode, belowSubnode: peersContentNode) } - + if let (layout, navigationBarHeight, _) = self.containerLayout { self.containerLayoutUpdated(layout, navigationBarHeight: navigationBarHeight, transition: .animated(duration: 0.4, curve: .spring)) } @@ -677,7 +685,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate if let topicsContentNode = self.topicsContentNode { transition.updateFrame(node: topicsContentNode, frame: CGRect(origin: CGPoint(x: floor((contentContainerFrame.size.width - contentFrame.size.width) / 2.0), y: titleAreaHeight), size: gridSize)) - topicsContentNode.updateLayout(size: gridSize, isLandscape: layout.size.width > layout.size.height, bottomInset: bottomGridInset, transition: transition) + + topicsContentNode.updateLayout(size: gridSize, isLandscape: layout.size.width > layout.size.height, bottomInset: self.contentNode === self.peersContentNode ? bottomGridInset : 0.0, transition: transition) } } diff --git a/submodules/ShareController/Sources/SharePeersContainerNode.swift b/submodules/ShareController/Sources/SharePeersContainerNode.swift index 9f1f0b61de..f21342381a 100644 --- a/submodules/ShareController/Sources/SharePeersContainerNode.swift +++ b/submodules/ShareController/Sources/SharePeersContainerNode.swift @@ -118,7 +118,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { let contentGridNode: GridNode private let headerNode: ASDisplayNode private let contentTitleNode: ASTextNode - private let contentSubtitleNode: ASTextNode + private let contentSubtitleNode: ImmediateTextNode private let contentTitleAccountNode: AvatarNode private let contentSeparatorNode: ASDisplayNode private let searchButtonNode: HighlightableButtonNode @@ -199,7 +199,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { self.contentTitleNode = ASTextNode() self.contentTitleNode.attributedText = NSAttributedString(string: strings.ShareMenu_ShareTo, font: Font.medium(20.0), textColor: self.theme.actionSheet.primaryTextColor) - self.contentSubtitleNode = ASTextNode() + self.contentSubtitleNode = ImmediateTextNode() self.contentSubtitleNode.maximumNumberOfLines = 1 self.contentSubtitleNode.isUserInteractionEnabled = false self.contentSubtitleNode.displaysAsynchronously = false @@ -378,6 +378,14 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { } } + func prepareForAnimateIn() { + self.searchButtonNode.alpha = 0.0 + self.shareButtonNode.alpha = 0.0 + self.contentTitleNode.alpha = 0.0 + self.contentSubtitleNode.alpha = 0.0 + self.contentGridNode.alpha = 0.0 + } + func animateIn(peerId: EnginePeer.Id, scrollDelta: CGFloat) -> CGRect? { self.headerNode.layer.animatePosition(from: CGPoint(x: 0.0, y: -scrollDelta), to: .zero, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring, additive: true) @@ -419,11 +427,10 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { maskView.addSubview(maskImageView) clippedNode.view.mask = maskView - self.contentGridNode.alpha = 1.0 self.contentGridNode.forEachItemNode { itemNode in if let itemNode = itemNode as? ShareControllerPeerGridItemNode, itemNode.peerId == peerId { - itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, removeOnCompletion: false) + itemNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15) itemNode.layer.animateScale(from: 1.35, to: 1.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, completion: { [weak clippedNode] _ in clippedNode?.view.removeFromSuperview() }) @@ -577,7 +584,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: 15.0), size: titleSize) transition.updateFrame(node: self.contentTitleNode, frame: titleFrame) - let subtitleSize = self.contentSubtitleNode.measure(CGSize(width: size.width - 44.0 * 2.0 - 8.0 * 2.0, height: titleAreaHeight)) + let subtitleSize = self.contentSubtitleNode.updateLayout(CGSize(width: size.width - 44.0 * 2.0 - 8.0 * 2.0, height: titleAreaHeight)) let subtitleFrame = CGRect(origin: CGPoint(x: floor((size.width - subtitleSize.width) / 2.0), y: 40.0), size: subtitleSize) var originalSubtitleFrame = self.contentSubtitleNode.frame originalSubtitleFrame.origin.x = subtitleFrame.origin.x diff --git a/submodules/ShareController/Sources/ShareTopicsContainerNode.swift b/submodules/ShareController/Sources/ShareTopicsContainerNode.swift index 1ab6f849cf..eebaac0dc3 100644 --- a/submodules/ShareController/Sources/ShareTopicsContainerNode.swift +++ b/submodules/ShareController/Sources/ShareTopicsContainerNode.swift @@ -128,7 +128,7 @@ private class CancelButtonNode: ASDisplayNode { let labelSize = self.labelNode.updateLayout(CGSize(width: 120.0, height: 56.0)) - self.buttonNode.frame = CGRect(origin: .zero, size: CGSize(width: labelSize.width, height: self.buttonNode.frame.height)) + self.buttonNode.frame = CGRect(origin: .zero, size: CGSize(width: labelSize.width + 16.0, height: self.buttonNode.frame.height)) self.arrowNode.image = NavigationBarTheme.generateBackArrowImage(color: self.theme.rootController.navigationBar.accentTextColor) if let image = self.arrowNode.image { self.arrowNode.frame = CGRect(origin: self.arrowNode.frame.origin, size: image.size) @@ -142,7 +142,7 @@ private class CancelButtonNode: ASDisplayNode { self.arrowNode.frame = CGRect(origin: CGPoint(x: -19.0, y: floorToScreenPixels((constrainedSize.height - self.arrowNode.frame.size.height) / 2.0)), size: self.arrowNode.frame.size) self.labelNode.frame = CGRect(origin: CGPoint(x: 0.0, y: floorToScreenPixels((constrainedSize.height - self.labelNode.frame.size.height) / 2.0)), size: self.labelNode.frame.size) - return CGSize(width: 70.0, height: 56.0) + return CGSize(width: self.buttonNode.frame.width, height: 56.0) } } @@ -207,7 +207,9 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode { self.headerNode = ASDisplayNode() self.contentTitleNode = ASTextNode() + self.contentTitleNode.maximumNumberOfLines = 1 self.contentTitleNode.attributedText = NSAttributedString(string: peer.compactDisplayTitle, font: Font.medium(20.0), textColor: self.theme.actionSheet.primaryTextColor) + self.contentTitleNode.textAlignment = .center self.contentSubtitleNode = ASTextNode() self.contentSubtitleNode.maximumNumberOfLines = 1 @@ -425,7 +427,11 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode { let headerFrame = CGRect(origin: CGPoint(x: 0.0, y: titleOffset), size: CGSize(width: size.width, height: 64.0)) transition.updateFrame(node: self.headerNode, frame: headerFrame) - let titleSize = self.contentTitleNode.measure(size) + let backSize = self.backNode.measure(CGSize(width: size.width, height: 56.0)) + let backFrame = CGRect(origin: CGPoint(x: 20.0, y: 6.0), size: CGSize(width: backSize.width, height: 56.0)) + transition.updateFrame(node: self.backNode, frame: backFrame) + + let titleSize = self.contentTitleNode.measure(CGSize(width: size.width - (backSize.width * 2.0 + 40.0), height: size.height)) let titleFrame = CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: 15.0), size: titleSize) transition.updateFrame(node: self.contentTitleNode, frame: titleFrame) @@ -437,8 +443,7 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode { self.contentSubtitleNode.frame = originalSubtitleFrame transition.updateFrame(node: self.contentSubtitleNode, frame: subtitleFrame) - let backFrame = CGRect(origin: CGPoint(x: 30.0, y: 6.0), size: CGSize(width: 90.0, height: 56.0)) - transition.updateFrame(node: self.backNode, frame: backFrame) + self.contentOffsetUpdated?(presentationLayout.contentOffset.y, actualTransition) }