Merge commit '987cbeae08f8c9a79f8c2b090022b62f355a262d'

This commit is contained in:
Ali 2020-07-17 22:54:37 +04:00
commit ca2664d6b1
17 changed files with 3783 additions and 3641 deletions

View File

@ -5696,3 +5696,7 @@ Any member of this group will be able to see messages in the channel.";
"EditProfile.NameAndPhotoOrVideoHelp" = "Enter your name and add an optional profile photo or video."; "EditProfile.NameAndPhotoOrVideoHelp" = "Enter your name and add an optional profile photo or video.";
"Settings.RemoveConfirmation" = "Remove"; "Settings.RemoveConfirmation" = "Remove";
"Conversation.ContextMenuOpenProfile" = "Open Profile";
"Conversation.ContextMenuSendMessage" = "Send Message";
"Conversation.ContextMenuMention" = "Mention";

View File

@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "ic_mention.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -2029,6 +2029,57 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.chatDisplayNode.animateQuizCorrectOptionSelected() strongSelf.chatDisplayNode.animateQuizCorrectOptionSelected()
}, greetingStickerNode: { [weak self] in }, greetingStickerNode: { [weak self] in
return self?.chatDisplayNode.greetingStickerNode return self?.chatDisplayNode.greetingStickerNode
}, openPeerContextMenu: { [weak self] peer, node, rect, gesture in
guard let strongSelf = self else {
return
}
let context = strongSelf.context
let _ = (context.account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peer.id)
}
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let strongSelf = self, let peer = peer, peer.smallProfileImage != nil else {
return
}
let galleryController = AvatarGalleryController(context: context, peer: peer, remoteEntries: nil, replaceRootController: { controller, ready in
}, synchronousLoad: true)
galleryController.setHintWillBePresentedInPreviewingContext(true)
let items: Signal<[ContextMenuItem], NoError> = context.account.postbox.transaction { transaction -> [ContextMenuItem] in
var items: [ContextMenuItem] = [
.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuOpenProfile, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Info"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
f(.dismissWithoutContent)
self?.openPeer(peerId: peer.id, navigation: .info, fromMessage: nil)
}))
]
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuSendMessage, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Message"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
f(.dismissWithoutContent)
self?.openPeer(peerId: peer.id, navigation: .chat(textInputState: nil, subject: nil, peekData: nil), fromMessage: nil)
})))
items.append(.action(ContextMenuActionItem(text: strongSelf.presentationData.strings.Conversation_ContextMenuMention, icon: { theme in
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Mention"), color: theme.actionSheet.primaryTextColor)
}, action: { _, f in
f(.dismissWithoutContent)
self?.interfaceInteraction?.updateTextInputStateAndMode { current, inputMode in
var inputMode = inputMode
if inputMode == .none {
inputMode = .text
}
return (chatTextInputAddMentionAttribute(current, peer: peer), inputMode)
}
})))
return items
}
let contextController = ContextController(account: strongSelf.context.account, presentationData: strongSelf.presentationData, source: .controller(ContextControllerContentSourceImpl(controller: galleryController, sourceNode: node)), items: items, reactionItems: [], gesture: gesture)
strongSelf.presentInGlobalOverlay(contextController)
})
}, requestMessageUpdate: { [weak self] id in }, requestMessageUpdate: { [weak self] id in
if let strongSelf = self { if let strongSelf = self {
strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id) strongSelf.chatDisplayNode.historyNode.requestMessageUpdate(id)

View File

@ -120,6 +120,7 @@ public final class ChatControllerInteraction {
let displayDiceTooltip: (TelegramMediaDice) -> Void let displayDiceTooltip: (TelegramMediaDice) -> Void
let animateDiceSuccess: () -> Void let animateDiceSuccess: () -> Void
let greetingStickerNode: () -> (ASDisplayNode, ASDisplayNode, ASDisplayNode, () -> Void)? let greetingStickerNode: () -> (ASDisplayNode, ASDisplayNode, ASDisplayNode, () -> Void)?
let openPeerContextMenu: (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void
let requestMessageUpdate: (MessageId) -> Void let requestMessageUpdate: (MessageId) -> Void
let cancelInteractiveKeyboardGestures: () -> Void let cancelInteractiveKeyboardGestures: () -> Void
@ -137,7 +138,7 @@ public final class ChatControllerInteraction {
var searchTextHighightState: (String, [MessageIndex])? var searchTextHighightState: (String, [MessageIndex])?
var seenOneTimeAnimatedMedia = Set<MessageId>() var seenOneTimeAnimatedMedia = Set<MessageId>()
init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, tapMessage: ((Message) -> Void)?, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?, Message?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId, Bool) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOptions: @escaping (MessageId, [Data]) -> Void, requestOpenMessagePollResults: @escaping (MessageId, MediaId) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, NSAttributedString, TextSelectionAction) -> Void, updateMessageLike: @escaping (MessageId, Bool) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, dismissReplyMarkupMessage: @escaping (Message) -> Void, openMessagePollResults: @escaping (MessageId, Data) -> Void, openPollCreation: @escaping (Bool?) -> Void, displayPollSolution: @escaping (TelegramMediaPollResults.Solution, ASDisplayNode) -> Void, displayPsa: @escaping (String, ASDisplayNode) -> Void, displayDiceTooltip: @escaping (TelegramMediaDice) -> Void, animateDiceSuccess: @escaping () -> Void, greetingStickerNode: @escaping () -> (ASDisplayNode, ASDisplayNode, ASDisplayNode, () -> Void)?, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) { init(openMessage: @escaping (Message, ChatControllerInteractionOpenMessageMode) -> Bool, openPeer: @escaping (PeerId?, ChatControllerInteractionNavigateToPeer, Message?) -> Void, openPeerMention: @escaping (String) -> Void, openMessageContextMenu: @escaping (Message, Bool, ASDisplayNode, CGRect, UIGestureRecognizer?) -> Void, openMessageContextActions: @escaping (Message, ASDisplayNode, CGRect, ContextGesture?) -> Void, navigateToMessage: @escaping (MessageId, MessageId) -> Void, tapMessage: ((Message) -> Void)?, clickThroughMessage: @escaping () -> Void, toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, ASDisplayNode, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect) -> Bool, sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageId, Int32) -> Void, activateSwitchInline: @escaping (PeerId?, String) -> Void, openUrl: @escaping (String, Bool, Bool?, Message?) -> Void, shareCurrentLocation: @escaping () -> Void, shareAccountContact: @escaping () -> Void, sendBotCommand: @escaping (MessageId?, String) -> Void, openInstantPage: @escaping (Message, ChatMessageItemAssociatedData?) -> Void, openWallpaper: @escaping (Message) -> Void, openTheme: @escaping (Message) -> Void, openHashtag: @escaping (String?, String) -> Void, updateInputState: @escaping ((ChatTextInputState) -> ChatTextInputState) -> Void, updateInputMode: @escaping ((ChatInputMode) -> ChatInputMode) -> Void, openMessageShareMenu: @escaping (MessageId) -> Void, presentController: @escaping (ViewController, Any?) -> Void, navigationController: @escaping () -> NavigationController?, chatControllerNode: @escaping () -> ASDisplayNode?, reactionContainerNode: @escaping () -> ReactionSelectionParentNode?, presentGlobalOverlayController: @escaping (ViewController, Any?) -> Void, callPeer: @escaping (PeerId, Bool) -> Void, longTap: @escaping (ChatControllerInteractionLongTapAction, Message?) -> Void, openCheckoutOrReceipt: @escaping (MessageId) -> Void, openSearch: @escaping () -> Void, setupReply: @escaping (MessageId) -> Void, canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction, navigateToFirstDateMessage: @escaping(Int32) ->Void, requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void, addContact: @escaping (String) -> Void, rateCall: @escaping (Message, CallId) -> Void, requestSelectMessagePollOptions: @escaping (MessageId, [Data]) -> Void, requestOpenMessagePollResults: @escaping (MessageId, MediaId) -> Void, openAppStorePage: @escaping () -> Void, displayMessageTooltip: @escaping (MessageId, String, ASDisplayNode?, CGRect?) -> Void, seekToTimecode: @escaping (Message, Double, Bool) -> Void, scheduleCurrentMessage: @escaping () -> Void, sendScheduledMessagesNow: @escaping ([MessageId]) -> Void, editScheduledMessagesTime: @escaping ([MessageId]) -> Void, performTextSelectionAction: @escaping (UInt32, NSAttributedString, TextSelectionAction) -> Void, updateMessageLike: @escaping (MessageId, Bool) -> Void, openMessageReactions: @escaping (MessageId) -> Void, displaySwipeToReplyHint: @escaping () -> Void, dismissReplyMarkupMessage: @escaping (Message) -> Void, openMessagePollResults: @escaping (MessageId, Data) -> Void, openPollCreation: @escaping (Bool?) -> Void, displayPollSolution: @escaping (TelegramMediaPollResults.Solution, ASDisplayNode) -> Void, displayPsa: @escaping (String, ASDisplayNode) -> Void, displayDiceTooltip: @escaping (TelegramMediaDice) -> Void, animateDiceSuccess: @escaping () -> Void, greetingStickerNode: @escaping () -> (ASDisplayNode, ASDisplayNode, ASDisplayNode, () -> Void)?, openPeerContextMenu: @escaping (Peer, ASDisplayNode, CGRect, ContextGesture?) -> Void, requestMessageUpdate: @escaping (MessageId) -> Void, cancelInteractiveKeyboardGestures: @escaping () -> Void, automaticMediaDownloadSettings: MediaAutoDownloadSettings, pollActionState: ChatInterfacePollActionState, stickerSettings: ChatInterfaceStickerSettings) {
self.openMessage = openMessage self.openMessage = openMessage
self.openPeer = openPeer self.openPeer = openPeer
self.openPeerMention = openPeerMention self.openPeerMention = openPeerMention
@ -201,6 +202,7 @@ public final class ChatControllerInteraction {
self.displayDiceTooltip = displayDiceTooltip self.displayDiceTooltip = displayDiceTooltip
self.animateDiceSuccess = animateDiceSuccess self.animateDiceSuccess = animateDiceSuccess
self.greetingStickerNode = greetingStickerNode self.greetingStickerNode = greetingStickerNode
self.openPeerContextMenu = openPeerContextMenu
self.requestMessageUpdate = requestMessageUpdate self.requestMessageUpdate = requestMessageUpdate
self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures self.cancelInteractiveKeyboardGestures = cancelInteractiveKeyboardGestures
@ -248,6 +250,7 @@ public final class ChatControllerInteraction {
}, animateDiceSuccess: { }, animateDiceSuccess: {
}, greetingStickerNode: { }, greetingStickerNode: {
return nil return nil
}, openPeerContextMenu: { _, _, _, _ in
}, requestMessageUpdate: { _ in }, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: { }, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -1,6 +1,7 @@
import Foundation import Foundation
import UIKit import UIKit
import Postbox import Postbox
import AsyncDisplayKit
import Display import Display
import TelegramCore import TelegramCore
import SyncCore import SyncCore
@ -17,16 +18,18 @@ final class ChatMessageAvatarAccessoryItem: ListViewAccessoryItem {
private let messageReference: MessageReference? private let messageReference: MessageReference?
private let messageTimestamp: Int32 private let messageTimestamp: Int32
private let emptyColor: UIColor private let emptyColor: UIColor
private let controllerInteraction: ChatControllerInteraction
private let day: Int32 private let day: Int32
init(context: AccountContext, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, messageTimestamp: Int32, emptyColor: UIColor) { init(context: AccountContext, peerId: PeerId, peer: Peer?, messageReference: MessageReference?, messageTimestamp: Int32, emptyColor: UIColor, controllerInteraction: ChatControllerInteraction) {
self.context = context self.context = context
self.peerId = peerId self.peerId = peerId
self.peer = peer self.peer = peer
self.messageReference = messageReference self.messageReference = messageReference
self.messageTimestamp = messageTimestamp self.messageTimestamp = messageTimestamp
self.emptyColor = emptyColor self.emptyColor = emptyColor
self.controllerInteraction = controllerInteraction
var t: time_t = time_t(messageTimestamp) var t: time_t = time_t(messageTimestamp)
var timeinfo: tm = tm() var timeinfo: tm = tm()
@ -47,29 +50,57 @@ final class ChatMessageAvatarAccessoryItem: ListViewAccessoryItem {
let node = ChatMessageAvatarAccessoryItemNode() let node = ChatMessageAvatarAccessoryItemNode()
node.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0)) node.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0))
if let peer = self.peer { if let peer = self.peer {
node.setPeer(context: self.context, theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme, synchronousLoad: synchronous, peer: peer, authorOfMessage: self.messageReference, emptyColor: self.emptyColor) node.setPeer(context: self.context, theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme, synchronousLoad: synchronous, peer: peer, authorOfMessage: self.messageReference, emptyColor: self.emptyColor, controllerInteraction: self.controllerInteraction)
} }
return node return node
} }
} }
final class ChatMessageAvatarAccessoryItemNode: ListViewAccessoryItemNode { final class ChatMessageAvatarAccessoryItemNode: ListViewAccessoryItemNode {
var controllerInteraction: ChatControllerInteraction?
var peer: Peer?
let containerNode: ContextControllerSourceNode
let avatarNode: AvatarNode let avatarNode: AvatarNode
var contextActionIsEnabled: Bool = true {
didSet {
if self.contextActionIsEnabled != oldValue {
self.containerNode.isGestureEnabled = self.contextActionIsEnabled
}
}
}
override init() { override init() {
let isLayerBacked = !smartInvertColorsEnabled() self.containerNode = ContextControllerSourceNode()
self.containerNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0))
self.avatarNode = AvatarNode(font: avatarFont) self.avatarNode = AvatarNode(font: avatarFont)
self.avatarNode.isLayerBacked = isLayerBacked self.avatarNode.isLayerBacked = !smartInvertColorsEnabled()
self.avatarNode.frame = CGRect(origin: CGPoint(), size: CGSize(width: 38.0, height: 38.0)) self.avatarNode.frame = self.containerNode.bounds
self.avatarNode.isUserInteractionEnabled = false
super.init() super.init()
self.isLayerBacked = isLayerBacked self.isLayerBacked = false
self.addSubnode(self.avatarNode)
self.addSubnode(self.containerNode)
self.containerNode.addSubnode(self.avatarNode)
self.containerNode.activated = { [weak self] gesture, _ in
guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction, let peer = strongSelf.peer else {
return
}
strongSelf.controllerInteraction?.openPeerContextMenu(peer, strongSelf.containerNode, strongSelf.containerNode.bounds, gesture)
}
} }
func setPeer(context: AccountContext, theme: PresentationTheme, synchronousLoad:Bool, peer: Peer, authorOfMessage: MessageReference?, emptyColor: UIColor) { func setPeer(context: AccountContext, theme: PresentationTheme, synchronousLoad:Bool, peer: Peer, authorOfMessage: MessageReference?, emptyColor: UIColor, controllerInteraction: ChatControllerInteraction) {
self.controllerInteraction = controllerInteraction
self.peer = peer
self.contextActionIsEnabled = peer.smallProfileImage != nil
var overrideImage: AvatarNodeImageOverride? var overrideImage: AvatarNodeImageOverride?
if peer.isDeleted { if peer.isDeleted {
overrideImage = .deletedIcon overrideImage = .deletedIcon

View File

@ -2719,7 +2719,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
} }
if let avatarNode = self.accessoryItemNode as? ChatMessageAvatarAccessoryItemNode, avatarNode.frame.contains(point) { if let avatarNode = self.accessoryItemNode as? ChatMessageAvatarAccessoryItemNode, avatarNode.frame.contains(point) {
return self.view return avatarNode.containerNode.view
} }
if !self.backgroundNode.frame.contains(point) { if !self.backgroundNode.frame.contains(point) {

View File

@ -368,7 +368,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
} }
if !hasActionMedia && !isBroadcastChannel { if !hasActionMedia && !isBroadcastChannel {
if let effectiveAuthor = effectiveAuthor { if let effectiveAuthor = effectiveAuthor {
accessoryItem = ChatMessageAvatarAccessoryItem(context: context, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), messageTimestamp: content.index.timestamp, emptyColor: presentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper.fill) accessoryItem = ChatMessageAvatarAccessoryItem(context: context, peerId: effectiveAuthor.id, peer: effectiveAuthor, messageReference: MessageReference(message), messageTimestamp: content.index.timestamp, emptyColor: presentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper.fill, controllerInteraction: controllerInteraction)
} }
} }
} }

