diff --git a/submodules/Display/Source/ContextMenuAction.swift b/submodules/Display/Source/ContextMenuAction.swift index 37a766860b..3660673cfd 100644 --- a/submodules/Display/Source/ContextMenuAction.swift +++ b/submodules/Display/Source/ContextMenuAction.swift @@ -4,6 +4,7 @@ public enum ContextMenuActionContent { case text(title: String, accessibilityLabel: String) case icon(UIImage) case textWithIcon(title: String, icon: UIImage?) + case textWithSubtitleAndIcon(title: String, subtitle: String, icon: UIImage?) } public struct ContextMenuAction { diff --git a/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift b/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift index 1b7bb28e75..afa49a37d3 100644 --- a/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift +++ b/submodules/DrawingUI/Sources/DrawingStickerEntityView.swift @@ -697,6 +697,10 @@ public class DrawingStickerEntityView: DrawingEntityView { override func selectedTapAction() -> Bool { if case let .link(url, name, positionBelowText, largeMedia, size, compactSize, style) = self.stickerEntity.content { + let values = [self.entity.scale, self.entity.scale * 0.93, self.entity.scale] + let keyTimes = [0.0, 0.33, 1.0] + self.layer.animateKeyframes(values: values as [NSNumber], keyTimes: keyTimes as [NSNumber], duration: 0.3, keyPath: "transform.scale") + let updatedStyle: DrawingStickerEntity.Content.LinkStyle switch style { case .white: diff --git a/submodules/TelegramCore/Sources/Account/AccountManager.swift b/submodules/TelegramCore/Sources/Account/AccountManager.swift index 5996ab1ca2..5002caddf2 100644 --- a/submodules/TelegramCore/Sources/Account/AccountManager.swift +++ b/submodules/TelegramCore/Sources/Account/AccountManager.swift @@ -216,6 +216,7 @@ private var declaredEncodables: Void = { declareEncodable(SynchronizeViewStoriesOperation.self, f: { SynchronizeViewStoriesOperation(decoder: $0) }) declareEncodable(SynchronizePeerStoriesOperation.self, f: { SynchronizePeerStoriesOperation(decoder: $0) }) declareEncodable(MapVenue.self, f: { MapVenue(decoder: $0) }) + declareEncodable(MapGeoAddress.self, f: { MapGeoAddress(decoder: $0) }) declareEncodable(TelegramMediaGiveaway.self, f: { TelegramMediaGiveaway(decoder: $0) }) declareEncodable(TelegramMediaGiveawayResults.self, f: { TelegramMediaGiveawayResults(decoder: $0) }) declareEncodable(WebpagePreviewMessageAttribute.self, f: { WebpagePreviewMessageAttribute(decoder: $0) }) diff --git a/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuActionNode.swift b/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuActionNode.swift index 4d803b4a96..6f00594791 100644 --- a/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuActionNode.swift +++ b/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuActionNode.swift @@ -15,7 +15,9 @@ final private class ContextMenuActionButton: HighlightTrackingButton { final class ContextMenuActionNode: ASDisplayNode { private let textNode: ImmediateTextNode? + private let subtitleNode: ImmediateTextNode? private var textSize: CGSize? + private var subtitleSize: CGSize? private let iconView: UIImageView? private let action: () -> Void private let button: ContextMenuActionButton @@ -28,37 +30,60 @@ final class ContextMenuActionNode: ASDisplayNode { self.actionArea.accessibilityTraits = .button switch action.content { - case let .text(title, accessibilityLabel): - self.actionArea.accessibilityLabel = accessibilityLabel - - let textNode = ImmediateTextNode() - textNode.isUserInteractionEnabled = false - textNode.displaysAsynchronously = false - textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: isDark ? .white : .black) - textNode.isAccessibilityElement = false - - self.textNode = textNode - self.iconView = nil - case let .textWithIcon(title, icon): - let textNode = ImmediateTextNode() - textNode.isUserInteractionEnabled = false - textNode.displaysAsynchronously = false - textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: isDark ? .white : .black) - textNode.isAccessibilityElement = false + case let .text(title, accessibilityLabel): + self.actionArea.accessibilityLabel = accessibilityLabel - let iconView = UIImageView() - iconView.tintColor = isDark ? .white : .black - iconView.image = icon - - self.textNode = textNode - self.iconView = iconView - case let .icon(image): - let iconView = UIImageView() - iconView.tintColor = isDark ? .white : .black - iconView.image = image - - self.iconView = iconView - self.textNode = nil + let textNode = ImmediateTextNode() + textNode.isUserInteractionEnabled = false + textNode.displaysAsynchronously = false + textNode.attributedText = NSAttributedString(string: title, font: Font.regular(14.0), textColor: isDark ? .white : .black) + textNode.isAccessibilityElement = false + + self.textNode = textNode + self.subtitleNode = nil + self.iconView = nil + case let .textWithIcon(title, icon): + let textNode = ImmediateTextNode() + textNode.isUserInteractionEnabled = false + textNode.displaysAsynchronously = false + textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: isDark ? .white : .black) + textNode.isAccessibilityElement = false + + let iconView = UIImageView() + iconView.tintColor = isDark ? .white : .black + iconView.image = icon + + self.textNode = textNode + self.subtitleNode = nil + self.iconView = iconView + case let .textWithSubtitleAndIcon(title, subtitle, icon): + let textNode = ImmediateTextNode() + textNode.isUserInteractionEnabled = false + textNode.displaysAsynchronously = false + textNode.attributedText = NSAttributedString(string: title, font: Font.regular(17.0), textColor: isDark ? .white : .black) + textNode.isAccessibilityElement = false + + let subtitleNode = ImmediateTextNode() + subtitleNode.isUserInteractionEnabled = false + subtitleNode.displaysAsynchronously = false + subtitleNode.attributedText = NSAttributedString(string: subtitle, font: Font.regular(12.0), textColor: (isDark ? UIColor.white : UIColor.black).withAlphaComponent(0.5)) + subtitleNode.isAccessibilityElement = false + + let iconView = UIImageView() + iconView.tintColor = isDark ? .white : .black + iconView.image = icon + + self.textNode = textNode + self.subtitleNode = subtitleNode + self.iconView = iconView + case let .icon(image): + let iconView = UIImageView() + iconView.tintColor = isDark ? .white : .black + iconView.image = image + + self.iconView = iconView + self.textNode = nil + self.subtitleNode = nil } self.action = action.action @@ -74,6 +99,9 @@ final class ContextMenuActionNode: ASDisplayNode { if let textNode = self.textNode { self.addSubnode(textNode) } + if let subtitleNode = self.subtitleNode { + self.addSubnode(subtitleNode) + } if let iconView = self.iconView { self.view.addSubview(iconView) } @@ -119,7 +147,16 @@ final class ContextMenuActionNode: ASDisplayNode { self.textSize = textSize var totalWidth = 0.0 + var totalHeight: CGFloat = 54.0 totalWidth += textSize.width + + if let subtitleNode = self.subtitleNode { + let subtitleSize = subtitleNode.updateLayout(constrainedSize) + self.subtitleSize = subtitleSize + totalWidth = max(totalWidth, subtitleSize.width) + totalHeight += 14.0 + } + if let image = self.iconView?.image { if totalWidth > 0.0 { totalWidth += 11.0 @@ -130,7 +167,7 @@ final class ContextMenuActionNode: ASDisplayNode { totalWidth += 36.0 } - return CGSize(width: totalWidth, height: 54.0) + return CGSize(width: totalWidth, height: totalHeight) } else if let iconView = self.iconView, let image = iconView.image { return CGSize(width: image.size.width + 36.0, height: 54.0) } else { @@ -148,6 +185,9 @@ final class ContextMenuActionNode: ASDisplayNode { if let textSize = self.textSize { totalWidth += textSize.width } + if let subtitleSize = self.subtitleSize { + totalWidth = max(totalWidth, subtitleSize.width) + } if let image = self.iconView?.image { if totalWidth > 0.0 { totalWidth += 11.0 @@ -155,8 +195,18 @@ final class ContextMenuActionNode: ASDisplayNode { totalWidth += image.size.width } + var totalTextHeight: CGFloat = 0.0 + if let textSize = self.textSize { + totalTextHeight += textSize.height + } + if let subtitleSize = self.subtitleSize { + totalTextHeight += subtitleSize.height + } if let textNode = self.textNode, let textSize = self.textSize { - textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - textSize.height) / 2.0)), size: textSize) + textNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - totalTextHeight) / 2.0)), size: textSize) + } + if let subtitleNode = self.subtitleNode, let subtitleSize = self.subtitleSize { + subtitleNode.frame = CGRect(origin: CGPoint(x: floor((self.bounds.size.width - totalWidth) / 2.0), y: floor((self.bounds.size.height - totalTextHeight) / 2.0) + totalTextHeight - subtitleSize.height), size: subtitleSize) } if let iconView = self.iconView, let image = iconView.image { let iconSize = image.size diff --git a/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuNode.swift b/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuNode.swift index 9e046f5987..581adfe196 100644 --- a/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuNode.swift +++ b/submodules/TelegramUI/Components/ContextMenuScreen/Sources/ContextMenuNode.swift @@ -175,12 +175,11 @@ final class ContextMenuNode: ASDisplayNode { let separatorColor = self.isDark ? UIColor(rgb: 0x8c8e8e) : UIColor(rgb: 0xDCE3DC) - let height: CGFloat = 54.0 + var height: CGFloat = 54.0 - let pageLeftSize = self.pageLeftNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height) - let pageRightSize = self.pageRightNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height) - - let maxPageWidth = layout.size.width - 20.0 - pageLeftSize.width - pageRightSize.width + let handleWidth: CGFloat = 33.0 + + let maxPageWidth = layout.size.width - 20.0 - handleWidth * 2.0 var absoluteActionOffsetX: CGFloat = 0.0 var pages: [Page] = [] @@ -188,7 +187,8 @@ final class ContextMenuNode: ASDisplayNode { if i != 0 { absoluteActionOffsetX += UIScreenPixel } - let actionSize = self.actionNodes[i].measure(CGSize(width: layout.size.width, height: height)) + let actionSize = self.actionNodes[i].measure(CGSize(width: layout.size.width, height: 100.0)) + height = max(height, actionSize.height) if pages.isEmpty || (pages[pages.count - 1].width + actionSize.width) > maxPageWidth { pages.append(Page(range: i ..< (i + 1), width: actionSize.width, offsetX: absoluteActionOffsetX)) } else { @@ -212,6 +212,9 @@ final class ContextMenuNode: ASDisplayNode { separatorNode.isHidden = i == self.actionNodes.count - 1 } + let pageLeftSize = self.pageLeftNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height) + let pageRightSize = self.pageRightNode.update(color: self.isDark ? .white : .black, separatorColor: separatorColor, height: height) + self.pageCount = pages.count if !pages.isEmpty { diff --git a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift index 8aac683731..60bb5521f4 100644 --- a/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift +++ b/submodules/TelegramUI/Components/MediaEditor/Sources/Drawing/CodableDrawingEntity.swift @@ -123,6 +123,10 @@ public enum CodableDrawingEntity: Equatable { ) case let .sticker(entity): if case let .link(url, _, _, _, _, _, _) = entity.content { + var url = url + if !url.hasPrefix("http://") && !url.hasPrefix("https://") { + url = "https://\(url)" + } return .link( coordinates: coordinates, url: url diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift index 011d2c8916..c9874c1aa9 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/CreateLinkScreen.swift @@ -319,7 +319,9 @@ private final class CreateLinkSheetComponent: CombinedComponent { self.link = link?.url ?? "" self.name = link?.name ?? "" - + self.positionBelowText = link?.positionBelowText ?? true + self.largeMedia = link?.largeMedia + super.init() self.linkDisposable.set((self.linkPromise.get() @@ -463,10 +465,10 @@ private final class CreateLinkSheetComponent: CombinedComponent { let renderer = DrawingMessageRenderer(context: self.context, messages: [message], parentView: controller.view, isLink: true) renderer.render(completion: { result in completion( - link, CreateLinkScreen.Result( - url: link, + url: self.link, name: self.name, + webpage: !self.dismissed ? self.webpage : nil, positionBelowText: self.positionBelowText, largeMedia: self.largeMedia, image: !media.isEmpty ? result.dayImage : nil, @@ -556,16 +558,26 @@ public final class CreateLinkScreen: ViewControllerComponentContainer { public struct Link: Equatable { let url: String let name: String? + let positionBelowText: Bool + let largeMedia: Bool? - init(url: String, name: String?) { + init( + url: String, + name: String?, + positionBelowText: Bool, + largeMedia: Bool? + ) { self.url = url self.name = name + self.positionBelowText = positionBelowText + self.largeMedia = largeMedia } } public struct Result { let url: String let name: String + let webpage: TelegramMediaWebpage? let positionBelowText: Bool let largeMedia: Bool? let image: UIImage? @@ -575,12 +587,12 @@ public final class CreateLinkScreen: ViewControllerComponentContainer { } private let context: AccountContext - fileprivate let completion: (String, CreateLinkScreen.Result) -> Void + fileprivate let completion: (CreateLinkScreen.Result) -> Void public init( context: AccountContext, link: CreateLinkScreen.Link?, - completion: @escaping (String, CreateLinkScreen.Result) -> Void + completion: @escaping (CreateLinkScreen.Result) -> Void ) { self.context = context self.completion = completion diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 976fd52364..a03ea5fac3 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -3300,6 +3300,8 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate if let self { if let location = entity as? DrawingLocationEntity { self.presentLocationPicker(location) + } else if let sticker = entity as? DrawingStickerEntity, case .link = sticker.content { + self.addOrEditLink(sticker) } } }, @@ -4478,34 +4480,66 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate self.controller?.present(contextController, in: .window(.root)) } - func addLink() { + func addOrEditLink(_ existingEntity: DrawingStickerEntity? = nil) { guard let controller = self.controller else { return } + + var link: CreateLinkScreen.Link? + if let existingEntity, case let .link(url, name, positionBelowText, largeMedia, _, _, _) = existingEntity.content { + link = CreateLinkScreen.Link( + url: url, + name: name, + positionBelowText: positionBelowText, + largeMedia: largeMedia + ) + } - let linkController = CreateLinkScreen(context: controller.context, link: nil, completion: { [weak self] url, result in + let linkController = CreateLinkScreen(context: controller.context, link: link, completion: { [weak self] result in guard let self else { return } + var linkStyle: DrawingStickerEntity.Content.LinkStyle + if let existingEntity, case let .link(_, _, _, _, _, _, existingStyle) = existingEntity.content { + if [.white, .black].contains(existingStyle), result.image == nil { + switch existingStyle { + case .white: + linkStyle = .whiteCompact + case .black: + linkStyle = .blackCompact + default: + linkStyle = existingStyle + } + } else { + linkStyle = existingStyle + } + } else { + linkStyle = result.image != nil ? .white : .whiteCompact + } + let entity = DrawingStickerEntity( - content: .link(url, result.name, result.positionBelowText, result.largeMedia, result.image?.size, result.compactLightImage.size, result.image != nil ? .white : .whiteCompact) + content: .link(result.url, result.name, result.positionBelowText, result.largeMedia, result.image?.size, result.compactLightImage.size, linkStyle) ) entity.renderImage = result.image entity.secondaryRenderImage = result.nightImage entity.tertiaryRenderImage = result.compactLightImage entity.quaternaryRenderImage = result.compactDarkImage - + let fraction: CGFloat if let image = result.image { fraction = max(image.size.width, image.size.height) / 353.0 } else { - fraction = 1.0 + fraction = max(result.compactLightImage.size.width, result.compactLightImage.size.height) / 353.0 + } + + if let existingEntity { + self.entitiesView.remove(uuid: existingEntity.uuid, animated: true) } self.interaction?.insertEntity( entity, - scale: min(6.0, 3.3 * fraction) * 0.5, - position: nil + scale: existingEntity?.scale ?? min(6.0, 3.3 * fraction) * 0.5, + position: existingEntity?.position ) }) controller.push(linkController) @@ -4786,7 +4820,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate } controller.addLink = { [weak self, weak controller] in if let self { - self.addLink() + self.addOrEditLink() self.stickerScreen = nil controller?.dismiss(animated: true) @@ -5724,7 +5758,7 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate }, action: { [weak self] _, a in a(.default) - self?.node.addLink() + self?.node.addOrEditLink() }))) items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaEditor_Shortcut_Location, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Media Editor/LocationSmall"), color: theme.contextMenu.primaryColor) diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 2a9ae6d1bc..45190ed7c0 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -1728,12 +1728,13 @@ private func editingItems(data: PeerInfoScreenData?, state: PeerInfoState, chatL let ItemBotInfo = 10 if let botInfo = user.botInfo, botInfo.flags.contains(.canEdit) { - items[.peerDataSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text("@\(user.addressName ?? "")"), text: presentationData.strings.PeerInfo_BotLinks, icon: PresentationResourcesSettings.bot, action: { + //TODO:localize + items[.peerDataSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemUsername, label: .text("@\(user.addressName ?? "")"), text: "Username", icon: PresentationResourcesSettings.bot, action: { interaction.editingOpenPublicLinkSetup() })) if "".isEmpty { - let balance: Int64 = 1000 + let balance: Int64 = 2275 items[.peerDataSettings]!.append(PeerInfoScreenDisclosureItem(id: ItemStars, label: .text(presentationData.strings.PeerInfo_Bot_Balance_Stars(Int32(balance))), text: presentationData.strings.PeerInfo_Bot_Balance, icon: PresentationResourcesSettings.stars, action: { interaction.editingOpenStars() })) diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsBalanceComponent.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsBalanceComponent.swift index 1fcd9997cb..63ebc61c45 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsBalanceComponent.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsBalanceComponent.swift @@ -15,6 +15,7 @@ final class StarsBalanceComponent: Component { let dateTimeFormat: PresentationDateTimeFormat let count: Int64 let rate: Double? + let actionTitle: String let actionAvailable: Bool let buy: () -> Void @@ -24,6 +25,7 @@ final class StarsBalanceComponent: Component { dateTimeFormat: PresentationDateTimeFormat, count: Int64, rate: Double?, + actionTitle: String, actionAvailable: Bool, buy: @escaping () -> Void ) { @@ -32,6 +34,7 @@ final class StarsBalanceComponent: Component { self.dateTimeFormat = dateTimeFormat self.count = count self.rate = rate + self.actionTitle = actionTitle self.actionAvailable = actionAvailable self.buy = buy } @@ -46,6 +49,9 @@ final class StarsBalanceComponent: Component { if lhs.dateTimeFormat != rhs.dateTimeFormat { return false } + if lhs.actionTitle != rhs.actionTitle { + return false + } if lhs.actionAvailable != rhs.actionAvailable { return false } @@ -111,11 +117,18 @@ final class StarsBalanceComponent: Component { } contentHeight += titleSize.height + let subtitleText: String + if let rate = component.rate { + subtitleText = "≈\(formatUsdValue(component.count, rate: rate))" + } else { + subtitleText = component.strings.Stars_Intro_YourBalance + } + let subtitleSize = self.subtitle.update( transition: .immediate, component: AnyComponent( MultilineTextComponent( - text: .plain(NSAttributedString(string: component.strings.Stars_Intro_YourBalance, font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)), + text: .plain(NSAttributedString(string: subtitleText, font: Font.regular(17.0), textColor: component.theme.list.itemSecondaryTextColor)), horizontalAlignment: .center ) ), @@ -138,7 +151,7 @@ final class StarsBalanceComponent: Component { transition: .immediate, component: AnyComponent( SolidRoundedButtonComponent( - title: component.strings.Stars_Intro_Buy, + title: component.actionTitle, theme: SolidRoundedButtonComponent.Theme(theme: component.theme), height: 50.0, cornerRadius: 11.0, diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift index a19fd9ddc5..06aec07d41 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsStatisticsScreen.swift @@ -13,7 +13,6 @@ import Postbox import MultilineTextComponent import BalancedTextComponent import Markdown -import PremiumStarComponent import ListSectionComponent import BundleIconComponent import TextFormat @@ -84,18 +83,12 @@ final class StarsStatisticsScreenComponent: Component { private let scrollContainerView: UIView - private let overscroll = ComponentView() - private let fade = ComponentView() - private let starView = ComponentView() private let titleView = ComponentView() - private let descriptionView = ComponentView() + private let chartView = ComponentView() + private let proceedsView = ComponentView() private let balanceView = ComponentView() - - private let topBalanceTitleView = ComponentView() - private let topBalanceValueView = ComponentView() - private let topBalanceIconView = ComponentView() - + private let panelContainer = ComponentView() private var component: StarsStatisticsScreenComponent? @@ -115,8 +108,8 @@ final class StarsStatisticsScreenComponent: Component { private var previousBalance: Int64? private var allTransactionsContext: StarsTransactionsContext? - private var incomingTransactionsContext: StarsTransactionsContext? - private var outgoingTransactionsContext: StarsTransactionsContext? + + private var cachedChevronImage: (UIImage, PresentationTheme)? override init(frame: CGRect) { self.headerOffsetContainer = UIView() @@ -206,61 +199,21 @@ final class StarsStatisticsScreenComponent: Component { let scrollBounds = self.scrollView.bounds let isLockedAtPanels = scrollBounds.maxY == self.scrollView.contentSize.height + + let topContentOffset = self.scrollView.contentOffset.y + let navigationBackgroundAlpha = min(20.0, max(0.0, topContentOffset - 95.0)) / 20.0 + + let animatedTransition = Transition(animation: .curve(duration: 0.18, curve: .easeInOut)) + animatedTransition.setAlpha(view: self.navigationBackgroundView, alpha: navigationBackgroundAlpha) + animatedTransition.setAlpha(layer: self.navigationSeparatorLayerContainer, alpha: navigationBackgroundAlpha) - if let navigationMetrics = self.navigationMetrics { - let topInset: CGFloat = navigationMetrics.navigationHeight - 56.0 - - let titleOffset: CGFloat - let titleScale: CGFloat - let titleOffsetDelta = (topInset + 160.0) - (navigationMetrics.statusBarHeight + (navigationMetrics.navigationHeight - navigationMetrics.statusBarHeight) / 2.0) - - var topContentOffset = self.scrollView.contentOffset.y - - let navigationBackgroundAlpha = min(20.0, max(0.0, topContentOffset - 95.0)) / 20.0 - topContentOffset = topContentOffset + max(0.0, min(1.0, topContentOffset / titleOffsetDelta)) * 10.0 - titleOffset = topContentOffset - let fraction = max(0.0, min(1.0, titleOffset / titleOffsetDelta)) - titleScale = 1.0 - fraction * 0.36 - - let headerTransition: Transition = .immediate - - if let starView = self.starView.view { - let starPosition = CGPoint(x: self.scrollView.frame.width / 2.0, y: topInset + starView.bounds.height / 2.0 - 30.0 - titleOffset * titleScale) - - headerTransition.setPosition(view: starView, position: starPosition) - headerTransition.setScale(view: starView, scale: titleScale) - } - - if let titleView = self.titleView.view { - let titlePosition = CGPoint(x: scrollBounds.width / 2.0, y: max(topInset + 160.0 - titleOffset, navigationMetrics.statusBarHeight + (navigationMetrics.navigationHeight - navigationMetrics.statusBarHeight) / 2.0)) - - headerTransition.setPosition(view: titleView, position: titlePosition) - headerTransition.setScale(view: titleView, scale: titleScale) - } - - let animatedTransition = Transition(animation: .curve(duration: 0.18, curve: .easeInOut)) - animatedTransition.setAlpha(view: self.navigationBackgroundView, alpha: navigationBackgroundAlpha) - animatedTransition.setAlpha(layer: self.navigationSeparatorLayerContainer, alpha: navigationBackgroundAlpha) - - let expansionDistance: CGFloat = 32.0 - var expansionDistanceFactor: CGFloat = abs(scrollBounds.maxY - self.scrollView.contentSize.height) / expansionDistance - expansionDistanceFactor = max(0.0, min(1.0, expansionDistanceFactor)) - - transition.setAlpha(layer: self.navigationSeparatorLayer, alpha: expansionDistanceFactor) - if let panelContainerView = self.panelContainer.view as? StarsTransactionsPanelContainerComponent.View { - panelContainerView.updateNavigationMergeFactor(value: 1.0 - expansionDistanceFactor, transition: transition) - } - - let topBalanceAlpha = 1.0 - expansionDistanceFactor - if let view = self.topBalanceTitleView.view { - view.alpha = topBalanceAlpha - } - if let view = self.topBalanceValueView.view { - view.alpha = topBalanceAlpha - } - if let view = self.topBalanceIconView.view { - view.alpha = topBalanceAlpha - } + let expansionDistance: CGFloat = 32.0 + var expansionDistanceFactor: CGFloat = abs(scrollBounds.maxY - self.scrollView.contentSize.height) / expansionDistance + expansionDistanceFactor = max(0.0, min(1.0, expansionDistanceFactor)) + + transition.setAlpha(layer: self.navigationSeparatorLayer, alpha: expansionDistanceFactor) + if let panelContainerView = self.panelContainer.view as? StarsTransactionsPanelContainerComponent.View { + panelContainerView.updateNavigationMergeFactor(value: 1.0 - expansionDistanceFactor, transition: transition) } let _ = self.panelContainer.updateEnvironment( @@ -290,6 +243,7 @@ final class StarsStatisticsScreenComponent: Component { } let environment = environment[ViewControllerComponentContainer.Environment.self].value + let presentationData = component.context.sharedContext.currentPresentationData.with { $0 } if self.stateDisposable == nil { self.stateDisposable = (component.starsContext.state @@ -335,82 +289,14 @@ final class StarsStatisticsScreenComponent: Component { let sideInsets: CGFloat = environment.safeInsets.left + environment.safeInsets.right + 16 * 2.0 let bottomInset: CGFloat = environment.safeInsets.bottom - contentHeight += environment.statusBarHeight + contentHeight += environment.navigationHeight + contentHeight += 31.0 - let starTransition: Transition = .immediate - - var topBackgroundColor = environment.theme.list.plainBackgroundColor - let bottomBackgroundColor = environment.theme.list.blocksBackgroundColor - if environment.theme.overallDarkAppearance { - topBackgroundColor = bottomBackgroundColor - } - - let overscrollSize = self.overscroll.update( - transition: .immediate, - component: AnyComponent(Rectangle(color: topBackgroundColor)), - environment: {}, - containerSize: CGSize(width: availableSize.width, height: 1000.0) - ) - let overscrollFrame = CGRect(origin: CGPoint(x: 0.0, y: -overscrollSize.height), size: overscrollSize) - if let overscrollView = self.overscroll.view { - if overscrollView.superview == nil { - self.scrollView.addSubview(overscrollView) - } - starTransition.setFrame(view: overscrollView, frame: overscrollFrame) - } - - let fadeSize = self.fade.update( - transition: .immediate, - component: AnyComponent(RoundedRectangle( - colors: [ - topBackgroundColor, - bottomBackgroundColor - ], - cornerRadius: 0.0, - gradientDirection: .vertical - )), - environment: {}, - containerSize: CGSize(width: availableSize.width, height: 1000.0) - ) - let fadeFrame = CGRect(origin: CGPoint(x: 0.0, y: -fadeSize.height), size: fadeSize) - if let fadeView = self.fade.view { - if fadeView.superview == nil { - self.scrollView.addSubview(fadeView) - } - starTransition.setFrame(view: fadeView, frame: fadeFrame) - } - - let starSize = self.starView.update( - transition: .immediate, - component: AnyComponent(PremiumStarComponent( - theme: environment.theme, - isIntro: true, - isVisible: true, - hasIdleAnimations: true, - colors: [ - UIColor(rgb: 0xe57d02), - UIColor(rgb: 0xf09903), - UIColor(rgb: 0xf9b004), - UIColor(rgb: 0xfdd219) - ], - particleColor: UIColor(rgb: 0xf9b004) - )), - environment: {}, - containerSize: CGSize(width: min(414.0, availableSize.width), height: 220.0) - ) - let starFrame = CGRect(origin: .zero, size: starSize) - if let starView = self.starView.view { - if starView.superview == nil { - self.insertSubview(starView, aboveSubview: self.scrollView) - } - starTransition.setBounds(view: starView, bounds: starFrame) - } - let titleSize = self.titleView.update( transition: .immediate, component: AnyComponent( MultilineTextComponent( - text: .plain(NSAttributedString(string: environment.strings.Stars_Intro_Title, font: Font.bold(28.0), textColor: environment.theme.list.itemPrimaryTextColor)), + text: .plain(NSAttributedString(string: "Stars Balance", font: Font.semibold(17.0), textColor: environment.theme.list.itemPrimaryTextColor)), horizontalAlignment: .center, truncationType: .end, maximumNumberOfLines: 1 @@ -423,114 +309,100 @@ final class StarsStatisticsScreenComponent: Component { if titleView.superview == nil { self.addSubview(titleView) } - starTransition.setBounds(view: titleView, bounds: CGRect(origin: .zero, size: titleSize)) + let titlePosition = CGPoint(x: availableSize.width / 2.0, y: environment.statusBarHeight + (environment.navigationHeight - environment.statusBarHeight) / 2.0) + transition.setPosition(view: titleView, position: titlePosition) + transition.setBounds(view: titleView, bounds: CGRect(origin: .zero, size: titleSize)) } - let topBalanceTitleSize = self.topBalanceTitleView.update( + let proceedsSize = self.proceedsView.update( transition: .immediate, - component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString( - string: environment.strings.Stars_Intro_Balance, - font: Font.regular(14.0), - textColor: environment.theme.actionSheet.primaryTextColor + component: AnyComponent(ListSectionComponent( + theme: environment.theme, + header: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString( + string: "Proceeds Overview".uppercased(), + font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize), + textColor: environment.theme.list.freeTextColor + )), + maximumNumberOfLines: 0 )), - maximumNumberOfLines: 1 + footer: nil, + items: [AnyComponentWithIdentity(id: 0, component: AnyComponent( + VStack([ + AnyComponentWithIdentity(id: 0, component: AnyComponent(HStack([ + AnyComponentWithIdentity(id: 0, component: AnyComponent(BundleIconComponent(name: "Premium/Stars/StarMedium", tintColor: nil))), + AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: presentationStringsFormattedNumber(Int32(self.starsState?.balance ?? 0), environment.dateTimeFormat.groupingSeparator), font: Font.semibold(17.0), textColor: environment.theme.list.itemPrimaryTextColor))))), + AnyComponentWithIdentity(id: 2, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: formatUsdValue(self.starsState?.balance ?? 0, rate: 0.2), font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor))))), + ], spacing: 3.0))), + AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Available Balance", font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor))))) + ], alignment: .left, spacing: 2.0) + )), + AnyComponentWithIdentity(id: 1, component: AnyComponent( + VStack([ + AnyComponentWithIdentity(id: 0, component: AnyComponent(HStack([ + AnyComponentWithIdentity(id: 0, component: AnyComponent(BundleIconComponent(name: "Premium/Stars/StarMedium", tintColor: nil))), + AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: presentationStringsFormattedNumber(Int32(self.starsState?.balance ?? 0) * 3, environment.dateTimeFormat.groupingSeparator), font: Font.semibold(17.0), textColor: environment.theme.list.itemPrimaryTextColor))))), + AnyComponentWithIdentity(id: 2, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: formatUsdValue((self.starsState?.balance ?? 0) * 3, rate: 0.2), font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor))))), + ], spacing: 3.0))), + AnyComponentWithIdentity(id: 1, component: AnyComponent(MultilineTextComponent(text: .plain(NSAttributedString(string: "Total Lifetime Proceeds", font: Font.regular(13.0), textColor: environment.theme.list.itemSecondaryTextColor))))) + ], alignment: .left, spacing: 2.0) + ))], + displaySeparators: false )), environment: {}, - containerSize: CGSize(width: 120.0, height: 100.0) + containerSize: CGSize(width: availableSize.width - sideInsets, height: availableSize.height) ) - - let topBalanceValueSize = self.topBalanceValueView.update( - transition: .immediate, - component: AnyComponent(MultilineTextComponent( - text: .plain(NSAttributedString( - string: presentationStringsFormattedNumber(Int32(self.starsState?.balance ?? 0), environment.dateTimeFormat.groupingSeparator), - font: Font.semibold(14.0), - textColor: environment.theme.actionSheet.primaryTextColor - )), - maximumNumberOfLines: 1 - )), - environment: {}, - containerSize: CGSize(width: 120.0, height: 100.0) - ) - let topBalanceIconSize = self.topBalanceIconView.update( - transition: .immediate, - component: AnyComponent(BundleIconComponent(name: "Premium/Stars/StarSmall", tintColor: nil)), - environment: {}, - containerSize: availableSize - ) - - let navigationHeight = environment.navigationHeight - environment.statusBarHeight - let topBalanceOriginY = environment.statusBarHeight + (navigationHeight - topBalanceTitleSize.height - topBalanceValueSize.height) / 2.0 - let topBalanceTitleFrame = CGRect(origin: CGPoint(x: availableSize.width - topBalanceTitleSize.width - 16.0 - environment.safeInsets.right, y: topBalanceOriginY), size: topBalanceTitleSize) - if let topBalanceTitleView = self.topBalanceTitleView.view { - if topBalanceTitleView.superview == nil { - topBalanceTitleView.alpha = 0.0 - self.addSubview(topBalanceTitleView) + let proceedsFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - proceedsSize.width) / 2.0), y: contentHeight), size: proceedsSize) + if let proceedsView = self.proceedsView.view { + if proceedsView.superview == nil { + self.scrollView.addSubview(proceedsView) } - starTransition.setFrame(view: topBalanceTitleView, frame: topBalanceTitleFrame) - } - - let topBalanceValueFrame = CGRect(origin: CGPoint(x: availableSize.width - topBalanceValueSize.width - 16.0 - environment.safeInsets.right, y: topBalanceTitleFrame.maxY), size: topBalanceValueSize) - if let topBalanceValueView = self.topBalanceValueView.view { - if topBalanceValueView.superview == nil { - topBalanceValueView.alpha = 0.0 - self.addSubview(topBalanceValueView) - } - starTransition.setFrame(view: topBalanceValueView, frame: topBalanceValueFrame) + transition.setFrame(view: proceedsView, frame: proceedsFrame) } - let topBalanceIconFrame = CGRect(origin: CGPoint(x: topBalanceValueFrame.minX - topBalanceIconSize.width - 2.0, y: floorToScreenPixels(topBalanceValueFrame.midY - topBalanceIconSize.height / 2.0) - UIScreenPixel), size: topBalanceIconSize) - if let topBalanceIconView = self.topBalanceIconView.view { - if topBalanceIconView.superview == nil { - topBalanceIconView.alpha = 0.0 - self.addSubview(topBalanceIconView) - } - starTransition.setFrame(view: topBalanceIconView, frame: topBalanceIconFrame) - } - - contentHeight += 181.0 + contentHeight += proceedsSize.height + contentHeight += 44.0 - let descriptionSize = self.descriptionView.update( - transition: .immediate, - component: AnyComponent( - BalancedTextComponent( - text: .plain(NSAttributedString(string: environment.strings.Stars_Intro_Description, font: Font.regular(15.0), textColor: environment.theme.list.itemPrimaryTextColor)), - horizontalAlignment: .center, - maximumNumberOfLines: 0, - lineSpacing: 0.2 - ) - ), - environment: {}, - containerSize: CGSize(width: availableSize.width - sideInsets - 8.0, height: 240.0) - ) - let descriptionFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((availableSize.width - descriptionSize.width) / 2.0), y: contentHeight + 20.0 - floor(descriptionSize.height / 2.0)), size: descriptionSize) - if let descriptionView = self.descriptionView.view { - if descriptionView.superview == nil { - self.scrollView.addSubview(descriptionView) - } - - starTransition.setFrame(view: descriptionView, frame: descriptionFrame) - } - - contentHeight += descriptionSize.height - contentHeight += 29.0 + let termsFont = Font.regular(13.0) + let termsTextColor = environment.theme.list.freeTextColor + let termsMarkdownAttributes = MarkdownAttributes(body: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), bold: MarkdownAttributeSet(font: termsFont, textColor: termsTextColor), link: MarkdownAttributeSet(font: termsFont, textColor: environment.theme.list.itemAccentColor), linkAttribute: { contents in + return (TelegramTextAttributes.URL, contents) + }) - let premiumConfiguration = PremiumConfiguration.with(appConfiguration: component.context.currentAppConfiguration.with { $0 }) + let balanceInfoString = NSMutableAttributedString(attributedString: parseMarkdownIntoAttributedString("You can withdraw Stars using Fragment, or use Stars to advertise your bot. [Learn More >]()", attributes: termsMarkdownAttributes, textAlignment: .natural + )) + if self.cachedChevronImage == nil || self.cachedChevronImage?.1 !== environment.theme { + self.cachedChevronImage = (generateTintedImage(image: UIImage(bundleImageName: "Contact List/SubtitleArrow"), color: environment.theme.list.itemAccentColor)!, environment.theme) + } + if let range = balanceInfoString.string.range(of: ">"), let chevronImage = self.cachedChevronImage?.0 { + balanceInfoString.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: balanceInfoString.string)) + } + let balanceSize = self.balanceView.update( transition: .immediate, component: AnyComponent(ListSectionComponent( theme: environment.theme, - header: nil, - footer: nil, + header: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString( + string: "Available Balance".uppercased(), + font: Font.regular(presentationData.listsFontSize.itemListBaseHeaderFontSize), + textColor: environment.theme.list.freeTextColor + )), + maximumNumberOfLines: 0 + )), + footer: AnyComponent(MultilineTextComponent( + text: .plain(balanceInfoString), + maximumNumberOfLines: 0 + )), items: [AnyComponentWithIdentity(id: 0, component: AnyComponent( StarsBalanceComponent( theme: environment.theme, strings: environment.strings, dateTimeFormat: environment.dateTimeFormat, count: self.starsState?.balance ?? 0, - rate: nil, - actionAvailable: !premiumConfiguration.areStarsDisabled, + rate: 0.2, + actionTitle: "Withdraw via Fragment", + actionAvailable: true, buy: { [weak self] in guard let self, let component = self.component else { return @@ -548,7 +420,7 @@ final class StarsStatisticsScreenComponent: Component { if balanceView.superview == nil { self.scrollView.addSubview(balanceView) } - starTransition.setFrame(view: balanceView, frame: balanceFrame) + transition.setFrame(view: balanceView, frame: balanceFrame) } contentHeight += balanceSize.height @@ -563,21 +435,7 @@ final class StarsStatisticsScreenComponent: Component { } else { allTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .all) } - - let incomingTransactionsContext: StarsTransactionsContext - if let current = self.incomingTransactionsContext { - incomingTransactionsContext = current - } else { - incomingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .incoming) - } - - let outgoingTransactionsContext: StarsTransactionsContext - if let current = self.outgoingTransactionsContext { - outgoingTransactionsContext = current - } else { - outgoingTransactionsContext = component.context.engine.payments.peerStarsTransactionsContext(starsContext: component.starsContext, subject: .outgoing) - } - + panelItems.append(StarsTransactionsPanelContainerComponent.Item( id: "all", title: environment.strings.Stars_Intro_AllTransactions, @@ -589,30 +447,6 @@ final class StarsStatisticsScreenComponent: Component { } )) )) - - panelItems.append(StarsTransactionsPanelContainerComponent.Item( - id: "incoming", - title: environment.strings.Stars_Intro_Incoming, - panel: AnyComponent(StarsTransactionsListPanelComponent( - context: component.context, - transactionsContext: incomingTransactionsContext, - action: { transaction in - component.openTransaction(transaction) - } - )) - )) - - panelItems.append(StarsTransactionsPanelContainerComponent.Item( - id: "outgoing", - title: environment.strings.Stars_Intro_Outgoing, - panel: AnyComponent(StarsTransactionsListPanelComponent( - context: component.context, - transactionsContext: outgoingTransactionsContext, - action: { transaction in - component.openTransaction(transaction) - } - )) - )) } var panelTransition = transition diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift index 5f20863eac..27cbe04843 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsTransactionsScreen.swift @@ -78,10 +78,7 @@ final class StarsTransactionsScreenComponent: Component { private let navigationBackgroundView: BlurredBackgroundView private let navigationSeparatorLayer: SimpleLayer private let navigationSeparatorLayerContainer: SimpleLayer - - private let headerView = ComponentView() - private let headerOffsetContainer: UIView - + private let scrollContainerView: UIView private let overscroll = ComponentView() @@ -119,9 +116,6 @@ final class StarsTransactionsScreenComponent: Component { private var outgoingTransactionsContext: StarsTransactionsContext? override init(frame: CGRect) { - self.headerOffsetContainer = UIView() - self.headerOffsetContainer.isUserInteractionEnabled = false - self.navigationBackgroundView = BlurredBackgroundView(color: nil, enableBlur: true) self.navigationBackgroundView.alpha = 0.0 @@ -158,8 +152,6 @@ final class StarsTransactionsScreenComponent: Component { self.navigationSeparatorLayerContainer.addSublayer(self.navigationSeparatorLayer) self.layer.addSublayer(self.navigationSeparatorLayerContainer) - - self.addSubview(self.headerOffsetContainer) } required init?(coder: NSCoder) { @@ -530,6 +522,7 @@ final class StarsTransactionsScreenComponent: Component { dateTimeFormat: environment.dateTimeFormat, count: self.starsState?.balance ?? 0, rate: nil, + actionTitle: environment.strings.Stars_Intro_Buy, actionAvailable: !premiumConfiguration.areStarsDisabled, buy: { [weak self] in guard let self, let component = self.component else { diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsUtils.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsUtils.swift index 07020eeb8e..f09a7ed3ce 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsUtils.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionsScreen/Sources/StarsUtils.swift @@ -1,6 +1,6 @@ import Foundation func formatUsdValue(_ value: Int64, rate: Double) -> String { - let formattedValue = String(format: "%0.2f", (Double(value) / 1000000000) * rate) + let formattedValue = String(format: "%0.2f", (Double(value)) * rate) return "$\(formattedValue)" } diff --git a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift index 2af72518be..55a3593d82 100644 --- a/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift +++ b/submodules/TelegramUI/Components/Stories/StoryContainerScreen/Sources/StoryItemSetContainerViewSendMessage.swift @@ -3452,7 +3452,7 @@ final class StoryItemSetContainerSendMessage { action() return } - actions.append(ContextMenuAction(content: .textWithIcon(title: updatedPresentationData.initial.strings.Story_ViewLink, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: { + actions.append(ContextMenuAction(content: .textWithSubtitleAndIcon(title: updatedPresentationData.initial.strings.Story_ViewLink, subtitle: url, icon: generateTintedImage(image: UIImage(bundleImageName: "Settings/TextArrowRight"), color: .white)), action: { action() })) }