From 813a913bca47668b707ac5814923b3cd4d93bf23 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 23 Jun 2024 19:05:01 +0400 Subject: [PATCH] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 3 + .../ChatSendMessageContextScreen.swift | 3 +- .../Sources/MediaPickerSelectedListNode.swift | 1 - .../Sources/PremiumLimitsListScreen.swift | 1 - .../Sources/ChatBotInfoItem.swift | 35 +- .../Sources/ChatMessageBubbleItemNode.swift | 2 +- .../Sources/ChatMessageUnlockMediaNode.swift | 23 +- .../Sources/ChatControllerInteraction.swift | 2 +- .../Sources/MediaEditorScreen.swift | 17 +- .../Sources/StarsTransactionScreen.swift | 20 +- .../ChatControllerOpenLinkContextMenu.swift | 89 +++++ .../Chat/ChatControllerOpenLinkLongTap.swift | 357 ------------------ 12 files changed, 133 insertions(+), 420 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 56a724fa2e..d4a7ab246d 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -10629,6 +10629,7 @@ Sorry for the inconvenience."; "MediaEditor.Shortcut.Location" = "Location"; "MediaEditor.Shortcut.Reaction" = "Reaction"; "MediaEditor.Shortcut.Audio" = "Audio"; +"MediaEditor.Shortcut.Link" = "Link"; "BoostGift.AdditionalPrizes" = "Additional Prizes"; "BoostGift.AdditionalPrizesPlaceholder" = "Enter Your Prize"; @@ -12431,3 +12432,5 @@ Sorry for the inconvenience."; "Premium.MessageEffects" = "Message Effects"; "Premium.MessageEffectsInfo" = "Add over 500 animated effects to private messages."; + +"Chat.UnlockMedia" = "Unlock for %@"; diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift index 93890722b8..23cccaf8d9 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageContextScreen.swift @@ -1044,8 +1044,7 @@ final class ChatSendMessageContextScreenComponent: Component { self.animateOutToEmpty = true self.environment?.controller()?.dismiss() - //TODO:localize - let premiumController = component.context.sharedContext.makePremiumIntroController(context: component.context, source: .animatedEmoji, forceDark: false, dismissed: nil) + let premiumController = component.context.sharedContext.makePremiumIntroController(context: component.context, source: .messageEffects, forceDark: false, dismissed: nil) component.openPremiumPaywall(premiumController) } return false diff --git a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift index 5e6466db4b..dc991546e0 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerSelectedListNode.swift @@ -512,7 +512,6 @@ final class PriceNode: ASDisplayNode { var backgroundTransition = transition let labelTransition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut) if let price { - //TODO:localize self.labelNode.attributedText = NSAttributedString(string: "\(price)", font: Font.semibold(15.0), textColor: .white) labelSize = self.labelNode.updateLayout(CGSize(width: 240.0, height: 50.0)) diff --git a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift index ab35d50747..3f1fa037fd 100644 --- a/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumLimitsListScreen.swift @@ -826,7 +826,6 @@ public class PremiumLimitsListScreen: ViewController { ) ) ) - //TODO:localize availableItems[.messageEffects] = DemoPagerComponent.Item( AnyComponentWithIdentity( id: PremiumDemoScreen.Subject.messageEffects, diff --git a/submodules/TelegramUI/Components/Chat/ChatBotInfoItem/Sources/ChatBotInfoItem.swift b/submodules/TelegramUI/Components/Chat/ChatBotInfoItem/Sources/ChatBotInfoItem.swift index 6aecfd490f..8ee63a28ac 100644 --- a/submodules/TelegramUI/Components/Chat/ChatBotInfoItem/Sources/ChatBotInfoItem.swift +++ b/submodules/TelegramUI/Components/Chat/ChatBotInfoItem/Sources/ChatBotInfoItem.swift @@ -477,25 +477,22 @@ public final class ChatBotInfoItemNode: ListViewItemNode { case .longTap, .doubleTap: if let item = self.item, self.backgroundNode.frame.contains(location) { let tapAction = self.tapActionAtPoint(location, gesture: gesture, isEstimating: false) -//TODO:do - let _ = item - let _ = tapAction -// switch tapAction.content { -// case .none, .ignore: -// break -// case let .url(url): -// item.controllerInteraction.longTap(.url(url.url), nil) -// case let .peerMention(peerId, mention, _): -// item.controllerInteraction.longTap(.peerMention(peerId, mention), nil) -// case let .textMention(name): -// item.controllerInteraction.longTap(.mention(name), nil) -// case let .botCommand(command): -// item.controllerInteraction.longTap(.command(command), nil) -// case let .hashtag(_, hashtag): -// item.controllerInteraction.longTap(.hashtag(hashtag), nil) -// default: -// break -// } + switch tapAction.content { + case .none, .ignore: + break + case let .url(url): + item.controllerInteraction.longTap(.url(url.url), ChatControllerInteraction.LongTapParams()) + case let .peerMention(peerId, mention, _): + item.controllerInteraction.longTap(.peerMention(peerId, mention), ChatControllerInteraction.LongTapParams()) + case let .textMention(name): + item.controllerInteraction.longTap(.mention(name), ChatControllerInteraction.LongTapParams()) + case let .botCommand(command): + item.controllerInteraction.longTap(.command(command), ChatControllerInteraction.LongTapParams()) + case let .hashtag(_, hashtag): + item.controllerInteraction.longTap(.hashtag(hashtag), ChatControllerInteraction.LongTapParams()) + default: + break + } } default: break diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift index e7ab0d5bbc..6274b32845 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageBubbleItemNode/Sources/ChatMessageBubbleItemNode.swift @@ -2864,7 +2864,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI if let mosaicRange = mosaicRange, mosaicRange.contains(i), let (framesAndPositions, size) = calculatedGroupFramesAndSize { let mosaicIndex = i - mosaicRange.lowerBound - if mosaicIndex == 0 { + if mosaicIndex == 0 && i == 0 { if !headerSize.height.isZero { contentNodesHeight += 7.0 totalContentNodesHeight += 7.0 diff --git a/submodules/TelegramUI/Components/Chat/ChatMessageUnlockMediaNode/Sources/ChatMessageUnlockMediaNode.swift b/submodules/TelegramUI/Components/Chat/ChatMessageUnlockMediaNode/Sources/ChatMessageUnlockMediaNode.swift index d43eff65bf..8f97770655 100644 --- a/submodules/TelegramUI/Components/Chat/ChatMessageUnlockMediaNode/Sources/ChatMessageUnlockMediaNode.swift +++ b/submodules/TelegramUI/Components/Chat/ChatMessageUnlockMediaNode/Sources/ChatMessageUnlockMediaNode.swift @@ -79,25 +79,7 @@ public class ChatMessageUnlockMediaNode: ASDisplayNode { self.addSubnode(self.contentNode) self.contentNode.addSubnode(self.backgroundNode) - -// self.contentNode.highligthedChanged = { [weak self] highlighted in -// if let strongSelf = self { -// if highlighted, !strongSelf.frame.width.isZero { -// let scale = (strongSelf.frame.width - 10.0) / strongSelf.frame.width -// -// strongSelf.contentNode.layer.animateScale(from: 1.0, to: scale, duration: 0.15, removeOnCompletion: false) -// -// strongSelf.backgroundNode.layer.removeAnimation(forKey: "opacity") -// strongSelf.backgroundNode.alpha = 0.2 -// } else if let presentationLayer = strongSelf.contentNode.layer.presentation() { -// strongSelf.contentNode.layer.animateScale(from: CGFloat((presentationLayer.value(forKeyPath: "transform.scale.y") as? NSNumber)?.floatValue ?? 1.0), to: 1.0, duration: 0.25, removeOnCompletion: false) -// -// strongSelf.backgroundNode.alpha = 1.0 -// strongSelf.backgroundNode.layer.animateAlpha(from: 0.2, to: 1.0, duration: 0.2) -// } -// } -// } - + self.contentNode.addTarget(self, action: #selector(self.buttonPressed), forControlEvents: .touchUpInside) } @@ -113,8 +95,7 @@ public class ChatMessageUnlockMediaNode: ASDisplayNode { let textFont = Font.medium(fontSize) let padding: CGFloat = 10.0 - //TODO:localize - let text = NSMutableAttributedString(string: "Unlock for ⭐️ \(arguments.media.amount)", font: textFont, textColor: .white) + let text = NSMutableAttributedString(string: arguments.presentationData.strings.Chat_UnlockMedia("⭐️ \(arguments.media.amount)").string, font: textFont, textColor: .white) if let range = text.string.range(of: "⭐️") { text.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(interactivelySelectedFromPackId: nil, fileId: 0, file: nil, custom: .stars(tinted: false)), range: NSRange(range, in: text.string)) text.addAttribute(.baselineOffset, value: 0.5, range: NSRange(range, in: text.string)) diff --git a/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift index bfc7c94301..710517d8fb 100644 --- a/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Components/ChatControllerInteraction/Sources/ChatControllerInteraction.swift @@ -158,7 +158,7 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol public var messageNode: ASDisplayNode? public var progress: Promise? - public init(message: Message?, contentNode: ContextExtractedContentContainingNode? = nil, messageNode: ASDisplayNode? = nil, progress: Promise? = nil) { + public init(message: Message? = nil, contentNode: ContextExtractedContentContainingNode? = nil, messageNode: ASDisplayNode? = nil, progress: Promise? = nil) { self.message = message self.contentNode = contentNode self.messageNode = messageNode diff --git a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift index 5e92d6188f..c6758ebf51 100644 --- a/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift +++ b/submodules/TelegramUI/Components/MediaEditorScreen/Sources/MediaEditorScreen.swift @@ -5750,14 +5750,15 @@ public final class MediaEditorScreen: ViewController, UIDropInteractionDelegate self?.node.presentGallery() }))) - //TODO:localize - items.append(.action(ContextMenuActionItem(text: "Link", icon: { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor) - }, action: { [weak self] _, a in - a(.default) - - self?.node.addOrEditLink() - }))) + if self.context.isPremium { + items.append(.action(ContextMenuActionItem(text: presentationData.strings.MediaEditor_Shortcut_Link, icon: { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Link"), color: theme.contextMenu.primaryColor) + }, action: { [weak self] _, a in + a(.default) + + 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) }, action: { [weak self] _, a in diff --git a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift index 1fb311b351..8bf58a689c 100644 --- a/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift +++ b/submodules/TelegramUI/Components/Stars/StarsTransactionScreen/Sources/StarsTransactionScreen.swift @@ -33,7 +33,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { let openPeer: (EnginePeer) -> Void let openMessage: (EngineMessage.Id) -> Void let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void - let copyTransactionId: () -> Void + let copyTransactionId: (String) -> Void init( context: AccountContext, @@ -43,7 +43,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { openPeer: @escaping (EnginePeer) -> Void, openMessage: @escaping (EngineMessage.Id) -> Void, openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void, - copyTransactionId: @escaping () -> Void + copyTransactionId: @escaping (String) -> Void ) { self.context = context self.subject = subject @@ -464,7 +464,7 @@ private final class StarsTransactionSheetContent: CombinedComponent { ) ), action: { - component.copyTransactionId() + component.copyTransactionId(transactionId) } ) ), @@ -650,7 +650,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent { let openPeer: (EnginePeer) -> Void let openMessage: (EngineMessage.Id) -> Void let openMedia: ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void - let copyTransactionId: () -> Void + let copyTransactionId: (String) -> Void init( context: AccountContext, @@ -659,7 +659,7 @@ private final class StarsTransactionSheetComponent: CombinedComponent { openPeer: @escaping (EnginePeer) -> Void, openMessage: @escaping (EngineMessage.Id) -> Void, openMedia: @escaping ([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void, - copyTransactionId: @escaping () -> Void + copyTransactionId: @escaping (String) -> Void ) { self.context = context self.subject = subject @@ -799,7 +799,7 @@ public class StarsTransactionScreen: ViewControllerComponentContainer { var openPeerImpl: ((EnginePeer) -> Void)? var openMessageImpl: ((EngineMessage.Id) -> Void)? var openMediaImpl: (([Media], @escaping (Media) -> (ASDisplayNode, CGRect, () -> (UIView?, UIView?))?, @escaping (UIView) -> Void) -> Void)? - var copyTransactionIdImpl: (() -> Void)? + var copyTransactionIdImpl: ((String) -> Void)? super.init( context: context, component: StarsTransactionSheetComponent( @@ -815,8 +815,8 @@ public class StarsTransactionScreen: ViewControllerComponentContainer { openMedia: { media, transitionNode, addToTransitionSurface in openMediaImpl?(media, transitionNode, addToTransitionSurface) }, - copyTransactionId: { - copyTransactionIdImpl?() + copyTransactionId: { transactionId in + copyTransactionIdImpl?(transactionId) } ), navigationBarAppearance: .none, @@ -902,10 +902,12 @@ public class StarsTransactionScreen: ViewControllerComponentContainer { })) } - copyTransactionIdImpl = { [weak self] in + copyTransactionIdImpl = { [weak self] transactionId in guard let self else { return } + UIPasteboard.general.string = transactionId + self.dismissAllTooltips() let presentationData = context.sharedContext.currentPresentationData.with { $0 } diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkContextMenu.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkContextMenu.swift index 91cc8cd751..c3d6c7070b 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkContextMenu.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkContextMenu.swift @@ -19,6 +19,95 @@ import SafariServices extension ChatControllerImpl { func openLinkContextMenu(url: String, params: ChatControllerInteraction.LongTapParams) -> Void { guard let message = params.message, let contentNode = params.contentNode else { + var (cleanUrl, _) = parseUrl(url: url, wasConcealed: false) + var canAddToReadingList = true + var canOpenIn = availableOpenInOptions(context: self.context, item: .url(url: url)).count > 1 + let mailtoString = "mailto:" + let telString = "tel:" + var openText = self.presentationData.strings.Conversation_LinkDialogOpen + var phoneNumber: String? + + var isPhoneNumber = false + var isEmail = false + var hasOpenAction = true + + if cleanUrl.hasPrefix(mailtoString) { + canAddToReadingList = false + cleanUrl = String(cleanUrl[cleanUrl.index(cleanUrl.startIndex, offsetBy: mailtoString.distance(from: mailtoString.startIndex, to: mailtoString.endIndex))...]) + isEmail = true + } else if cleanUrl.hasPrefix(telString) { + canAddToReadingList = false + phoneNumber = String(cleanUrl[cleanUrl.index(cleanUrl.startIndex, offsetBy: telString.distance(from: telString.startIndex, to: telString.endIndex))...]) + cleanUrl = phoneNumber! + openText = self.presentationData.strings.UserInfo_PhoneCall + canOpenIn = false + isPhoneNumber = true + + if cleanUrl.hasPrefix("+888") { + hasOpenAction = false + } + } else if canOpenIn { + openText = self.presentationData.strings.Conversation_FileOpenIn + } + + let actionSheet = ActionSheetController(presentationData: self.presentationData) + var items: [ActionSheetItem] = [] + items.append(ActionSheetTextItem(title: cleanUrl)) + if hasOpenAction { + items.append(ActionSheetButtonItem(title: openText, color: .accent, action: { [weak self, weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + if canOpenIn { + strongSelf.openUrlIn(url) + } else { + strongSelf.openUrl(url, concealed: false) + } + } + })) + } + if let phoneNumber = phoneNumber { + items.append(ActionSheetButtonItem(title: self.presentationData.strings.Conversation_AddContact, color: .accent, action: { [weak self, weak actionSheet] in + actionSheet?.dismissAnimated() + if let strongSelf = self { + strongSelf.controllerInteraction?.addContact(phoneNumber) + } + })) + } + items.append(ActionSheetButtonItem(title: canAddToReadingList ? self.presentationData.strings.ShareMenu_CopyShareLink : self.presentationData.strings.Conversation_ContextMenuCopy, color: .accent, action: { [weak actionSheet, weak self] in + actionSheet?.dismissAnimated() + guard let self else { + return + } + UIPasteboard.general.string = cleanUrl + + let content: UndoOverlayContent + if isPhoneNumber { + content = .copy(text: self.presentationData.strings.Conversation_PhoneCopied) + } else if isEmail { + content = .copy(text: self.presentationData.strings.Conversation_EmailCopied) + } else if canAddToReadingList { + content = .linkCopied(text: self.presentationData.strings.Conversation_LinkCopied) + } else { + content = .copy(text: self.presentationData.strings.Conversation_TextCopied) + } + self.present(UndoOverlayController(presentationData: self.presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) + })) + if canAddToReadingList { + items.append(ActionSheetButtonItem(title: self.presentationData.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + if let link = URL(string: url) { + let _ = try? SSReadingList.default()?.addItem(with: link, title: nil, previewText: nil) + } + })) + } + actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ + ActionSheetButtonItem(title: self.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in + actionSheet?.dismissAnimated() + }) + ])]) + self.chatDisplayNode.dismissInput() + self.present(actionSheet, in: .window(.root)) + return } diff --git a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkLongTap.swift b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkLongTap.swift index 1340fdac41..4f48129509 100644 --- a/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkLongTap.swift +++ b/submodules/TelegramUI/Sources/Chat/ChatControllerOpenLinkLongTap.swift @@ -38,360 +38,3 @@ extension ChatControllerImpl { } } } - -//if let strongSelf = self { -// let presentationData = strongSelf.presentationData -// switch action { -// case let .url(url): -// var (cleanUrl, _) = parseUrl(url: url, wasConcealed: false) -// var canAddToReadingList = true -// var canOpenIn = availableOpenInOptions(context: strongSelf.context, item: .url(url: url)).count > 1 -// let mailtoString = "mailto:" -// let telString = "tel:" -// var openText = strongSelf.presentationData.strings.Conversation_LinkDialogOpen -// var phoneNumber: String? -// -// var isPhoneNumber = false -// var isEmail = false -// var hasOpenAction = true -// -// if cleanUrl.hasPrefix(mailtoString) { -// canAddToReadingList = false -// cleanUrl = String(cleanUrl[cleanUrl.index(cleanUrl.startIndex, offsetBy: mailtoString.distance(from: mailtoString.startIndex, to: mailtoString.endIndex))...]) -// isEmail = true -// } else if cleanUrl.hasPrefix(telString) { -// canAddToReadingList = false -// phoneNumber = String(cleanUrl[cleanUrl.index(cleanUrl.startIndex, offsetBy: telString.distance(from: telString.startIndex, to: telString.endIndex))...]) -// cleanUrl = phoneNumber! -// openText = strongSelf.presentationData.strings.UserInfo_PhoneCall -// canOpenIn = false -// isPhoneNumber = true -// -// if cleanUrl.hasPrefix("+888") { -// hasOpenAction = false -// } -// } else if canOpenIn { -// openText = strongSelf.presentationData.strings.Conversation_FileOpenIn -// } -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// -// var items: [ActionSheetItem] = [] -// items.append(ActionSheetTextItem(title: cleanUrl)) -// if hasOpenAction { -// items.append(ActionSheetButtonItem(title: openText, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// if canOpenIn { -// strongSelf.openUrlIn(url) -// } else { -// strongSelf.openUrl(url, concealed: false) -// } -// } -// })) -// } -// if let phoneNumber = phoneNumber { -// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_AddContact, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// strongSelf.controllerInteraction?.addContact(phoneNumber) -// } -// })) -// } -// items.append(ActionSheetButtonItem(title: canAddToReadingList ? strongSelf.presentationData.strings.ShareMenu_CopyShareLink : strongSelf.presentationData.strings.Conversation_ContextMenuCopy, color: .accent, action: { [weak actionSheet, weak self] in -// actionSheet?.dismissAnimated() -// UIPasteboard.general.string = cleanUrl -// -// let content: UndoOverlayContent -// if isPhoneNumber { -// content = .copy(text: presentationData.strings.Conversation_PhoneCopied) -// } else if isEmail { -// content = .copy(text: presentationData.strings.Conversation_EmailCopied) -// } else if canAddToReadingList { -// content = .linkCopied(text: presentationData.strings.Conversation_LinkCopied) -// } else { -// content = .copy(text: presentationData.strings.Conversation_TextCopied) -// } -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// })) -// if canAddToReadingList { -// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_AddToReadingList, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let link = URL(string: url) { -// let _ = try? SSReadingList.default()?.addItem(with: link, title: nil, previewText: nil) -// } -// })) -// } -// actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// }) -// ])]) -// strongSelf.chatDisplayNode.dismissInput() -// strongSelf.present(actionSheet, in: .window(.root)) -// case let .peerMention(peerId, mention): -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// var items: [ActionSheetItem] = [] -// if !mention.isEmpty { -// items.append(ActionSheetTextItem(title: mention)) -// } -// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// let _ = (strongSelf.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) -// |> deliverOnMainQueue).startStandalone(next: { peer in -// if let strongSelf = self, let peer = peer { -// strongSelf.openPeer(peer: peer, navigation: .chat(textInputState: nil, subject: nil, peekData: nil), fromMessage: nil) -// } -// }) -// } -// })) -// if !mention.isEmpty { -// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// UIPasteboard.general.string = mention -// -// let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_TextCopied) -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// })) -// } -// actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// }) -// ])]) -// strongSelf.chatDisplayNode.dismissInput() -// strongSelf.present(actionSheet, in: .window(.root)) -// case let .mention(mention): -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// actionSheet.setItemGroups([ActionSheetItemGroup(items: [ -// ActionSheetTextItem(title: mention), -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// strongSelf.openPeerMention(mention, sourceMessageId: message?.id) -// } -// }), -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// UIPasteboard.general.string = mention -// -// let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_UsernameCopied) -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// }) -// ]), ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// }) -// ])]) -// strongSelf.chatDisplayNode.dismissInput() -// strongSelf.present(actionSheet, in: .window(.root)) -// case let .command(command): -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// var items: [ActionSheetItem] = [] -// items.append(ActionSheetTextItem(title: command)) -// if canSendMessagesToChat(strongSelf.presentationInterfaceState) { -// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.ShareMenu_Send, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// strongSelf.sendMessages([.message(text: command, attributes: [], inlineStickers: [:], mediaReference: nil, threadId: strongSelf.chatLocation.threadId, replyToMessageId: nil, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])]) -// } -// })) -// } -// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// UIPasteboard.general.string = command -// -// let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_TextCopied) -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// })) -// actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// }) -// ])]) -// strongSelf.chatDisplayNode.dismissInput() -// strongSelf.present(actionSheet, in: .window(.root)) -// case let .hashtag(hashtag): -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// actionSheet.setItemGroups([ActionSheetItemGroup(items: [ -// ActionSheetTextItem(title: hashtag), -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// strongSelf.openHashtag(hashtag, peerName: nil) -// } -// }), -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// UIPasteboard.general.string = hashtag -// -// let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_HashtagCopied) -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// }) -// ]), ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// }) -// ])]) -// strongSelf.chatDisplayNode.dismissInput() -// strongSelf.present(actionSheet, in: .window(.root)) -// case let .timecode(timecode, text): -// guard let message = message else { -// return -// } -// -// let context = strongSelf.context -// let chatPresentationInterfaceState = strongSelf.presentationInterfaceState -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// -// var isCopyLink = false -// var isForward = false -// if message.id.namespace == Namespaces.Message.Cloud, let _ = message.peers[message.id.peerId] as? TelegramChannel, !(message.media.first is TelegramMediaAction) { -// isCopyLink = true -// } else if let forwardInfo = message.forwardInfo, let _ = forwardInfo.author as? TelegramChannel { -// isCopyLink = true -// isForward = true -// } -// -// actionSheet.setItemGroups([ActionSheetItemGroup(items: [ -// ActionSheetTextItem(title: text), -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogOpen, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// strongSelf.controllerInteraction?.seekToTimecode(message, timecode, true) -// } -// }), -// ActionSheetButtonItem(title: isCopyLink ? strongSelf.presentationData.strings.Conversation_ContextMenuCopyLink : strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// -// var messageId = message.id -// var channel = message.peers[message.id.peerId] -// if isForward, let forwardMessageId = message.forwardInfo?.sourceMessageId, let forwardAuthor = message.forwardInfo?.author as? TelegramChannel { -// messageId = forwardMessageId -// channel = forwardAuthor -// } -// -// if isCopyLink, let channel = channel as? TelegramChannel { -// var threadId: Int64? -// -// if case let .replyThread(replyThreadMessage) = chatPresentationInterfaceState.chatLocation { -// threadId = replyThreadMessage.threadId -// } -// let _ = (context.engine.messages.exportMessageLink(peerId: messageId.peerId, messageId: messageId, isThread: threadId != nil) -// |> map { result -> String? in -// return result -// } -// |> deliverOnMainQueue).startStandalone(next: { link in -// if let link = link { -// UIPasteboard.general.string = link + "?t=\(Int32(timecode))" -// -// let presentationData = context.sharedContext.currentPresentationData.with { $0 } -// -// var warnAboutPrivate = false -// if case .peer = chatPresentationInterfaceState.chatLocation { -// if channel.addressName == nil { -// warnAboutPrivate = true -// } -// } -// Queue.mainQueue().after(0.2, { -// let content: UndoOverlayContent -// if warnAboutPrivate { -// content = .linkCopied(text: presentationData.strings.Conversation_PrivateMessageLinkCopiedLong) -// } else { -// content = .linkCopied(text: presentationData.strings.Conversation_LinkCopied) -// } -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// }) -// } else { -// UIPasteboard.general.string = text -// -// let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_TextCopied) -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// } -// }) -// } else { -// UIPasteboard.general.string = text -// -// let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_TextCopied) -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// } -// }) -// ]), ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// }) -// ])]) -// strongSelf.chatDisplayNode.dismissInput() -// strongSelf.present(actionSheet, in: .window(.root)) -// case let .bankCard(number): -// guard let message = message else { -// return -// } -// -// var signal = strongSelf.context.engine.payments.getBankCardInfo(cardNumber: number) -// let disposable: MetaDisposable -// if let current = strongSelf.bankCardDisposable { -// disposable = current -// } else { -// disposable = MetaDisposable() -// strongSelf.bankCardDisposable = disposable -// } -// -// var cancelImpl: (() -> Void)? -// let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } -// let progressSignal = Signal { subscriber in -// let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: { -// cancelImpl?() -// })) -// strongSelf.present(controller, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) -// return ActionDisposable { [weak controller] in -// Queue.mainQueue().async() { -// controller?.dismiss() -// } -// } -// } -// |> runOn(Queue.mainQueue()) -// |> delay(0.15, queue: Queue.mainQueue()) -// let progressDisposable = progressSignal.startStrict() -// -// signal = signal -// |> afterDisposed { -// Queue.mainQueue().async { -// progressDisposable.dispose() -// } -// } -// cancelImpl = { -// disposable.set(nil) -// } -// disposable.set((signal -// |> deliverOnMainQueue).startStrict(next: { [weak self] info in -// if let strongSelf = self, let info = info { -// let actionSheet = ActionSheetController(presentationData: strongSelf.presentationData) -// var items: [ActionSheetItem] = [] -// items.append(ActionSheetTextItem(title: info.title)) -// for url in info.urls { -// items.append(ActionSheetButtonItem(title: url.title, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// if let strongSelf = self { -// strongSelf.controllerInteraction?.openUrl(ChatControllerInteraction.OpenUrl(url: url.url, concealed: false, external: false, message: message)) -// } -// })) -// } -// items.append(ActionSheetButtonItem(title: strongSelf.presentationData.strings.Conversation_LinkDialogCopy, color: .accent, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// UIPasteboard.general.string = number -// -// let content: UndoOverlayContent = .copy(text: presentationData.strings.Conversation_CardNumberCopied) -// self?.present(UndoOverlayController(presentationData: presentationData, content: content, elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current) -// })) -// actionSheet.setItemGroups([ActionSheetItemGroup(items: items), ActionSheetItemGroup(items: [ -// ActionSheetButtonItem(title: strongSelf.presentationData.strings.Common_Cancel, color: .accent, font: .bold, action: { [weak actionSheet] in -// actionSheet?.dismissAnimated() -// }) -// ])]) -// strongSelf.present(actionSheet, in: .window(.root)) -// } -// })) -// -// strongSelf.chatDisplayNode.dismissInput() -// }