mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Merge commit '987cbeae08f8c9a79f8c2b090022b62f355a262d'
This commit is contained in:
commit
ca2664d6b1
@ -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";
|
||||||
|
File diff suppressed because it is too large
Load Diff
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Mention.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Mention.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "ic_mention.pdf",
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Mention.imageset/ic_mention.pdf
vendored
Normal file
BIN
submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Mention.imageset/ic_mention.pdf
vendored
Normal file
Binary file not shown.
Binary file not shown.
@ -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)
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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))
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user