View File

@ -450,6 +450,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, animateDiceSuccess: { }, animateDiceSuccess: {
}, greetingStickerNode: { }, greetingStickerNode: {
return nil return nil
}, openPeerContextMenu: { _, _, _, _ in
}, requestMessageUpdate: { _ in }, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: { }, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, }, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,

View File

@ -1,5 +1,6 @@
import Foundation import Foundation
import TextFormat import TextFormat
import Postbox
import AccountContext import AccountContext
func chatTextInputAddFormattingAttribute(_ state: ChatTextInputState, attribute: NSAttributedString.Key) -> ChatTextInputState { func chatTextInputAddFormattingAttribute(_ state: ChatTextInputState, attribute: NSAttributedString.Key) -> ChatTextInputState {
@ -75,3 +76,33 @@ func chatTextInputAddLinkAttribute(_ state: ChatTextInputState, url: String) ->
return state return state
} }
} }
func chatTextInputAddMentionAttribute(_ state: ChatTextInputState, peer: Peer) -> ChatTextInputState {
let inputText = NSMutableAttributedString(attributedString: state.inputText)
let range = NSMakeRange(state.selectionRange.startIndex, state.selectionRange.endIndex - state.selectionRange.startIndex)
if let addressName = peer.addressName, !addressName.isEmpty {
let replacementText = "@\(addressName) "
inputText.replaceCharacters(in: range, with: replacementText)
let selectionPosition = range.lowerBound + (replacementText as NSString).length
return ChatTextInputState(inputText: inputText, selectionRange: selectionPosition ..< selectionPosition)
} else if !peer.compactDisplayTitle.isEmpty {
let replacementText = NSMutableAttributedString()
replacementText.append(NSAttributedString(string: peer.compactDisplayTitle, attributes: [ChatTextInputAttributes.textMention: ChatTextInputTextMentionAttribute(peerId: peer.id)]))
replacementText.append(NSAttributedString(string: " "))
let updatedRange = NSRange(location: range.location , length: range.length)
inputText.replaceCharacters(in: updatedRange, with: replacementText)
let selectionPosition = updatedRange.lowerBound + replacementText.length
return ChatTextInputState(inputText: inputText, selectionRange: selectionPosition ..< selectionPosition)
} else {
return state
}
}

