diff --git a/submodules/AttachmentUI/BUILD b/submodules/AttachmentUI/BUILD index fc72bf71d8..e9c2f7b890 100644 --- a/submodules/AttachmentUI/BUILD +++ b/submodules/AttachmentUI/BUILD @@ -36,6 +36,7 @@ swift_library( "//submodules/Components/AnimatedStickerComponent:AnimatedStickerComponent", "//submodules/Components/MultilineTextComponent:MultilineTextComponent", "//submodules/ShimmerEffect:ShimmerEffect", + "//submodules/TextFormat:TextFormat", ], visibility = [ "//visibility:public", diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index bc1b81ada7..5e7cf29c0e 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -18,6 +18,7 @@ import SemanticStatusNode import MediaResources import MultilineTextComponent import ShimmerEffect +import TextFormat private let buttonSize = CGSize(width: 88.0, height: 49.0) private let smallButtonWidth: CGFloat = 69.0 @@ -885,20 +886,29 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, openLinkEditing: { [weak self] in if let strongSelf = self { var selectionRange: Range? - var text: String? + var text: NSAttributedString? var inputMode: ChatInputMode? strongSelf.updateChatPresentationInterfaceState(animated: true, { state in selectionRange = state.interfaceState.effectiveInputState.selectionRange if let selectionRange = selectionRange { - text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)).string + text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)) } inputMode = state.inputMode return state }) + + var link: String? + if let text { + text.enumerateAttributes(in: NSMakeRange(0, text.length)) { attributes, _, _ in + if let linkAttribute = attributes[ChatTextInputAttributes.textUrl] as? ChatTextInputTextUrlAttribute { + link = linkAttribute.url + } + } + } let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: (presentationData, .never()), account: strongSelf.context.account, text: text ?? "", link: nil, apply: { [weak self] link in + let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: (presentationData, .never()), account: strongSelf.context.account, text: text?.string ?? "", link: link, apply: { [weak self] link in if let strongSelf = self, let inputMode = inputMode, let selectionRange = selectionRange { if let link = link { strongSelf.updateChatPresentationInterfaceState(animated: true, { state in diff --git a/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift b/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift index 0206d8f688..fd54f6dd23 100644 --- a/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift +++ b/submodules/ChatTextLinkEditUI/Sources/ChatTextLinkEditController.swift @@ -12,7 +12,7 @@ import UrlEscaping private final class ChatTextLinkEditInputFieldNode: ASDisplayNode, ASEditableTextNodeDelegate { private var theme: PresentationTheme private let backgroundNode: ASImageNode - private let textInputNode: EditableTextNode + fileprivate let textInputNode: EditableTextNode private let placeholderNode: ASTextNode var updateHeight: (() -> Void)? @@ -238,6 +238,21 @@ private final class ChatTextLinkEditAlertContentNode: AlertContentNode { } self.updateTheme(theme) + + if (link ?? "").isEmpty { + Queue.mainQueue().after(0.1, { + let pasteboard = UIPasteboard.general + if pasteboard.hasURLs { + if let url = pasteboard.url?.absoluteString, !url.isEmpty { + self.inputFieldNode.text = url + if let lastNode = self.actionNodes.last { + lastNode.actionEnabled = true + } + self.inputFieldNode.textInputNode.textView.selectAll(nil) + } + } + }) + } } deinit { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index c9cb7853bb..104af2439c 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -9777,18 +9777,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, openLinkEditing: { [weak self] in if let strongSelf = self { var selectionRange: Range? - var text: String? + var text: NSAttributedString? var inputMode: ChatInputMode? strongSelf.updateChatPresentationInterfaceState(animated: false, interactive: false, { state in selectionRange = state.interfaceState.effectiveInputState.selectionRange if let selectionRange = selectionRange { - text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)).string + text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)) } inputMode = state.inputMode return state }) - let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: strongSelf.updatedPresentationData, account: strongSelf.context.account, text: text ?? "", link: nil, apply: { [weak self] link in + var link: String? + if let text { + text.enumerateAttributes(in: NSMakeRange(0, text.length)) { attributes, _, _ in + if let linkAttribute = attributes[ChatTextInputAttributes.textUrl] as? ChatTextInputTextUrlAttribute { + link = linkAttribute.url + } + } + } + + let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: strongSelf.updatedPresentationData, account: strongSelf.context.account, text: text?.string ?? "", link: link, apply: { [weak self] link in if let strongSelf = self, let inputMode = inputMode, let selectionRange = selectionRange { if let link = link { strongSelf.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in @@ -12507,18 +12516,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, openLinkEditing: { [weak self] in if let strongSelf = self { var selectionRange: Range? - var text: String? + var text: NSAttributedString? var inputMode: ChatInputMode? updateChatPresentationInterfaceStateImpl?({ state in selectionRange = state.interfaceState.effectiveInputState.selectionRange if let selectionRange = selectionRange { - text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)).string + text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)) } inputMode = state.inputMode return state }) - let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: (presentationData, .never()), account: strongSelf.context.account, text: text ?? "", link: nil, apply: { link in + var link: String? + if let text { + text.enumerateAttributes(in: NSMakeRange(0, text.length)) { attributes, _, _ in + if let linkAttribute = attributes[ChatTextInputAttributes.textUrl] as? ChatTextInputTextUrlAttribute { + link = linkAttribute.url + } + } + } + + let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: (presentationData, .never()), account: strongSelf.context.account, text: text?.string ?? "", link: link, apply: { link in if let inputMode = inputMode, let selectionRange = selectionRange { if let link = link { updateChatPresentationInterfaceStateImpl?({ @@ -16013,7 +16031,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.dismiss() let navigateToLocation: NavigateToChatControllerParams.Location - if let message = messages.first, let threadId = message.threadId, threadId != 1 || (message.peers[message.id.peerId] as? TelegramChannel)?.flags.contains(.isForum) == true { + if let message = messages.first, let threadId = message.threadId, let channel = message.peers[message.id.peerId] as? TelegramChannel, channel.flags.contains(.isForum) { navigateToLocation = .replyThread(ChatReplyThreadMessage(messageId: MessageId(peerId: peer.id, namespace: Namespaces.Message.Cloud, id: Int32(clamping: threadId)), channelMessageId: nil, isChannelPost: false, isForumPost: true, maxMessage: nil, maxReadIncomingMessageId: nil, maxReadOutgoingMessageId: nil, unreadCount: 0, initialFilledHoles: IndexSet(), initialAnchor: .automatic, isNotAvailable: false)) } else { navigateToLocation = .peer(peer) diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index cf986f9507..4f144e12ad 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -22,6 +22,7 @@ import AnimatedStickerNode import TelegramAnimatedStickerNode import SolidRoundedButtonNode import ContextUI +import TextFormat final class PeerSelectionControllerNode: ASDisplayNode { private let context: AccountContext @@ -611,19 +612,28 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, openLinkEditing: { [weak self] in if let strongSelf = self { var selectionRange: Range? - var text: String? + var text: NSAttributedString? var inputMode: ChatInputMode? strongSelf.updateChatPresentationInterfaceState(animated: true, { state in selectionRange = state.interfaceState.effectiveInputState.selectionRange if let selectionRange = selectionRange { - text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)).string + text = state.interfaceState.effectiveInputState.inputText.attributedSubstring(from: NSRange(location: selectionRange.startIndex, length: selectionRange.count)) } inputMode = state.inputMode return state }) - let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: (presentationData, .never()), account: strongSelf.context.account, text: text ?? "", link: nil, apply: { [weak self] link in + var link: String? + if let text { + text.enumerateAttributes(in: NSMakeRange(0, text.length)) { attributes, _, _ in + if let linkAttribute = attributes[ChatTextInputAttributes.textUrl] as? ChatTextInputTextUrlAttribute { + link = linkAttribute.url + } + } + } + + let controller = chatTextLinkEditController(sharedContext: strongSelf.context.sharedContext, updatedPresentationData: (presentationData, .never()), account: strongSelf.context.account, text: text?.string ?? "", link: link, apply: { [weak self] link in if let strongSelf = self, let inputMode = inputMode, let selectionRange = selectionRange { if let link = link { strongSelf.updateChatPresentationInterfaceState(animated: true, { state in