mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
[WIP] Quotes
This commit is contained in:
parent
afcc8f39f2
commit
f1a9bec56d
@ -10102,3 +10102,5 @@ Sorry for the inconvenience.";
|
||||
|
||||
"GiftLink.LinkSharedToChat" = "Gift link forwarded to **%@**";
|
||||
"GiftLink.LinkSharedToSavedMessages" = "Gift link forwarded to **Saved Messages**";
|
||||
|
||||
"ChatContextMenu.TextSelectionTip2" = "Hold on a word, then move cursor to select more| text to copy or quote.";
|
||||
|
@ -528,10 +528,23 @@ public enum ChatControllerSubject: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public struct MessageOptionsInfo: Equatable {
|
||||
public enum Kind {
|
||||
case forward
|
||||
case reply
|
||||
}
|
||||
|
||||
public let kind: Kind
|
||||
|
||||
public init(kind: Kind) {
|
||||
self.kind = kind
|
||||
}
|
||||
}
|
||||
|
||||
case message(id: MessageSubject, highlight: Bool, timecode: Double?)
|
||||
case scheduledMessages
|
||||
case pinnedMessages(id: EngineMessage.Id?)
|
||||
case forwardedMessages(peerIds: [EnginePeer.Id], ids: [EngineMessage.Id], options: Signal<ForwardOptions, NoError>)
|
||||
case messageOptions(peerIds: [EnginePeer.Id], ids: [EngineMessage.Id], info: MessageOptionsInfo, options: Signal<ForwardOptions, NoError>)
|
||||
|
||||
public static func ==(lhs: ChatControllerSubject, rhs: ChatControllerSubject) -> Bool {
|
||||
switch lhs {
|
||||
@ -553,8 +566,8 @@ public enum ChatControllerSubject: Equatable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .forwardedMessages(lhsPeerIds, lhsIds, _):
|
||||
if case let .forwardedMessages(rhsPeerIds, rhsIds, _) = rhs, lhsPeerIds == rhsPeerIds, lhsIds == rhsIds {
|
||||
case let .messageOptions(lhsPeerIds, lhsIds, lhsInfo, _):
|
||||
if case let .messageOptions(rhsPeerIds, rhsIds, rhsInfo, _) = rhs, lhsPeerIds == rhsPeerIds, lhsIds == rhsIds, lhsInfo == rhsInfo {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
@ -778,6 +778,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate {
|
||||
strongSelf.updateChatPresentationInterfaceState(animated: true, { $0.updatedInterfaceState({ $0.withUpdatedForwardOptionsState($0.forwardOptionsState) }) })
|
||||
}
|
||||
}, presentForwardOptions: { _ in
|
||||
}, presentReplyOptions: { _ in
|
||||
}, shareSelectedMessages: {
|
||||
}, updateTextInputStateAndMode: { [weak self] f in
|
||||
if let strongSelf = self {
|
||||
|
@ -80,6 +80,7 @@ public final class ChatPanelInterfaceInteraction {
|
||||
public let forwardMessages: ([Message]) -> Void
|
||||
public let updateForwardOptionsState: ((ChatInterfaceForwardOptionsState) -> ChatInterfaceForwardOptionsState) -> Void
|
||||
public let presentForwardOptions: (ASDisplayNode) -> Void
|
||||
public let presentReplyOptions: (ASDisplayNode) -> Void
|
||||
public let shareSelectedMessages: () -> Void
|
||||
public let updateTextInputStateAndMode: (@escaping (ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void
|
||||
public let updateInputModeAndDismissedButtonKeyboardMessageId: ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void
|
||||
@ -184,6 +185,7 @@ public final class ChatPanelInterfaceInteraction {
|
||||
forwardMessages: @escaping ([Message]) -> Void,
|
||||
updateForwardOptionsState: @escaping ((ChatInterfaceForwardOptionsState) -> ChatInterfaceForwardOptionsState) -> Void,
|
||||
presentForwardOptions: @escaping (ASDisplayNode) -> Void,
|
||||
presentReplyOptions: @escaping (ASDisplayNode) -> Void,
|
||||
shareSelectedMessages: @escaping () -> Void,
|
||||
updateTextInputStateAndMode: @escaping ((ChatTextInputState, ChatInputMode) -> (ChatTextInputState, ChatInputMode)) -> Void,
|
||||
updateInputModeAndDismissedButtonKeyboardMessageId: @escaping ((ChatPresentationInterfaceState) -> (ChatInputMode, MessageId?)) -> Void,
|
||||
@ -287,6 +289,7 @@ public final class ChatPanelInterfaceInteraction {
|
||||
self.forwardMessages = forwardMessages
|
||||
self.updateForwardOptionsState = updateForwardOptionsState
|
||||
self.presentForwardOptions = presentForwardOptions
|
||||
self.presentReplyOptions = presentReplyOptions
|
||||
self.shareSelectedMessages = shareSelectedMessages
|
||||
self.updateTextInputStateAndMode = updateTextInputStateAndMode
|
||||
self.updateInputModeAndDismissedButtonKeyboardMessageId = updateInputModeAndDismissedButtonKeyboardMessageId
|
||||
@ -398,6 +401,7 @@ public final class ChatPanelInterfaceInteraction {
|
||||
}, forwardMessages: { _ in
|
||||
}, updateForwardOptionsState: { _ in
|
||||
}, presentForwardOptions: { _ in
|
||||
}, presentReplyOptions: { _ in
|
||||
}, shareSelectedMessages: {
|
||||
}, updateTextInputStateAndMode: updateTextInputStateAndMode, updateInputModeAndDismissedButtonKeyboardMessageId: updateInputModeAndDismissedButtonKeyboardMessageId, openStickers: {
|
||||
}, editMessage: {
|
||||
|
@ -393,7 +393,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode {
|
||||
var icon: UIImage?
|
||||
switch tip {
|
||||
case .textSelection:
|
||||
var rawText = self.presentationData.strings.ChatContextMenu_TextSelectionTip
|
||||
var rawText = self.presentationData.strings.ChatContextMenu_TextSelectionTip2
|
||||
if let range = rawText.range(of: "|") {
|
||||
rawText.removeSubrange(range)
|
||||
self.text = rawText
|
||||
|
@ -181,6 +181,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
||||
case storyStealthModeReplyCount = 47
|
||||
case viewOnceTooltip = 48
|
||||
case displayStoryUnmuteTooltip = 49
|
||||
case chatReplyOptionsTip = 50
|
||||
|
||||
var key: ValueBoxKey {
|
||||
let v = ValueBoxKey(length: 4)
|
||||
@ -355,6 +356,10 @@ private struct ApplicationSpecificNoticeKeys {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatForwardOptionsTip.key)
|
||||
}
|
||||
|
||||
static func chatReplyOptionsTip() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.chatReplyOptionsTip.key)
|
||||
}
|
||||
|
||||
static func interactiveEmojiSyncTip() -> NoticeEntryKey {
|
||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.interactiveEmojiSyncTip.key)
|
||||
}
|
||||
@ -1245,6 +1250,33 @@ public struct ApplicationSpecificNotice {
|
||||
}
|
||||
}
|
||||
|
||||
public static func getChatReplyOptionsTip(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||
return accountManager.transaction { transaction -> Int32 in
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatReplyOptionsTip())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
return value.value
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static func incrementChatReplyOptionsTip(accountManager: AccountManager<TelegramAccountManagerTypes>, count: Int = 1) -> Signal<Int, NoError> {
|
||||
return accountManager.transaction { transaction -> Int in
|
||||
var currentValue: Int32 = 0
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.chatReplyOptionsTip())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
currentValue = value.value
|
||||
}
|
||||
let previousValue = currentValue
|
||||
currentValue += Int32(count)
|
||||
|
||||
if let entry = CodableEntry(ApplicationSpecificCounterNotice(value: currentValue)) {
|
||||
transaction.setNotice(ApplicationSpecificNoticeKeys.chatReplyOptionsTip(), entry)
|
||||
}
|
||||
|
||||
return Int(previousValue)
|
||||
}
|
||||
}
|
||||
|
||||
public static func getClearStorageDismissedTipSize(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||
return accountManager.transaction { transaction -> Int32 in
|
||||
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.clearStorageDismissedTipSize())?.get(ApplicationSpecificCounterNotice.self) {
|
||||
|
@ -87,7 +87,7 @@ public func stringForMessageTimestampStatus(accountPeerId: PeerId, message: Mess
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
authorTitle = nil
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let message = item.message
|
||||
|
||||
let incoming: Bool
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
} else {
|
||||
incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
@ -181,7 +181,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
let dateFormat: MessageTimestampStatusFormat
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
dateFormat = .minimal
|
||||
} else {
|
||||
dateFormat = .regular
|
||||
@ -344,7 +344,7 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
let textFont = item.presentationData.messageFont
|
||||
|
||||
if let entities = entities {
|
||||
attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseQuoteTintColor: messageTheme.accentControlColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont, message: item.message, adjustQuoteFontSize: true)
|
||||
attributedText = stringWithAppliedEntities(rawText, entities: entities, baseColor: messageTheme.primaryTextColor, linkColor: messageTheme.linkTextColor, baseQuoteTintColor: messageTheme.accentTextColor, baseFont: textFont, linkFont: textFont, boldFont: item.presentationData.messageBoldFont, italicFont: item.presentationData.messageItalicFont, boldItalicFont: item.presentationData.messageBoldItalicFont, fixedFont: item.presentationData.messageFixedFont, blockQuoteFont: item.presentationData.messageBlockQuoteFont, message: item.message, adjustQuoteFontSize: true)
|
||||
} else if !rawText.isEmpty {
|
||||
attributedText = NSAttributedString(string: rawText, font: textFont, textColor: messageTheme.primaryTextColor)
|
||||
} else {
|
||||
@ -563,6 +563,10 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
} else {
|
||||
strongSelf.statusNode.pressed = nil
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .reply = info.kind {
|
||||
strongSelf.updateIsExtractedToContextPreview(true)
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@ -369,7 +369,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
let chatController = strongSelf.context.sharedContext.makeChatController(
|
||||
context: strongSelf.context,
|
||||
chatLocation: .peer(id: strongSelf.context.account.peerId),
|
||||
subject: .forwardedMessages(peerIds: peerIds, ids: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], options: forwardOptions),
|
||||
subject: .messageOptions(peerIds: peerIds, ids: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], info: ChatControllerSubject.MessageOptionsInfo(kind: .forward), options: forwardOptions),
|
||||
botStart: nil,
|
||||
mode: .standard(previewing: true)
|
||||
)
|
||||
@ -543,6 +543,7 @@ final class PeerSelectionControllerNode: ASDisplayNode {
|
||||
}
|
||||
contextController.immediateItemsTransitionAnimation = true
|
||||
strongSelf.controller?.presentInGlobalOverlay(contextController)
|
||||
}, presentReplyOptions: { _ in
|
||||
}, shareSelectedMessages: {
|
||||
}, updateTextInputStateAndMode: { [weak self] f in
|
||||
if let strongSelf = self {
|
||||
|
@ -0,0 +1,279 @@
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AsyncDisplayKit
|
||||
import Display
|
||||
import SwiftSignalKit
|
||||
import Postbox
|
||||
import TelegramCore
|
||||
import TelegramPresentationData
|
||||
import AccountContext
|
||||
import ChatPresentationInterfaceState
|
||||
import ContextUI
|
||||
|
||||
func presentChatForwardOptions(selfController: ChatControllerImpl, sourceNode: ASDisplayNode) {
|
||||
guard let peerId = selfController.chatLocation.peerId else {
|
||||
return
|
||||
}
|
||||
let presentationData = selfController.presentationData
|
||||
|
||||
let forwardOptions = selfController.presentationInterfaceStatePromise.get()
|
||||
|> map { state -> ChatControllerSubject.ForwardOptions in
|
||||
var hideNames = state.interfaceState.forwardOptionsState?.hideNames ?? false
|
||||
if peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
hideNames = true
|
||||
}
|
||||
return ChatControllerSubject.ForwardOptions(hideNames: hideNames, hideCaptions: state.interfaceState.forwardOptionsState?.hideCaptions ?? false)
|
||||
}
|
||||
|> distinctUntilChanged
|
||||
|
||||
let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [peerId], ids: selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? [], info: ChatControllerSubject.MessageOptionsInfo(kind: .forward), options: forwardOptions), botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
|
||||
let messageIds = selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
let messagesCount: Signal<Int, NoError>
|
||||
if let chatController = chatController as? ChatControllerImpl, messageIds.count > 1 {
|
||||
messagesCount = .single(messageIds.count)
|
||||
|> then(
|
||||
chatController.presentationInterfaceStatePromise.get()
|
||||
|> map { state -> Int in
|
||||
return state.interfaceState.selectionState?.selectedIds.count ?? 1
|
||||
}
|
||||
)
|
||||
} else {
|
||||
messagesCount = .single(1)
|
||||
}
|
||||
|
||||
let accountPeerId = selfController.context.account.peerId
|
||||
let items = combineLatest(forwardOptions, selfController.context.account.postbox.messagesAtIds(messageIds), messagesCount)
|
||||
|> deliverOnMainQueue
|
||||
|> map { [weak selfController] forwardOptions, messages, messagesCount -> [ContextMenuItem] in
|
||||
guard let selfController else {
|
||||
return []
|
||||
}
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
var hasCaptions = false
|
||||
var uniquePeerIds = Set<PeerId>()
|
||||
|
||||
var hasOther = false
|
||||
var hasNotOwnMessages = false
|
||||
for message in messages {
|
||||
if let author = message.effectiveAuthor {
|
||||
if !uniquePeerIds.contains(author.id) {
|
||||
uniquePeerIds.insert(author.id)
|
||||
}
|
||||
if message.id.peerId == accountPeerId && message.forwardInfo == nil {
|
||||
} else {
|
||||
hasNotOwnMessages = true
|
||||
}
|
||||
}
|
||||
|
||||
var isDice = false
|
||||
var isMusic = false
|
||||
for media in message.media {
|
||||
if let media = media as? TelegramMediaFile, media.isMusic {
|
||||
isMusic = true
|
||||
} else if media is TelegramMediaDice {
|
||||
isDice = true
|
||||
} else {
|
||||
if !message.text.isEmpty {
|
||||
if media is TelegramMediaImage || media is TelegramMediaFile {
|
||||
hasCaptions = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !isDice && !isMusic {
|
||||
hasOther = true
|
||||
}
|
||||
}
|
||||
|
||||
var canHideNames = hasNotOwnMessages && hasOther
|
||||
if case let .peer(peerId) = selfController.chatLocation, peerId.namespace == Namespaces.Peer.SecretChat {
|
||||
canHideNames = false
|
||||
}
|
||||
let hideNames = forwardOptions.hideNames
|
||||
let hideCaptions = forwardOptions.hideCaptions
|
||||
|
||||
if canHideNames {
|
||||
items.append(.action(ContextMenuActionItem(text: uniquePeerIds.count == 1 ? presentationData.strings.Conversation_ForwardOptions_ShowSendersName : presentationData.strings.Conversation_ForwardOptions_ShowSendersNames, icon: { theme in
|
||||
if hideNames {
|
||||
return nil
|
||||
} else {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
|
||||
}
|
||||
}, action: { [weak selfController] _, f in
|
||||
selfController?.interfaceInteraction?.updateForwardOptionsState({ current in
|
||||
var updated = current
|
||||
updated.hideNames = false
|
||||
updated.hideCaptions = false
|
||||
updated.unhideNamesOnCaptionChange = false
|
||||
return updated
|
||||
})
|
||||
})))
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: uniquePeerIds.count == 1 ? presentationData.strings.Conversation_ForwardOptions_HideSendersName : presentationData.strings.Conversation_ForwardOptions_HideSendersNames, icon: { theme in
|
||||
if hideNames {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}, action: { [weak selfController] _, f in
|
||||
selfController?.interfaceInteraction?.updateForwardOptionsState({ current in
|
||||
var updated = current
|
||||
updated.hideNames = true
|
||||
updated.unhideNamesOnCaptionChange = false
|
||||
return updated
|
||||
})
|
||||
})))
|
||||
|
||||
items.append(.separator)
|
||||
}
|
||||
|
||||
if hasCaptions {
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ForwardOptions_ShowCaption, icon: { theme in
|
||||
if hideCaptions {
|
||||
return nil
|
||||
} else {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
|
||||
}
|
||||
}, action: { [weak selfController] _, f in
|
||||
selfController?.interfaceInteraction?.updateForwardOptionsState({ current in
|
||||
var updated = current
|
||||
updated.hideCaptions = false
|
||||
if canHideNames {
|
||||
if updated.unhideNamesOnCaptionChange {
|
||||
updated.unhideNamesOnCaptionChange = false
|
||||
updated.hideNames = false
|
||||
}
|
||||
}
|
||||
return updated
|
||||
})
|
||||
})))
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ForwardOptions_HideCaption, icon: { theme in
|
||||
if hideCaptions {
|
||||
return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Check"), color: theme.contextMenu.primaryColor)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}, action: { [weak selfController] _, f in
|
||||
selfController?.interfaceInteraction?.updateForwardOptionsState({ current in
|
||||
var updated = current
|
||||
updated.hideCaptions = true
|
||||
if canHideNames {
|
||||
if !updated.hideNames {
|
||||
updated.hideNames = true
|
||||
updated.unhideNamesOnCaptionChange = true
|
||||
}
|
||||
}
|
||||
return updated
|
||||
})
|
||||
})))
|
||||
|
||||
items.append(.separator)
|
||||
}
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ForwardOptions_ChangeRecipient, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) }, action: { [weak selfController] c, f in
|
||||
selfController?.interfaceInteraction?.forwardCurrentForwardMessages()
|
||||
|
||||
f(.default)
|
||||
})))
|
||||
|
||||
items.append(.action(ContextMenuActionItem(text: messagesCount == 1 ? presentationData.strings.Conversation_ForwardOptions_SendMessage : presentationData.strings.Conversation_ForwardOptions_SendMessages, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Resend"), color: theme.contextMenu.primaryColor) }, action: { [weak selfController, weak chatController] c, f in
|
||||
guard let selfController else {
|
||||
return
|
||||
}
|
||||
if let selectedMessageIds = (chatController as? ChatControllerImpl)?.selectedMessageIds {
|
||||
var forwardMessageIds = selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
forwardMessageIds = forwardMessageIds.filter { selectedMessageIds.contains($0) }
|
||||
selfController.updateChatPresentationInterfaceState(interactive: false, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(forwardMessageIds) }) })
|
||||
}
|
||||
|
||||
selfController.controllerInteraction?.sendCurrentMessage(false)
|
||||
|
||||
f(.default)
|
||||
})))
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
selfController.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
|
||||
|
||||
selfController.canReadHistory.set(false)
|
||||
|
||||
let contextController = ContextController(presentationData: selfController.presentationData, source: .controller(ChatContextControllerContentSourceImpl(controller: chatController, sourceNode: sourceNode, passthroughTouches: true)), items: items |> map { ContextController.Items(content: .list($0)) })
|
||||
contextController.dismissed = { [weak selfController] in
|
||||
selfController?.canReadHistory.set(true)
|
||||
}
|
||||
contextController.dismissedForCancel = { [weak selfController, weak chatController] in
|
||||
guard let selfController else {
|
||||
return
|
||||
}
|
||||
if let selectedMessageIds = (chatController as? ChatControllerImpl)?.selectedMessageIds {
|
||||
var forwardMessageIds = selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
forwardMessageIds = forwardMessageIds.filter { selectedMessageIds.contains($0) }
|
||||
selfController.updateChatPresentationInterfaceState(interactive: false, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(forwardMessageIds) }) })
|
||||
}
|
||||
}
|
||||
contextController.immediateItemsTransitionAnimation = true
|
||||
selfController.presentInGlobalOverlay(contextController)
|
||||
}
|
||||
|
||||
|
||||
func presentChatReplyOptions(selfController: ChatControllerImpl, sourceNode: ASDisplayNode) {
|
||||
guard let peerId = selfController.chatLocation.peerId else {
|
||||
return
|
||||
}
|
||||
guard let replySubject = selfController.presentationInterfaceState.interfaceState.replyMessageSubject else {
|
||||
return
|
||||
}
|
||||
|
||||
//let presentationData = selfController.presentationData
|
||||
|
||||
let chatController = selfController.context.sharedContext.makeChatController(context: selfController.context, chatLocation: .peer(id: peerId), subject: .messageOptions(peerIds: [replySubject.messageId.peerId], ids: [replySubject.messageId], info: ChatControllerSubject.MessageOptionsInfo(kind: .reply), options: .single(ChatControllerSubject.ForwardOptions(hideNames: false, hideCaptions: false))), botStart: nil, mode: .standard(previewing: true))
|
||||
chatController.canReadHistory.set(false)
|
||||
|
||||
let messageIds: [EngineMessage.Id] = [replySubject.messageId]
|
||||
let messagesCount: Signal<Int, NoError> = .single(1)
|
||||
|
||||
//let accountPeerId = selfController.context.account.peerId
|
||||
let items = combineLatest(selfController.context.account.postbox.messagesAtIds(messageIds), messagesCount)
|
||||
|> deliverOnMainQueue
|
||||
|> map { [weak selfController] messages, messagesCount -> [ContextMenuItem] in
|
||||
guard let selfController else {
|
||||
return []
|
||||
}
|
||||
var items: [ContextMenuItem] = []
|
||||
|
||||
//TODO:localize
|
||||
items.append(.action(ContextMenuActionItem(text: "Reply in Another Chat", icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Forward"), color: theme.contextMenu.primaryColor) }, action: { [weak selfController] c, f in
|
||||
selfController?.interfaceInteraction?.forwardCurrentForwardMessages()
|
||||
|
||||
f(.default)
|
||||
})))
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
selfController.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
|
||||
|
||||
selfController.canReadHistory.set(false)
|
||||
|
||||
let contextController = ContextController(presentationData: selfController.presentationData, source: .controller(ChatContextControllerContentSourceImpl(controller: chatController, sourceNode: sourceNode, passthroughTouches: true)), items: items |> map { ContextController.Items(content: .list($0)) })
|
||||
contextController.dismissed = { [weak selfController] in
|
||||
selfController?.canReadHistory.set(true)
|
||||
}
|
||||
contextController.dismissedForCancel = { [weak selfController, weak chatController] in
|
||||
guard let selfController else {
|
||||
return
|
||||
}
|
||||
if let selectedMessageIds = (chatController as? ChatControllerImpl)?.selectedMessageIds {
|
||||
var forwardMessageIds = selfController.presentationInterfaceState.interfaceState.forwardMessageIds ?? []
|
||||
forwardMessageIds = forwardMessageIds.filter { selectedMessageIds.contains($0) }
|
||||
selfController.updateChatPresentationInterfaceState(interactive: false, { $0.updatedInterfaceState({ $0.withUpdatedForwardMessageIds(forwardMessageIds) }) })
|
||||
}
|
||||
}
|
||||
contextController.immediateItemsTransitionAnimation = true
|
||||
selfController.presentInGlobalOverlay(contextController)
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -30,6 +30,7 @@ import ForwardAccessoryPanelNode
|
||||
import ChatOverscrollControl
|
||||
import ChatInputPanelNode
|
||||
import ChatInputContextPanelNode
|
||||
import TextSelectionNode
|
||||
|
||||
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
|
||||
let itemNode: OverlayMediaItemNode
|
||||
@ -392,7 +393,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
self.inputContextOverTextPanelContainer = ChatControllerTitlePanelNodeContainer()
|
||||
|
||||
var source: ChatHistoryListSource
|
||||
if case let .forwardedMessages(_, messageIds, options) = subject {
|
||||
if case let .messageOptions(_, messageIds, info, options) = subject {
|
||||
let messages = combineLatest(context.account.postbox.messagesAtIds(messageIds), context.account.postbox.loadedPeerWithId(context.account.peerId), options)
|
||||
|> map { messages, accountPeer, options -> ([Message], Int32, Bool) in
|
||||
var messages = messages
|
||||
@ -412,28 +413,30 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
|
||||
var attributes = message.attributes
|
||||
attributes = attributes.filter({ attribute in
|
||||
if attribute is EditedMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if !forwardedMessageIds.contains(attribute.messageId) || hideNames {
|
||||
if case .forward = info.kind {
|
||||
if attribute is EditedMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if let attribute = attribute as? ReplyMessageAttribute {
|
||||
if !forwardedMessageIds.contains(attribute.messageId) || hideNames {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if attribute is ReplyMarkupMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if attribute is ReplyThreadMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if attribute is ViewCountMessageAttribute{
|
||||
return false
|
||||
}
|
||||
if attribute is ForwardCountMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if attribute is ReactionsMessageAttribute {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if attribute is ReplyMarkupMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if attribute is ReplyThreadMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if attribute is ViewCountMessageAttribute{
|
||||
return false
|
||||
}
|
||||
if attribute is ForwardCountMessageAttribute {
|
||||
return false
|
||||
}
|
||||
if attribute is ReactionsMessageAttribute {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
@ -2965,6 +2968,14 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
|
||||
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
switch self.chatPresentationInterfaceState.mode {
|
||||
case .standard(previewing: true):
|
||||
if let subject = self.controller?.subject, case let .messageOptions(_, _, info, _) = subject, case .reply = info.kind {
|
||||
if let result = self.historyNode.view.hitTest(self.view.convert(point, to: self.historyNode.view), with: event), let node = result.asyncdisplaykit_node {
|
||||
if node is TextSelectionNode {
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let result = self.historyNode.view.hitTest(self.view.convert(point, to: self.historyNode.view), with: event), let node = result.asyncdisplaykit_node, node is ChatMessageSelectionNode || node is GridMessageSelectionNode {
|
||||
return result
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ func accessoryPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceS
|
||||
}
|
||||
|
||||
switch chatPresentationInterfaceState.subject {
|
||||
case .pinnedMessages, .forwardedMessages:
|
||||
return nil
|
||||
default:
|
||||
break
|
||||
case .pinnedMessages, .messageOptions:
|
||||
return nil
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if let editMessage = chatPresentationInterfaceState.interfaceState.editMessage {
|
||||
|
@ -16,7 +16,7 @@ func inputPanelForChatPresentationIntefaceState(_ chatPresentationInterfaceState
|
||||
return (nil, nil)
|
||||
}
|
||||
|
||||
if case .forwardedMessages = chatPresentationInterfaceState.subject {
|
||||
if case .messageOptions = chatPresentationInterfaceState.subject {
|
||||
return (nil, nil)
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ struct ChatNavigationButton: Equatable {
|
||||
|
||||
func leftNavigationButtonForChatInterfaceState(_ presentationInterfaceState: ChatPresentationInterfaceState, subject: ChatControllerSubject?, strings: PresentationStrings, currentButton: ChatNavigationButton?, target: Any?, selector: Selector?) -> ChatNavigationButton? {
|
||||
if let _ = presentationInterfaceState.interfaceState.selectionState {
|
||||
if case .forwardedMessages = presentationInterfaceState.subject {
|
||||
if case .messageOptions = presentationInterfaceState.subject {
|
||||
return nil
|
||||
}
|
||||
if let _ = presentationInterfaceState.reportReason {
|
||||
@ -78,7 +78,7 @@ func leftNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Cha
|
||||
|
||||
func rightNavigationButtonForChatInterfaceState(_ presentationInterfaceState: ChatPresentationInterfaceState, strings: PresentationStrings, currentButton: ChatNavigationButton?, target: Any?, selector: Selector?, chatInfoNavigationButton: ChatNavigationButton?, moreInfoNavigationButton: ChatNavigationButton?) -> ChatNavigationButton? {
|
||||
if let _ = presentationInterfaceState.interfaceState.selectionState {
|
||||
if case .forwardedMessages = presentationInterfaceState.subject {
|
||||
if case .messageOptions = presentationInterfaceState.subject {
|
||||
return nil
|
||||
}
|
||||
if let currentButton = currentButton, currentButton.action == .cancelMessageSelection {
|
||||
@ -107,7 +107,7 @@ func rightNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Ch
|
||||
}
|
||||
}
|
||||
|
||||
if case .forwardedMessages = presentationInterfaceState.subject {
|
||||
if case .messageOptions = presentationInterfaceState.subject {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ func titlePanelForChatPresentationInterfaceState(_ chatPresentationInterfaceStat
|
||||
|
||||
var inhibitTitlePanelDisplay = false
|
||||
switch chatPresentationInterfaceState.subject {
|
||||
case .forwardedMessages:
|
||||
case .messageOptions:
|
||||
return nil
|
||||
case .scheduledMessages, .pinnedMessages:
|
||||
inhibitTitlePanelDisplay = true
|
||||
|
@ -1065,7 +1065,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
@ -1438,7 +1438,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
|
||||
var transition: ContainedViewLayoutTransition = .immediate
|
||||
if case let .System(duration, _) = animation {
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
transition = .animated(duration: duration, curve: .linear)
|
||||
} else {
|
||||
transition = .animated(duration: duration, curve: .spring)
|
||||
|
@ -378,7 +378,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
|
||||
let textBlockQuoteFont = Font.regular(fontSize)
|
||||
|
||||
var incoming = message.effectivelyIncoming(context.account.peerId)
|
||||
if case .forwardedMessages = associatedData.subject {
|
||||
if let subject = associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
}
|
||||
|
||||
|
@ -1122,6 +1122,11 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
}
|
||||
self.replyRecognizer = replyRecognizer
|
||||
self.view.addGestureRecognizer(replyRecognizer)
|
||||
|
||||
if let item = self.item, let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
self.tapRecognizer?.isEnabled = false
|
||||
self.replyRecognizer?.isEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
override func asyncLayout() -> (_ item: ChatMessageItem, _ params: ListViewItemLayoutParams, _ mergedTop: ChatMessageMerge, _ mergedBottom: ChatMessageMerge, _ dateHeaderAtBottom: Bool) -> (ListViewItemNodeLayout, (ListViewItemUpdateAnimation, ListViewItemApply, Bool) -> Void) {
|
||||
@ -1233,7 +1238,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
do {
|
||||
let peerId = chatLocationPeerId
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
displayAuthorInfo = false
|
||||
} else if item.message.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
|
||||
if let forwardInfo = item.content.firstMessage.forwardInfo {
|
||||
@ -1412,7 +1417,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
@ -1904,7 +1909,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
}
|
||||
|
||||
let dateFormat: MessageTimestampStatusFormat
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
dateFormat = .minimal
|
||||
} else {
|
||||
dateFormat = .regular
|
||||
@ -2697,7 +2702,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
if case let .System(duration, _) = animation {
|
||||
legacyTransition = .animated(duration: duration, curve: .spring)
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
useDisplayLinkAnimations = true
|
||||
}
|
||||
}
|
||||
@ -3525,6 +3530,15 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
strongSelf.mainContextSourceNode.layoutUpdated?(strongSelf.mainContextSourceNode.bounds.size, animation)
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
strongSelf.tapRecognizer?.isEnabled = false
|
||||
strongSelf.replyRecognizer?.isEnabled = false
|
||||
strongSelf.mainContainerNode.isGestureEnabled = false
|
||||
for contentContainer in strongSelf.contentContainers {
|
||||
contentContainer.containerNode.isGestureEnabled = false
|
||||
}
|
||||
}
|
||||
|
||||
strongSelf.updateSearchTextHighlightState()
|
||||
|
||||
if let (_, f) = strongSelf.awaitingAppliedReaction {
|
||||
@ -3532,7 +3546,6 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode
|
||||
|
||||
f()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override func updateAccessibilityData(_ accessibilityData: ChatMessageAccessibilityData) {
|
||||
|
@ -96,7 +96,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
var incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
if case .forwardedMessages = item.associatedData.subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
var incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
if case .forwardedMessages = item.associatedData.subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
}
|
||||
let statusType: ChatMessageDateAndStatusType?
|
||||
|
@ -185,7 +185,7 @@ class ChatMessageGiveawayBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
var incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
if case .forwardedMessages = item.associatedData.subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,7 @@ class ChatMessageInstantVideoBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
var incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
if case .forwardedMessages = item.associatedData.subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
}
|
||||
|
||||
|
@ -375,7 +375,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
||||
var updatedMuteIconImage: UIImage?
|
||||
|
||||
var incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
if case .forwardedMessages = item.associatedData.subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ public enum ChatMessageItemContent: Sequence {
|
||||
case group(messages: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)])
|
||||
|
||||
func effectivelyIncoming(_ accountPeerId: PeerId, associatedData: ChatMessageItemAssociatedData? = nil) -> Bool {
|
||||
if let subject = associatedData?.subject, case .forwardedMessages = subject {
|
||||
if let subject = associatedData?.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
return false
|
||||
}
|
||||
switch self {
|
||||
@ -420,7 +420,7 @@ public final class ChatMessageItem: ListViewItem, CustomStringConvertible {
|
||||
self.avatarHeader = avatarHeader
|
||||
|
||||
var headers: [ListViewItemHeader] = [self.dateHeader]
|
||||
if case .forwardedMessages = associatedData.subject {
|
||||
if case .messageOptions = associatedData.subject {
|
||||
headers = []
|
||||
}
|
||||
if let avatarHeader = self.avatarHeader {
|
||||
|
@ -92,7 +92,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
|
||||
}
|
||||
|
||||
var incoming = item.message.effectivelyIncoming(item.context.account.peerId)
|
||||
if case .forwardedMessages = item.associatedData.subject {
|
||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info, _) = subject, case .forward = info.kind {
|
||||
incoming = false
|
||||
}
|
||||
|
||||
|
@ -528,7 +528,7 @@ class ChatMessageStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
|
||||
if let subject = item.associatedData.subject, case .forwardedMessages = subject {
|
||||
if let subject = item.associatedData.subject, case .messageOptions = subject {
|
||||
needsShareButton = false
|
||||
}
|
||||
|
||||
|
@ -73,6 +73,7 @@ final class ChatRecentActionsController: TelegramBaseController {
|
||||
}, forwardMessages: { _ in
|
||||
}, updateForwardOptionsState: { _ in
|
||||
}, presentForwardOptions: { _ in
|
||||
}, presentReplyOptions: { _ in
|
||||
}, shareSelectedMessages: {
|
||||
}, updateTextInputStateAndMode: { _ in
|
||||
}, updateInputModeAndDismissedButtonKeyboardMessageId: { _ in
|
||||
|
@ -310,6 +310,7 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode {
|
||||
}, forwardMessages: { _ in
|
||||
}, updateForwardOptionsState: { _ in
|
||||
}, presentForwardOptions: { _ in
|
||||
}, presentReplyOptions: { _ in
|
||||
}, shareSelectedMessages: {
|
||||
shareMessages()
|
||||
}, updateTextInputStateAndMode: { _ in
|
||||
|
@ -17,6 +17,7 @@ import TextNodeWithEntities
|
||||
import AnimationCache
|
||||
import MultiAnimationRenderer
|
||||
import AccessoryPanelNode
|
||||
import TelegramNotices
|
||||
|
||||
final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
private let messageDisposable = MetaDisposable()
|
||||
@ -286,7 +287,11 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
|
||||
override func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) {
|
||||
if self.theme !== theme {
|
||||
self.updateThemeAndStrings(theme: theme, strings: strings, force: false)
|
||||
}
|
||||
|
||||
private func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings, force: Bool) {
|
||||
if self.theme !== theme || force {
|
||||
self.theme = theme
|
||||
|
||||
self.closeButton.setImage(PresentationResourcesChat.chatInputPanelCloseIconImage(theme), for: [])
|
||||
@ -362,9 +367,26 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
|
||||
}
|
||||
}
|
||||
|
||||
@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
private var previousTapTimestamp: Double?
|
||||
@objc private func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
let timestamp = CFAbsoluteTimeGetCurrent()
|
||||
if let previousTapTimestamp = self.previousTapTimestamp, previousTapTimestamp + 1.0 > timestamp {
|
||||
return
|
||||
}
|
||||
self.previousTapTimestamp = CFAbsoluteTimeGetCurrent()
|
||||
self.interfaceInteraction?.presentReplyOptions(self)
|
||||
Queue.mainQueue().after(1.5) {
|
||||
self.updateThemeAndStrings(theme: self.theme, strings: self.strings, force: true)
|
||||
}
|
||||
|
||||
let _ = ApplicationSpecificNotice.incrementChatReplyOptionsTip(accountManager: self.context.sharedContext.accountManager, count: 3).start()
|
||||
}
|
||||
}
|
||||
|
||||
/*@objc func tapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||
if case .ended = recognizer.state {
|
||||
self.interfaceInteraction?.navigateToMessage(self.messageId, false, true, .generic)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user