diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 26d1043107..f7b9e72e03 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7612,3 +7612,6 @@ Sorry for the inconvenience."; "Conversation.CopyProtectionSavingDisabledSecret" = "Saving is restricted"; "Conversation.CopyProtectionForwardingDisabledSecret" = "Forwards are restricted"; + +"Settings.Terms_URL" = "https://telegram.org/tos"; +"Settings.PrivacyPolicy_URL" = "https://telegram.org/privacy"; diff --git a/submodules/ChatListUI/Sources/ChatContextMenus.swift b/submodules/ChatListUI/Sources/ChatContextMenus.swift index f61b11caaa..3de098e3ac 100644 --- a/submodules/ChatListUI/Sources/ChatContextMenus.swift +++ b/submodules/ChatListUI/Sources/ChatContextMenus.swift @@ -326,11 +326,11 @@ func chatContextMenuItems(context: AccountContext, peerId: PeerId, promoInfo: Ch switch result { case .done: f(.default) - case .limitExceeded: + case let .limitExceeded(count, _): f(.default) var replaceImpl: ((ViewController) -> Void)? - let controller = PremiumLimitScreen(context: context, subject: .pins, count: 0, action: { + let controller = PremiumLimitScreen(context: context, subject: .pins, count: Int32(count), action: { let premiumScreen = PremiumIntroScreen(context: context) replaceImpl?(premiumScreen) }) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index a2c8f32dd8..8a2ba8738a 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -160,6 +160,8 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController private var activeDownloadsDisposable: Disposable? private var clearUnseenDownloadsTimer: SwiftSignalKit.Timer? + private var isPremium: Bool = false + private var didSetupTabs = false public override func updateNavigationCustomData(_ data: Any?, progress: CGFloat, transition: ContainedViewLayoutTransition) { @@ -762,7 +764,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController strongSelf.tabContainerNode.cancelAnimations() strongSelf.chatListDisplayNode.inlineTabContainerNode.cancelAnimations() } - strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: false, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition) + strongSelf.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: strongSelf.isPremium, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition) strongSelf.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: tabContainerData.0, selectedFilter: filter, isReordering: strongSelf.chatListDisplayNode.isReorderingFilters || (strongSelf.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !strongSelf.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: fraction, presentationData: strongSelf.presentationData, transition: transition) } self.reloadFilters() @@ -833,7 +835,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController self.navigationBar?.updatePresentationData(NavigationBarPresentationData(presentationData: self.presentationData)) if let layout = self.validLayout { - self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: true, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate) + self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate) self.chatListDisplayNode.inlineTabContainerNode.update(size: CGSize(width: layout.size.width, height: 40.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: false, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .immediate) } @@ -1810,7 +1812,7 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController let navigationBarHeight = self.navigationBar?.frame.maxY ?? 0.0 transition.updateFrame(node: self.tabContainerNode, frame: CGRect(origin: CGPoint(x: 0.0, y: navigationBarHeight - self.additionalNavigationBarHeight - 46.0 + tabContainerOffset), size: CGSize(width: layout.size.width, height: 46.0))) - self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: true, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring)) + self.tabContainerNode.update(size: CGSize(width: layout.size.width, height: 46.0), sideInset: layout.safeInsets.left, filters: self.tabContainerData?.0 ?? [], selectedFilter: self.chatListDisplayNode.containerNode.currentItemFilter, isReordering: self.chatListDisplayNode.isReorderingFilters || (self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing && !self.chatListDisplayNode.didBeginSelectingChatsWhileEditing), isEditing: self.chatListDisplayNode.containerNode.currentItemNode.currentState.editing, canReorderAllChats: self.isPremium, transitionFraction: self.chatListDisplayNode.containerNode.transitionFraction, presentationData: self.presentationData, transition: .animated(duration: 0.4, curve: .spring)) if let tabContainerData = self.tabContainerData { self.chatListDisplayNode.inlineTabContainerNode.isHidden = !tabContainerData.1 || tabContainerData.0.count <= 1 } else { @@ -1947,14 +1949,15 @@ public class ChatListControllerImpl: TelegramBaseController, ChatListController ]), filterItems, displayTabsAtBottom, - self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) + self.context.account.postbox.peerView(id: self.context.account.peerId) ) - |> deliverOnMainQueue).start(next: { [weak self] _, countAndFilterItems, displayTabsAtBottom, accountPeer in + |> deliverOnMainQueue).start(next: { [weak self] _, countAndFilterItems, displayTabsAtBottom, peerView in guard let strongSelf = self else { return } - let isPremium = accountPeer?.isPremium ?? false + let isPremium = peerView.peers[peerView.peerId]?.isPremium ?? false + strongSelf.isPremium = isPremium let (_, items) = countAndFilterItems var filterItems: [ChatListFilterTabEntry] = [] diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 64aeebffc0..c57f9f9272 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -842,9 +842,9 @@ public final class ChatListNode: ListView { switch result { case .done: break - case .limitExceeded: + case let .limitExceeded(count, _): var replaceImpl: ((ViewController) -> Void)? - let controller = PremiumLimitScreen(context: context, subject: .pins, count: 0, action: { + let controller = PremiumLimitScreen(context: context, subject: .pins, count: Int32(count), action: { let premiumScreen = PremiumIntroScreen(context: context) replaceImpl?(premiumScreen) }) diff --git a/submodules/Components/MultilineTextComponent/Sources/MultilineTextComponent.swift b/submodules/Components/MultilineTextComponent/Sources/MultilineTextComponent.swift index 2aa41374a6..42ec14d704 100644 --- a/submodules/Components/MultilineTextComponent/Sources/MultilineTextComponent.swift +++ b/submodules/Components/MultilineTextComponent/Sources/MultilineTextComponent.swift @@ -20,6 +20,10 @@ public final class MultilineTextComponent: Component { public let insets: UIEdgeInsets public let textShadowColor: UIColor? public let textStroke: (UIColor, CGFloat)? + public let highlightColor: UIColor? + public let highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)? + public let tapAction: (([NSAttributedString.Key: Any], Int) -> Void)? + public let longTapAction: (([NSAttributedString.Key: Any], Int) -> Void)? public init( text: TextContent, @@ -31,7 +35,11 @@ public final class MultilineTextComponent: Component { cutout: TextNodeCutout? = nil, insets: UIEdgeInsets = UIEdgeInsets(), textShadowColor: UIColor? = nil, - textStroke: (UIColor, CGFloat)? = nil + textStroke: (UIColor, CGFloat)? = nil, + highlightColor: UIColor? = nil, + highlightAction: (([NSAttributedString.Key: Any]) -> NSAttributedString.Key?)? = nil, + tapAction: (([NSAttributedString.Key: Any], Int) -> Void)? = nil, + longTapAction: (([NSAttributedString.Key: Any], Int) -> Void)? = nil ) { self.text = text self.horizontalAlignment = horizontalAlignment @@ -43,6 +51,10 @@ public final class MultilineTextComponent: Component { self.insets = insets self.textShadowColor = textShadowColor self.textStroke = textStroke + self.highlightColor = highlightColor + self.highlightAction = highlightAction + self.tapAction = tapAction + self.longTapAction = longTapAction } public static func ==(lhs: MultilineTextComponent, rhs: MultilineTextComponent) -> Bool { @@ -90,10 +102,18 @@ public final class MultilineTextComponent: Component { return false } + if let lhsHighlightColor = lhs.highlightColor, let rhsHighlightColor = rhs.highlightColor { + if !lhsHighlightColor.isEqual(rhsHighlightColor) { + return false + } + } else if (lhs.highlightColor != nil) != (rhs.highlightColor != nil) { + return false + } + return true } - public final class View: TextView { + public final class View: ImmediateTextView { public func update(component: MultilineTextComponent, availableSize: CGSize) -> CGSize { let attributedString: NSAttributedString switch component.text { @@ -102,26 +122,25 @@ public final class MultilineTextComponent: Component { case let .markdown(text, attributes): attributedString = parseMarkdownIntoAttributedString(text, attributes: attributes) } + + self.attributedText = attributedString + self.maximumNumberOfLines = component.maximumNumberOfLines + self.truncationType = component.truncationType + self.textAlignment = component.horizontalAlignment + self.verticalAlignment = component.verticalAlignment + self.lineSpacing = component.lineSpacing + self.cutout = component.cutout + self.insets = component.insets + self.textShadowColor = component.textShadowColor + self.textStroke = component.textStroke + self.linkHighlightColor = component.highlightColor + self.highlightAttributeAction = component.highlightAction + self.tapAttributeAction = component.tapAction + self.longTapAttributeAction = component.longTapAction - let makeLayout = TextView.asyncLayout(self) - let (layout, apply) = makeLayout(TextNodeLayoutArguments( - attributedString: attributedString, - backgroundColor: nil, - maximumNumberOfLines: component.maximumNumberOfLines, - truncationType: component.truncationType, - constrainedSize: availableSize, - alignment: component.horizontalAlignment, - verticalAlignment: component.verticalAlignment, - lineSpacing: component.lineSpacing, - cutout: component.cutout, - insets: component.insets, - textShadowColor: component.textShadowColor, - textStroke: component.textStroke, - displaySpoilers: false - )) - let _ = apply() - - return layout.size + let size = self.updateLayout(availableSize) + + return size } } diff --git a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift index 9d322809da..ec7dc58860 100644 --- a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift +++ b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift @@ -59,6 +59,12 @@ open class ViewControllerComponentContainer: ViewController { case `default` } + public enum StatusBarStyle { + case none + case ignore + case `default` + } + public final class Environment: Equatable { public let statusBarHeight: CGFloat public let navigationHeight: CGFloat @@ -127,11 +133,11 @@ open class ViewControllerComponentContainer: ViewController { } public final class Node: ViewControllerTracingNode { - private var presentationData: PresentationData + fileprivate var presentationData: PresentationData private weak var controller: ViewControllerComponentContainer? private var component: AnyComponent - private let theme: PresentationTheme? + var theme: PresentationTheme? public let hostView: ComponentHostView private var currentIsVisible: Bool = false @@ -204,30 +210,68 @@ open class ViewControllerComponentContainer: ViewController { } private let context: AccountContext - private let theme: PresentationTheme? + private var theme: PresentationTheme? private let component: AnyComponent - public init(context: AccountContext, component: C, navigationBarAppearance: NavigationBarAppearance, theme: PresentationTheme? = nil) where C.EnvironmentType == ViewControllerComponentContainer.Environment { + private var presentationDataDisposable: Disposable? + private var validLayout: ContainerViewLayout? + + public init(context: AccountContext, component: C, navigationBarAppearance: NavigationBarAppearance, statusBarStyle: StatusBarStyle = .default, theme: PresentationTheme? = nil) where C.EnvironmentType == ViewControllerComponentContainer.Environment { self.context = context self.component = AnyComponent(component) self.theme = theme + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let navigationBarPresentationData: NavigationBarPresentationData? switch navigationBarAppearance { case .none: navigationBarPresentationData = nil case .transparent: - navigationBarPresentationData = NavigationBarPresentationData(presentationData: context.sharedContext.currentPresentationData.with { $0 }, hideBackground: true, hideBadge: false, hideSeparator: true) + navigationBarPresentationData = NavigationBarPresentationData(presentationData: presentationData, hideBackground: true, hideBadge: false, hideSeparator: true) case .default: - navigationBarPresentationData = NavigationBarPresentationData(presentationData: context.sharedContext.currentPresentationData.with { $0 }) + navigationBarPresentationData = NavigationBarPresentationData(presentationData: presentationData) } super.init(navigationBarPresentationData: navigationBarPresentationData) + + self.presentationDataDisposable = (self.context.sharedContext.presentationData + |> deliverOnMainQueue).start(next: { [weak self] presentationData in + if let strongSelf = self { + strongSelf.node.presentationData = presentationData + + switch statusBarStyle { + case .none: + strongSelf.statusBar.statusBarStyle = .Hide + case .ignore: + strongSelf.statusBar.statusBarStyle = .Ignore + case .default: + strongSelf.statusBar.statusBarStyle = presentationData.theme.rootController.statusBarStyle.style + } + + if let layout = strongSelf.validLayout { + strongSelf.containerLayoutUpdated(layout, transition: .immediate) + } + } + }) + + switch statusBarStyle { + case .none: + self.statusBar.statusBarStyle = .Hide + case .ignore: + self.statusBar.statusBarStyle = .Ignore + case .default: + self.statusBar.statusBarStyle = presentationData.theme.rootController.statusBarStyle.style + } } required public init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } + deinit { + self.presentationDataDisposable?.dispose() + } + override open func loadDisplayNode() { self.displayNode = Node(context: self.context, controller: self, component: self.component, theme: self.theme) @@ -255,6 +299,7 @@ open class ViewControllerComponentContainer: ViewController { let navigationHeight = self.navigationLayout(layout: layout).navigationFrame.maxY + self.validLayout = layout self.node.containerLayoutUpdated(layout: layout, navigationHeight: navigationHeight, transition: Transition(transition)) } diff --git a/submodules/ContextUI/Sources/PeekControllerContent.swift b/submodules/ContextUI/Sources/PeekControllerContent.swift index d770e1ad29..ba9b23d524 100644 --- a/submodules/ContextUI/Sources/PeekControllerContent.swift +++ b/submodules/ContextUI/Sources/PeekControllerContent.swift @@ -30,5 +30,7 @@ public protocol PeekControllerContentNode { } public protocol PeekControllerAccessoryNode { + var dismiss: () -> Void { get set } + func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) } diff --git a/submodules/ContextUI/Sources/PeekControllerNode.swift b/submodules/ContextUI/Sources/PeekControllerNode.swift index 8893b785da..1895dd2955 100644 --- a/submodules/ContextUI/Sources/PeekControllerNode.swift +++ b/submodules/ContextUI/Sources/PeekControllerNode.swift @@ -115,6 +115,9 @@ final class PeekControllerNode: ViewControllerTracingNode { self.addSubnode(self.actionsContainerNode) if let fullScreenAccessoryNode = self.fullScreenAccessoryNode { + self.fullScreenAccessoryNode?.dismiss = { [weak self] in + self?.requestDismiss() + } self.addSubnode(fullScreenAccessoryNode) } @@ -194,6 +197,7 @@ final class PeekControllerNode: ViewControllerTracingNode { if let fullScreenAccessoryNode = self.fullScreenAccessoryNode { fullScreenAccessoryNode.updateLayout(size: layout.size, transition: transition) + transition.updateFrame(node: fullScreenAccessoryNode, frame: CGRect(origin: .zero, size: layout.size)) } self.contentNodeHasValidLayout = true diff --git a/submodules/Display/Source/ImmediateTextNode.swift b/submodules/Display/Source/ImmediateTextNode.swift index 612fb81758..b7dae91235 100644 --- a/submodules/Display/Source/ImmediateTextNode.swift +++ b/submodules/Display/Source/ImmediateTextNode.swift @@ -226,7 +226,7 @@ public class ASTextNode: ImmediateTextNode { } } -public class ImmediateTextView: TextView { +open class ImmediateTextView: TextView { public var attributedText: NSAttributedString? public var textAlignment: NSTextAlignment = .natural public var verticalAlignment: TextVerticalAlignment = .top diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 5ce6f8cadf..99bfdc5ac8 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -4,7 +4,7 @@ import SwiftSignalKit private var backArrowImageCache: [Int32: UIImage] = [:] -public final class SparseNode: ASDisplayNode { +open class SparseNode: ASDisplayNode { override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { if self.alpha.isZero { return nil diff --git a/submodules/Display/Source/TextNode.swift b/submodules/Display/Source/TextNode.swift index fed1774a06..a5b9e8c6bc 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -1621,7 +1621,6 @@ open class TextView: UIView { private class func calculateLayout(attributedString: NSAttributedString?, minimumNumberOfLines: Int, maximumNumberOfLines: Int, truncationType: CTLineTruncationType, backgroundColor: UIColor?, constrainedSize: CGSize, alignment: NSTextAlignment, verticalAlignment: TextVerticalAlignment, lineSpacingFactor: CGFloat, cutout: TextNodeCutout?, insets: UIEdgeInsets, lineColor: UIColor?, textShadowColor: UIColor?, textStroke: (UIColor, CGFloat)?, displaySpoilers: Bool) -> TextNodeLayout { if let attributedString = attributedString { - let stringLength = attributedString.length let font: CTFont diff --git a/submodules/InstantPageCache/BUILD b/submodules/InstantPageCache/BUILD index 101fd0f887..0b2afced14 100644 --- a/submodules/InstantPageCache/BUILD +++ b/submodules/InstantPageCache/BUILD @@ -15,6 +15,8 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/TelegramUIPreferences:TelegramUIPreferences", "//submodules/PersistentStringHash:PersistentStringHash", + "//submodules/AccountContext:AccountContext", + "//submodules/UrlHandling:UrlHandling", ], visibility = [ "//visibility:public", diff --git a/submodules/InstantPageCache/Sources/CachedInternalInstantPages.swift b/submodules/InstantPageCache/Sources/CachedInternalInstantPages.swift new file mode 100644 index 0000000000..07d32a5e33 --- /dev/null +++ b/submodules/InstantPageCache/Sources/CachedInternalInstantPages.swift @@ -0,0 +1,88 @@ +import Foundation +import SwiftSignalKit +import Postbox +import TelegramCore +import AccountContext +//import InstantPageUI +import UrlHandling + +public func extractAnchor(string: String) -> (String, String?) { + var anchorValue: String? + if let anchorRange = string.range(of: "#") { + let anchor = string[anchorRange.upperBound...] + if !anchor.isEmpty { + anchorValue = String(anchor) + } + } + var trimmedUrl = string + if let anchor = anchorValue, let anchorRange = string.range(of: "#\(anchor)") { + let url = string[.. Signal { + var faqUrl = context.sharedContext.currentPresentationData.with { $0 }.strings.Settings_FAQ_URL + if faqUrl == "Settings.FAQ_URL" || faqUrl.isEmpty { + faqUrl = "https://telegram.org/faq#general-questions" + } + return cachedInternalInstantPage(context: context, url: faqUrl) +} + +public func cachedTermsPage(context: AccountContext) -> Signal { + var termsUrl = context.sharedContext.currentPresentationData.with { $0 }.strings.Settings_Terms_URL + if termsUrl == "Settings.Terms_URL" || termsUrl.isEmpty { + termsUrl = "https://telegram.org/tos" + } + return cachedInternalInstantPage(context: context, url: termsUrl) +} + +public func cachedPrivacyPage(context: AccountContext) -> Signal { + var privacyUrl = context.sharedContext.currentPresentationData.with { $0 }.strings.Settings_PrivacyPolicy_URL + if privacyUrl == "Settings.PrivacyPolicy_URL" || privacyUrl.isEmpty { + privacyUrl = "https://telegram.org/privacy" + } + return cachedInternalInstantPage(context: context, url: privacyUrl) +} + +private func cachedInternalInstantPage(context: AccountContext, url: String) -> Signal { + let (cachedUrl, anchor) = extractAnchor(string: url) + return cachedInstantPage(postbox: context.account.postbox, url: cachedUrl) + |> mapToSignal { cachedInstantPage -> Signal in + let updated = resolveInstantViewUrl(account: context.account, url: url) + |> afterNext { result in + if case let .instantView(webPage, _) = result, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage { + if instantPage.isComplete { + let _ = updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage).start() + } else { + let _ = (actualizedWebpage(postbox: context.account.postbox, network: context.account.network, webpage: webPage) + |> mapToSignal { webPage -> Signal in + if case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, instantPage.isComplete { + return updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage) + } else { + return .complete() + } + }).start() + } + } + } + + let now = Int32(CFAbsoluteTimeGetCurrent()) + if let cachedInstantPage = cachedInstantPage, case let .Loaded(content) = cachedInstantPage.webPage.content, let instantPage = content.instantPage, instantPage.isComplete { + let current: Signal = .single(.instantView(cachedInstantPage.webPage, anchor)) + if now > cachedInstantPage.timestamp + refreshTimeout { + return current + |> then(updated) + } else { + return current + } + } else { + return updated + } + } +} diff --git a/submodules/PremiumUI/BUILD b/submodules/PremiumUI/BUILD index a5be59dbc1..3bfca16d19 100644 --- a/submodules/PremiumUI/BUILD +++ b/submodules/PremiumUI/BUILD @@ -44,6 +44,7 @@ swift_library( "//submodules/ConfettiEffect:ConfettiEffect", "//submodules/TextFormat:TextFormat", "//submodules/GZip:GZip", + "//submodules/InstantPageCache:InstantPageCache", ], visibility = [ "//visibility:public", diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 8ad86c20f9..e7cc10b0ef 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -15,6 +15,7 @@ import Markdown import InAppPurchaseManager import ConfettiEffect import TextFormat +import InstantPageCache private final class SectionGroupComponent: Component { public final class Item: Equatable { @@ -884,7 +885,39 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { ), horizontalAlignment: .natural, maximumNumberOfLines: 0, - lineSpacing: 0.0 + lineSpacing: 0.0, + highlightColor: environment.theme.list.itemAccentColor.withAlphaComponent(0.3), + highlightAction: { attributes in + if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] { + return NSAttributedString.Key(rawValue: TelegramTextAttributes.URL) + } else { + return nil + } + }, + tapAction: { attributes, _ in + if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String, + let controller = environment.controller() as? PremiumIntroScreen, let navigationController = controller.navigationController as? NavigationController { + let context = controller.context + let signal: Signal? + switch url { + case "terms": + signal = cachedTermsPage(context: context) + case "privacy": + signal = cachedPrivacyPage(context: context) + default: + signal = nil + } + if let signal = signal { + let _ = (signal + |> deliverOnMainQueue).start(next: { resolvedUrl in + context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peer, navigation in + }, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { [weak controller] c, arguments in + controller?.push(c) + }, dismissInput: {}, contentContext: nil) + }) + } + } + } ), environment: {}, availableSize: CGSize(width: availableWidth - sideInsets - textSideInset * 2.0, height: .greatestFiniteMagnitude), @@ -1222,7 +1255,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { .opacity(bottomPanelAlpha) ) context.add(bottomSeparator - .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height - bottomPanel.size.height - bottomSeparator.size.height)) + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height - bottomPanel.size.height)) .opacity(bottomPanelAlpha) ) context.add(button @@ -1235,7 +1268,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { } public final class PremiumIntroScreen: ViewControllerComponentContainer { - private let context: AccountContext + fileprivate let context: AccountContext private var didSetReady = false private let _ready = Promise() diff --git a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift index 33942e5f52..93aacedcd6 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitScreen.swift @@ -599,7 +599,7 @@ private final class LimitSheetContent: CombinedComponent { let limit = state.limits.maxFoldersCount let premiumLimit = state.premiumLimits.maxFoldersCount iconName = "Premium/Folder" - badgeText = "\(limit)" + badgeText = "\(component.count)" string = strings.Premium_MaxFoldersCountText("\(limit)", "\(premiumLimit)").string defaultValue = component.count > limit ? "\(limit)" : "" premiumValue = "\(premiumLimit)" @@ -608,7 +608,7 @@ private final class LimitSheetContent: CombinedComponent { let limit = state.limits.maxFolderChatsCount let premiumLimit = state.premiumLimits.maxFolderChatsCount iconName = "Premium/Chat" - badgeText = "\(limit)" + badgeText = "\(component.count)" string = strings.Premium_MaxChatsInFolderCountText("\(limit)", "\(premiumLimit)").string defaultValue = component.count > limit ? "\(limit)" : "" premiumValue = "\(premiumLimit)" @@ -617,7 +617,7 @@ private final class LimitSheetContent: CombinedComponent { let limit = state.limits.maxPinnedChatCount let premiumLimit = state.premiumLimits.maxPinnedChatCount iconName = "Premium/Pin" - badgeText = "\(limit)" + badgeText = "\(component.count)" string = strings.Premium_MaxPinsText("\(limit)", "\(premiumLimit)").string defaultValue = component.count > limit ? "\(limit)" : "" premiumValue = "\(premiumLimit)" diff --git a/submodules/PremiumUI/Sources/PremiumReactionsScreen.swift b/submodules/PremiumUI/Sources/PremiumReactionsScreen.swift index 863e08a51d..6fc1794441 100644 --- a/submodules/PremiumUI/Sources/PremiumReactionsScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumReactionsScreen.swift @@ -11,7 +11,7 @@ import PresentationDataUtils import SolidRoundedButtonNode import AppBundle -public final class PremiumStickersScreen: ViewController { +public final class PremiumReactionsScreen: ViewController { private let context: AccountContext private var presentationData: PresentationData private var presentationDataDisposable: Disposable? @@ -21,7 +21,7 @@ public final class PremiumStickersScreen: ViewController { public var proceed: (() -> Void)? private class Node: ViewControllerTracingNode, UIGestureRecognizerDelegate { - private weak var controller: PremiumStickersScreen? + private weak var controller: PremiumReactionsScreen? private var presentationData: PresentationData private let blurView: UIVisualEffectView @@ -38,7 +38,7 @@ public final class PremiumStickersScreen: ViewController { private var validLayout: ContainerViewLayout? - init(controller: PremiumStickersScreen) { + init(controller: PremiumReactionsScreen) { self.controller = controller self.presentationData = controller.presentationData @@ -70,7 +70,14 @@ public final class PremiumStickersScreen: ViewController { self.overlayTextNode.maximumNumberOfLines = 0 self.overlayTextNode.lineSpacing = 0.1 - self.proceedButton = SolidRoundedButtonNode(title: self.presentationData.strings.Premium_Reactions_Proceed, icon: UIImage(bundleImageName: "Premium/ButtonIcon"), theme: SolidRoundedButtonTheme(theme: self.presentationData.theme), height: 50.0, cornerRadius: 11.0, gloss: true) + self.proceedButton = SolidRoundedButtonNode(title: self.presentationData.strings.Premium_Reactions_Proceed, icon: UIImage(bundleImageName: "Premium/ButtonIcon"), theme: SolidRoundedButtonTheme( + backgroundColor: .white, + backgroundColors: [ + UIColor(rgb: 0x0077ff), + UIColor(rgb: 0x6b93ff), + UIColor(rgb: 0x8878ff), + UIColor(rgb: 0xe46ace) + ], foregroundColor: .white), height: 50.0, cornerRadius: 11.0, gloss: true) self.cancelButton = HighlightableButtonNode() self.cancelButton.setTitle(self.presentationData.strings.Common_Cancel, with: Font.regular(17.0), with: self.presentationData.theme.list.itemAccentColor, for: .normal) @@ -78,7 +85,7 @@ public final class PremiumStickersScreen: ViewController { self.carouselNode = ReactionCarouselNode(context: controller.context, theme: controller.presentationData.theme, reactions: controller.reactions) super.init() - + self.addSubnode(self.dimNode) self.addSubnode(self.darkDimNode) self.addSubnode(self.containerNode) @@ -99,7 +106,10 @@ public final class PremiumStickersScreen: ViewController { self.overlayTextNode.attributedText = NSAttributedString(string: self.presentationData.strings.Premium_Reactions_Description, font: Font.regular(17.0), textColor: textColor) self.proceedButton.pressed = { [weak self] in - self?.animateOut() + if let strongSelf = self, let controller = strongSelf.controller, let navigationController = controller.navigationController { + strongSelf.animateOut() + navigationController.pushViewController(PremiumIntroScreen(context: controller.context), animated: true) + } } self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside) @@ -209,6 +219,8 @@ public final class PremiumStickersScreen: ViewController { super.init(navigationBarPresentationData: nil) + self.navigationPresentation = .flatModal + self.statusBar.statusBarStyle = .Ignore self.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait) diff --git a/submodules/SettingsUI/Sources/CachedFaqInstantPage.swift b/submodules/SettingsUI/Sources/CachedFaqInstantPage.swift index cd108a673f..93671bb8e0 100644 --- a/submodules/SettingsUI/Sources/CachedFaqInstantPage.swift +++ b/submodules/SettingsUI/Sources/CachedFaqInstantPage.swift @@ -7,69 +7,6 @@ import InstantPageUI import InstantPageCache import UrlHandling -private func extractAnchor(string: String) -> (String, String?) { - var anchorValue: String? - if let anchorRange = string.range(of: "#") { - let anchor = string[anchorRange.upperBound...] - if !anchor.isEmpty { - anchorValue = String(anchor) - } - } - var trimmedUrl = string - if let anchor = anchorValue, let anchorRange = string.range(of: "#\(anchor)") { - let url = string[.. Signal { - var faqUrl = context.sharedContext.currentPresentationData.with { $0 }.strings.Settings_FAQ_URL - if faqUrl == "Settings.FAQ_URL" || faqUrl.isEmpty { - faqUrl = "https://telegram.org/faq#general-questions" - } - - let (cachedUrl, anchor) = extractAnchor(string: faqUrl) - - return cachedInstantPage(postbox: context.account.postbox, url: cachedUrl) - |> mapToSignal { cachedInstantPage -> Signal in - let updated = resolveInstantViewUrl(account: context.account, url: faqUrl) - |> afterNext { result in - if case let .instantView(webPage, _) = result, case let .Loaded(content) = webPage.content, let instantPage = content.instantPage { - if instantPage.isComplete { - let _ = updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage).start() - } else { - let _ = (actualizedWebpage(postbox: context.account.postbox, network: context.account.network, webpage: webPage) - |> mapToSignal { webPage -> Signal in - if case let .Loaded(content) = webPage.content, let instantPage = content.instantPage, instantPage.isComplete { - return updateCachedInstantPage(postbox: context.account.postbox, url: cachedUrl, webPage: webPage) - } else { - return .complete() - } - }).start() - } - } - } - - let now = Int32(CFAbsoluteTimeGetCurrent()) - if let cachedInstantPage = cachedInstantPage, case let .Loaded(content) = cachedInstantPage.webPage.content, let instantPage = content.instantPage, instantPage.isComplete { - let current: Signal = .single(.instantView(cachedInstantPage.webPage, anchor)) - if now > cachedInstantPage.timestamp + refreshTimeout { - return current - |> then(updated) - } else { - return current - } - } else { - return updated - } - } -} - func faqSearchableItems(context: AccountContext, resolvedUrl: Signal, suggestAccountDeletion: Bool) -> Signal<[SettingsSearchableItem], NoError> { let strings = context.sharedContext.currentPresentationData.with { $0 }.strings return resolvedUrl diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index 6d91abfc47..ebff87f703 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -236,7 +236,9 @@ final class StickerPackPreviewControllerNode: ViewControllerTracingNode, UIScrol } }))) } - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + + })) } else { return nil } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index dd7787860e..dd860b9ee5 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -369,7 +369,9 @@ private final class StickerPackContainer: ASDisplayNode { } }))) } - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + + })) } else { return nil } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift b/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift index 99c1c30edd..022e2a5bd6 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift @@ -35,8 +35,9 @@ public final class StickerPreviewPeekContent: PeekControllerContent { public let item: StickerPreviewPeekItem let isLocked: Bool let menu: [ContextMenuItem] + let openPremiumIntro: () -> Void - public init(account: Account, theme: PresentationTheme, strings: PresentationStrings, item: StickerPreviewPeekItem, isLocked: Bool = false, menu: [ContextMenuItem]) { + public init(account: Account, theme: PresentationTheme, strings: PresentationStrings, item: StickerPreviewPeekItem, isLocked: Bool = false, menu: [ContextMenuItem], openPremiumIntro: @escaping () -> Void) { self.account = account self.theme = theme self.strings = strings @@ -47,6 +48,7 @@ public final class StickerPreviewPeekContent: PeekControllerContent { } else { self.menu = menu } + self.openPremiumIntro = openPremiumIntro } public func presentation() -> PeekControllerContentPresentation { @@ -71,7 +73,7 @@ public final class StickerPreviewPeekContent: PeekControllerContent { public func fullScreenAccessoryNode(blurView: UIVisualEffectView) -> (PeekControllerAccessoryNode & ASDisplayNode)? { if self.isLocked { - return PremiumStickerPackAccessoryNode(theme: self.theme, strings: self.strings) + return PremiumStickerPackAccessoryNode(theme: self.theme, strings: self.strings, proceed: self.openPremiumIntro) } else { return nil } @@ -211,12 +213,17 @@ public final class StickerPreviewPeekContentNode: ASDisplayNode, PeekControllerC } } -final class PremiumStickerPackAccessoryNode: ASDisplayNode, PeekControllerAccessoryNode { +final class PremiumStickerPackAccessoryNode: SparseNode, PeekControllerAccessoryNode { + var dismiss: () -> Void = {} + let proceed: () -> Void + let textNode: ImmediateTextNode let proceedButton: SolidRoundedButtonNode let cancelButton: HighlightableButtonNode - init(theme: PresentationTheme, strings: PresentationStrings) { + init(theme: PresentationTheme, strings: PresentationStrings, proceed: @escaping () -> Void) { + self.proceed = proceed + self.textNode = ImmediateTextNode() self.textNode.displaysAsynchronously = false self.textNode.textAlignment = .center @@ -224,7 +231,14 @@ final class PremiumStickerPackAccessoryNode: ASDisplayNode, PeekControllerAccess self.textNode.attributedText = NSAttributedString(string: strings.Premium_Stickers_Description, font: Font.regular(17.0), textColor: theme.actionSheet.secondaryTextColor) self.textNode.lineSpacing = 0.1 - self.proceedButton = SolidRoundedButtonNode(title: strings.Premium_Stickers_Proceed, icon: UIImage(bundleImageName: "Premium/ButtonIcon"), theme: SolidRoundedButtonTheme(theme: theme), height: 50.0, cornerRadius: 11.0, gloss: true) + self.proceedButton = SolidRoundedButtonNode(title: strings.Premium_Stickers_Proceed, icon: UIImage(bundleImageName: "Premium/ButtonIcon"), theme: SolidRoundedButtonTheme( + backgroundColor: .white, + backgroundColors: [ + UIColor(rgb: 0x0077ff), + UIColor(rgb: 0x6b93ff), + UIColor(rgb: 0x8878ff), + UIColor(rgb: 0xe46ace) + ], foregroundColor: .white), height: 50.0, cornerRadius: 11.0, gloss: true) self.cancelButton = HighlightableButtonNode() self.cancelButton.setTitle(strings.Common_Cancel, with: Font.regular(17.0), with: theme.list.itemAccentColor, for: .normal) @@ -235,14 +249,14 @@ final class PremiumStickerPackAccessoryNode: ASDisplayNode, PeekControllerAccess self.addSubnode(self.proceedButton) self.addSubnode(self.cancelButton) - self.proceedButton.pressed = { - + self.proceedButton.pressed = { [weak self] in + self?.proceed() } self.cancelButton.addTarget(self, action: #selector(self.cancelPressed), forControlEvents: .touchUpInside) } @objc func cancelPressed() { - + self.dismiss() } func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TogglePeerChatPinned.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TogglePeerChatPinned.swift index 1a9a7d2a5f..e329d996d3 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TogglePeerChatPinned.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TogglePeerChatPinned.swift @@ -52,7 +52,7 @@ func _internal_toggleItemPinned(postbox: Postbox, accountPeerId: PeerId, locatio let count = sameKind.count + additionalCount if count > limitCount, itemIds.firstIndex(of: itemId) == nil { - return .limitExceeded(count: count, limit: limitCount) + return .limitExceeded(count: sameKind.count, limit: limitCount) } else { if let index = itemIds.firstIndex(of: itemId) { itemIds.remove(at: index) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index f2f176f5fc..bccdf1eaf2 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1095,8 +1095,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G if case .premium = value { controller?.dismiss() - let controller = PremiumStickersScreen(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, reactions: premiumReactions) - strongSelf.present(controller, in: .window(.root)) + let controller = PremiumReactionsScreen(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, reactions: premiumReactions) + strongSelf.push(controller) return } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index 5a6c14d730..845131605f 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -1617,7 +1617,9 @@ final class ChatMediaInputNode: ChatInputNode { } } }))) - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: item, menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: item, menu: menuItems, openPremiumIntro: { + + })) } else { return nil } @@ -1743,7 +1745,9 @@ final class ChatMediaInputNode: ChatInputNode { } })) ) - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), isLocked: item.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + + })) } else { return nil } diff --git a/submodules/TelegramUI/Sources/ChatTitleView.swift b/submodules/TelegramUI/Sources/ChatTitleView.swift index 0822142af5..9c84aa6a0f 100644 --- a/submodules/TelegramUI/Sources/ChatTitleView.swift +++ b/submodules/TelegramUI/Sources/ChatTitleView.swift @@ -621,6 +621,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView { self.strings = strings let titleContent = self.titleContent + self.titleCredibilityIcon = .none self.titleContent = titleContent let _ = self.updateStatus() diff --git a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift index 0c9160ae16..c5aa863376 100644 --- a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift +++ b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift @@ -531,7 +531,9 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: item, menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: item, menu: menuItems, openPremiumIntro: { + + })) } else { return nil } @@ -595,7 +597,9 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.presentationData.theme, strings: strongSelf.presentationData.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { + + })) } else { return nil } diff --git a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift index 4f9b362ab9..3402e0effb 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -174,7 +174,9 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont } }))) } - selectedItemNodeAndContent = (itemNode, StickerPreviewPeekContent(account: item.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .found(FoundStickerItem(file: file, stringRepresentations: [])), menu: menuItems)) + selectedItemNodeAndContent = (itemNode, StickerPreviewPeekContent(account: item.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .found(FoundStickerItem(file: file, stringRepresentations: [])), menu: menuItems, openPremiumIntro: { + + })) } else { var menuItems: [ContextMenuItem] = [] if case let .internalReference(internalReference) = item.result, let file = internalReference.file, file.isAnimated { diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index 6a15cb7543..39aa0c3c87 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -220,7 +220,9 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { + + })) } else { return nil } diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index ba1d5a9529..10ec47256d 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -175,7 +175,9 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie } })) ) - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { + + })) } else { return nil } diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index 0a675f3210..26831d0301 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -176,7 +176,9 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { } })) ] - return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems)) + return (itemNode, StickerPreviewPeekContent(account: strongSelf.context.account, theme: strongSelf.theme, strings: strongSelf.strings, item: .pack(item), menu: menuItems, openPremiumIntro: { + + })) } else { return nil }