View File

@ -143,6 +143,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode {
}, animateDiceSuccess: { }, animateDiceSuccess: {
}, greetingStickerNode: { }, greetingStickerNode: {
return nil return nil
}, openPeerContextMenu: { _, _, _, _ in
}, requestMessageUpdate: { _ in }, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: { }, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -130,6 +130,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
}, animateDiceSuccess: { }, animateDiceSuccess: {
}, greetingStickerNode: { }, greetingStickerNode: {
return nil return nil
}, openPeerContextMenu: { _, _, _, _ in
}, requestMessageUpdate: { _ in }, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: { }, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false)) }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(loopAnimatedStickers: false))

View File

@ -1952,6 +1952,7 @@ private final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewD
}, animateDiceSuccess: { }, animateDiceSuccess: {
}, greetingStickerNode: { }, greetingStickerNode: {
return nil return nil
}, openPeerContextMenu: { _, _, _, _ in
}, requestMessageUpdate: { _ in }, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: { }, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -435,6 +435,7 @@ public class PeerMediaCollectionController: TelegramBaseController {
}, animateDiceSuccess: { }, animateDiceSuccess: {
}, greetingStickerNode: { }, greetingStickerNode: {
return nil return nil
}, openPeerContextMenu: { _, _, _, _ in
}, requestMessageUpdate: { _ in }, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: { }, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,

View File

@ -1189,6 +1189,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
}, animateDiceSuccess: { }, animateDiceSuccess: {
}, greetingStickerNode: { }, greetingStickerNode: {
return nil return nil
}, openPeerContextMenu: { _, _, _, _ in
}, requestMessageUpdate: { _ in }, requestMessageUpdate: { _ in
}, cancelInteractiveKeyboardGestures: { }, cancelInteractiveKeyboardGestures: {
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, }, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,