mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various improvements
This commit is contained in:
parent
00455e1163
commit
ab5e3ae947
@ -985,6 +985,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
private var cachedChatListText: (String, String)?
|
private var cachedChatListText: (String, String)?
|
||||||
private var cachedChatListSearchResult: CachedChatListSearchResult?
|
private var cachedChatListSearchResult: CachedChatListSearchResult?
|
||||||
|
private var cachedChatListQuoteSearchResult: CachedChatListSearchResult?
|
||||||
private var cachedCustomTextEntities: CachedCustomTextEntities?
|
private var cachedCustomTextEntities: CachedCustomTextEntities?
|
||||||
|
|
||||||
var layoutParams: (ChatListItem, first: Bool, last: Bool, firstWithHeader: Bool, nextIsPinned: Bool, ListViewItemLayoutParams, countersSize: CGFloat)?
|
var layoutParams: (ChatListItem, first: Bool, last: Bool, firstWithHeader: Bool, nextIsPinned: Bool, ListViewItemLayoutParams, countersSize: CGFloat)?
|
||||||
@ -1585,6 +1586,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
let currentItem = self.layoutParams?.0
|
let currentItem = self.layoutParams?.0
|
||||||
let currentChatListText = self.cachedChatListText
|
let currentChatListText = self.cachedChatListText
|
||||||
let currentChatListSearchResult = self.cachedChatListSearchResult
|
let currentChatListSearchResult = self.cachedChatListSearchResult
|
||||||
|
let currentChatListQuoteSearchResult = self.cachedChatListQuoteSearchResult
|
||||||
let currentCustomTextEntities = self.cachedCustomTextEntities
|
let currentCustomTextEntities = self.cachedCustomTextEntities
|
||||||
|
|
||||||
return { item, params, first, last, firstWithHeader, nextIsPinned in
|
return { item, params, first, last, firstWithHeader, nextIsPinned in
|
||||||
@ -1869,6 +1871,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
|
|
||||||
var chatListText: (String, String)?
|
var chatListText: (String, String)?
|
||||||
var chatListSearchResult: CachedChatListSearchResult?
|
var chatListSearchResult: CachedChatListSearchResult?
|
||||||
|
var chatListQuoteSearchResult: CachedChatListSearchResult?
|
||||||
var customTextEntities: CachedCustomTextEntities?
|
var customTextEntities: CachedCustomTextEntities?
|
||||||
|
|
||||||
let contentImageSide: CGFloat = max(10.0, min(20.0, floor(item.presentationData.fontSize.baseDisplaySize * 18.0 / 17.0)))
|
let contentImageSide: CGFloat = max(10.0, min(20.0, floor(item.presentationData.fontSize.baseDisplaySize * 18.0 / 17.0)))
|
||||||
@ -2016,15 +2019,45 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
composedString = NSMutableAttributedString(attributedString: messageString)
|
composedString = NSMutableAttributedString(attributedString: messageString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var composedReplyString: NSMutableAttributedString?
|
||||||
if let searchQuery = item.interaction.searchTextHighightState {
|
if let searchQuery = item.interaction.searchTextHighightState {
|
||||||
|
var quoteText: String?
|
||||||
|
for attribute in message.attributes {
|
||||||
|
if let attribute = attribute as? ReplyMessageAttribute {
|
||||||
|
if let quote = attribute.quote {
|
||||||
|
quoteText = quote.text
|
||||||
|
}
|
||||||
|
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||||
|
if let quote = attribute.quote {
|
||||||
|
quoteText = quote.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let quoteText {
|
||||||
|
let quoteString = foldLineBreaks(stringWithAppliedEntities(quoteText, entities: [], baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: italicTextFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false, message: nil))
|
||||||
|
composedReplyString = NSMutableAttributedString(attributedString: quoteString)
|
||||||
|
}
|
||||||
|
|
||||||
if let cached = currentChatListSearchResult, cached.matches(text: composedString.string, searchQuery: searchQuery) {
|
if let cached = currentChatListSearchResult, cached.matches(text: composedString.string, searchQuery: searchQuery) {
|
||||||
chatListSearchResult = cached
|
chatListSearchResult = cached
|
||||||
} else {
|
} else {
|
||||||
let (ranges, text) = findSubstringRanges(in: composedString.string, query: searchQuery)
|
let (ranges, text) = findSubstringRanges(in: composedString.string, query: searchQuery)
|
||||||
chatListSearchResult = CachedChatListSearchResult(text: text, searchQuery: searchQuery, resultRanges: ranges)
|
chatListSearchResult = CachedChatListSearchResult(text: text, searchQuery: searchQuery, resultRanges: ranges)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let composedReplyString {
|
||||||
|
if let cached = currentChatListQuoteSearchResult, cached.matches(text: composedReplyString.string, searchQuery: searchQuery) {
|
||||||
|
chatListQuoteSearchResult = cached
|
||||||
|
} else {
|
||||||
|
let (ranges, text) = findSubstringRanges(in: composedReplyString.string, query: searchQuery)
|
||||||
|
chatListQuoteSearchResult = CachedChatListSearchResult(text: text, searchQuery: searchQuery, resultRanges: ranges)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chatListQuoteSearchResult = nil
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
chatListSearchResult = nil
|
chatListSearchResult = nil
|
||||||
|
chatListQuoteSearchResult = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let chatListSearchResult = chatListSearchResult, let firstRange = chatListSearchResult.resultRanges.first {
|
if let chatListSearchResult = chatListSearchResult, let firstRange = chatListSearchResult.resultRanges.first {
|
||||||
@ -2053,6 +2086,34 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
composedString = composedString.attributedSubstring(from: NSMakeRange(leftOrigin, composedString.length - leftOrigin)).mutableCopy() as! NSMutableAttributedString
|
composedString = composedString.attributedSubstring(from: NSMakeRange(leftOrigin, composedString.length - leftOrigin)).mutableCopy() as! NSMutableAttributedString
|
||||||
composedString.insert(NSAttributedString(string: "\u{2026}", attributes: [NSAttributedString.Key.font: textFont, NSAttributedString.Key.foregroundColor: theme.messageTextColor]), at: 0)
|
composedString.insert(NSAttributedString(string: "\u{2026}", attributes: [NSAttributedString.Key.font: textFont, NSAttributedString.Key.foregroundColor: theme.messageTextColor]), at: 0)
|
||||||
}
|
}
|
||||||
|
} else if var composedReplyString, let chatListQuoteSearchResult, let firstRange = chatListQuoteSearchResult.resultRanges.first {
|
||||||
|
for range in chatListQuoteSearchResult.resultRanges {
|
||||||
|
let stringRange = NSRange(range, in: chatListQuoteSearchResult.text)
|
||||||
|
if stringRange.location >= 0 && stringRange.location + stringRange.length <= composedReplyString.length {
|
||||||
|
var stringRange = stringRange
|
||||||
|
if stringRange.location > composedReplyString.length {
|
||||||
|
continue
|
||||||
|
} else if stringRange.location + stringRange.length > composedReplyString.length {
|
||||||
|
stringRange.length = composedReplyString.length - stringRange.location
|
||||||
|
}
|
||||||
|
composedReplyString.addAttribute(.foregroundColor, value: theme.messageHighlightedTextColor, range: stringRange)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let firstRangeOrigin = chatListQuoteSearchResult.text.distance(from: chatListQuoteSearchResult.text.startIndex, to: firstRange.lowerBound)
|
||||||
|
if firstRangeOrigin > 24 {
|
||||||
|
var leftOrigin: Int = 0
|
||||||
|
(composedReplyString.string as NSString).enumerateSubstrings(in: NSMakeRange(0, firstRangeOrigin), options: [.byWords, .reverse]) { (str, range1, _, _) in
|
||||||
|
let distanceFromEnd = firstRangeOrigin - range1.location
|
||||||
|
if (distanceFromEnd > 12 || range1.location == 0) && leftOrigin == 0 {
|
||||||
|
leftOrigin = range1.location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
composedReplyString = composedReplyString.attributedSubstring(from: NSMakeRange(leftOrigin, composedReplyString.length - leftOrigin)).mutableCopy() as! NSMutableAttributedString
|
||||||
|
composedReplyString.insert(NSAttributedString(string: "\u{2026}", attributes: [NSAttributedString.Key.font: textFont, NSAttributedString.Key.foregroundColor: theme.messageTextColor]), at: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
composedString = composedReplyString
|
||||||
}
|
}
|
||||||
|
|
||||||
attributedText = composedString
|
attributedText = composedString
|
||||||
@ -2712,6 +2773,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
|
|||||||
strongSelf.currentItemHeight = itemHeight
|
strongSelf.currentItemHeight = itemHeight
|
||||||
strongSelf.cachedChatListText = chatListText
|
strongSelf.cachedChatListText = chatListText
|
||||||
strongSelf.cachedChatListSearchResult = chatListSearchResult
|
strongSelf.cachedChatListSearchResult = chatListSearchResult
|
||||||
|
strongSelf.cachedChatListQuoteSearchResult = chatListQuoteSearchResult
|
||||||
strongSelf.cachedCustomTextEntities = customTextEntities
|
strongSelf.cachedCustomTextEntities = customTextEntities
|
||||||
strongSelf.onlineIsVoiceChat = onlineIsVoiceChat
|
strongSelf.onlineIsVoiceChat = onlineIsVoiceChat
|
||||||
|
|
||||||
|
@ -738,14 +738,21 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode,
|
|||||||
var textFrame = self.textFieldFrame
|
var textFrame = self.textFieldFrame
|
||||||
textFrame.origin = CGPoint(x: 13.0, y: 6.0 - UIScreenPixel)
|
textFrame.origin = CGPoint(x: 13.0, y: 6.0 - UIScreenPixel)
|
||||||
textFrame.size.height = self.textInputView.contentSize.height
|
textFrame.size.height = self.textInputView.contentSize.height
|
||||||
textFrame.size.width -= self.textInputView.textContainerInset.right
|
if let textInputView = self.textInputView as? ChatInputTextView {
|
||||||
|
textFrame.size.width -= textInputView.defaultTextContainerInset.right
|
||||||
|
} else {
|
||||||
|
textFrame.size.width -= self.textInputView.textContainerInset.right
|
||||||
|
}
|
||||||
|
|
||||||
if self.textInputView.isRTL {
|
if self.textInputView.isRTL {
|
||||||
textFrame.origin.x -= messageOriginDelta
|
textFrame.origin.x -= messageOriginDelta
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fromMessageTextNode.frame = textFrame
|
self.fromMessageTextNode.frame = textFrame
|
||||||
|
self.fromMessageTextNode.updateLayout(size: textFrame.size)
|
||||||
|
|
||||||
self.toMessageTextNode.frame = textFrame
|
self.toMessageTextNode.frame = textFrame
|
||||||
|
self.toMessageTextNode.updateLayout(size: textFrame.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
|
@objc private func dimTapGesture(_ recognizer: UITapGestureRecognizer) {
|
||||||
|
@ -738,7 +738,11 @@ public extension ContainedViewLayoutTransition {
|
|||||||
case .immediate:
|
case .immediate:
|
||||||
layer.removeAnimation(forKey: "position")
|
layer.removeAnimation(forKey: "position")
|
||||||
layer.removeAnimation(forKey: "bounds")
|
layer.removeAnimation(forKey: "bounds")
|
||||||
layer.frame = frame
|
if let view = layer.delegate as? UIView {
|
||||||
|
view.frame = frame
|
||||||
|
} else {
|
||||||
|
layer.frame = frame
|
||||||
|
}
|
||||||
if let completion = completion {
|
if let completion = completion {
|
||||||
completion(true)
|
completion(true)
|
||||||
}
|
}
|
||||||
|
@ -184,6 +184,7 @@ private enum ApplicationSpecificGlobalNotice: Int32 {
|
|||||||
case chatReplyOptionsTip = 50
|
case chatReplyOptionsTip = 50
|
||||||
case displayStoryInteractionGuide = 51
|
case displayStoryInteractionGuide = 51
|
||||||
case dismissedPremiumAppIconsBadge = 52
|
case dismissedPremiumAppIconsBadge = 52
|
||||||
|
case replyQuoteTextSelectionTip = 53
|
||||||
|
|
||||||
var key: ValueBoxKey {
|
var key: ValueBoxKey {
|
||||||
let v = ValueBoxKey(length: 4)
|
let v = ValueBoxKey(length: 4)
|
||||||
@ -449,6 +450,10 @@ private struct ApplicationSpecificNoticeKeys {
|
|||||||
static func dismissedPremiumAppIconsBadge() -> NoticeEntryKey {
|
static func dismissedPremiumAppIconsBadge() -> NoticeEntryKey {
|
||||||
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedPremiumAppIconsBadge.key)
|
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.dismissedPremiumAppIconsBadge.key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func replyQuoteTextSelectionTip() -> NoticeEntryKey {
|
||||||
|
return NoticeEntryKey(namespace: noticeNamespace(namespace: globalNamespace), key: ApplicationSpecificGlobalNotice.replyQuoteTextSelectionTip.key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct ApplicationSpecificNotice {
|
public struct ApplicationSpecificNotice {
|
||||||
@ -924,6 +929,30 @@ public struct ApplicationSpecificNotice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static func getReplyQuoteTextSelectionTips(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||||
|
return accountManager.transaction { transaction -> Int32 in
|
||||||
|
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.replyQuoteTextSelectionTip())?.get(ApplicationSpecificCounterNotice.self) {
|
||||||
|
return value.value
|
||||||
|
} else {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static func incrementReplyQuoteTextSelectionTips(accountManager: AccountManager<TelegramAccountManagerTypes>, count: Int32 = 1) -> Signal<Void, NoError> {
|
||||||
|
return accountManager.transaction { transaction -> Void in
|
||||||
|
var currentValue: Int32 = 0
|
||||||
|
if let value = transaction.getNotice(ApplicationSpecificNoticeKeys.replyQuoteTextSelectionTip())?.get(ApplicationSpecificCounterNotice.self) {
|
||||||
|
currentValue = value.value
|
||||||
|
}
|
||||||
|
currentValue += count
|
||||||
|
|
||||||
|
if let entry = CodableEntry(ApplicationSpecificCounterNotice(value: currentValue)) {
|
||||||
|
transaction.setNotice(ApplicationSpecificNoticeKeys.replyQuoteTextSelectionTip(), entry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static func getMessageViewsPrivacyTips(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
public static func getMessageViewsPrivacyTips(accountManager: AccountManager<TelegramAccountManagerTypes>) -> Signal<Int32, NoError> {
|
||||||
return accountManager.transaction { transaction -> Int32 in
|
return accountManager.transaction { transaction -> Int32 in
|
||||||
|
@ -1488,8 +1488,10 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var replyBackgroundFrame: CGRect?
|
||||||
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
||||||
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize)
|
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize)
|
||||||
|
replyBackgroundFrame = replyInfoFrame
|
||||||
|
|
||||||
let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation)
|
let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation)
|
||||||
if strongSelf.replyInfoNode == nil {
|
if strongSelf.replyInfoNode == nil {
|
||||||
@ -1504,8 +1506,8 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
strongSelf.replyInfoNode = nil
|
strongSelf.replyInfoNode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
if let replyBackgroundNode = strongSelf.replyBackgroundNode, let replyBackgroundFrame {
|
||||||
replyBackgroundNode.frame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 10.0)) - 4.0, y: headersOffset + 6.0), size: CGSize(width: messageInfoSize.width + 8.0, height: messageInfoSize.height + 5.0))
|
replyBackgroundNode.frame = replyBackgroundFrame
|
||||||
|
|
||||||
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
||||||
replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate)
|
replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate)
|
||||||
@ -1974,6 +1976,10 @@ public class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
|||||||
return .optionalAction({
|
return .optionalAction({
|
||||||
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
||||||
})
|
})
|
||||||
|
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||||
|
return .action({
|
||||||
|
item.controllerInteraction.attemptedNavigationToPrivateQuote(attribute.peerId.flatMap { item.message.peers[$0] })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -843,14 +843,14 @@ public final class ChatMessageAttachedContentNode: ASDisplayNode {
|
|||||||
if let current = self.backgroundView {
|
if let current = self.backgroundView {
|
||||||
backgroundView = current
|
backgroundView = current
|
||||||
animation.animator.updateFrame(layer: backgroundView.layer, frame: backgroundFrame, completion: nil)
|
animation.animator.updateFrame(layer: backgroundView.layer, frame: backgroundFrame, completion: nil)
|
||||||
|
backgroundView.update(size: backgroundFrame.size, primaryColor: mainColor, secondaryColor: secondaryColor, pattern: nil, animation: animation)
|
||||||
} else {
|
} else {
|
||||||
backgroundView = MessageInlineBlockBackgroundView()
|
backgroundView = MessageInlineBlockBackgroundView()
|
||||||
self.backgroundView = backgroundView
|
self.backgroundView = backgroundView
|
||||||
backgroundView.frame = backgroundFrame
|
backgroundView.frame = backgroundFrame
|
||||||
self.transformContainer.view.insertSubview(backgroundView, at: 0)
|
self.transformContainer.view.insertSubview(backgroundView, at: 0)
|
||||||
|
backgroundView.update(size: backgroundFrame.size, primaryColor: mainColor, secondaryColor: secondaryColor, pattern: nil, animation: .None)
|
||||||
}
|
}
|
||||||
|
|
||||||
backgroundView.update(size: backgroundFrame.size, primaryColor: mainColor, secondaryColor: secondaryColor, pattern: nil, animation: animation)
|
|
||||||
} else {
|
} else {
|
||||||
if let backgroundView = self.backgroundView {
|
if let backgroundView = self.backgroundView {
|
||||||
self.backgroundView = nil
|
self.backgroundView = nil
|
||||||
|
@ -3955,6 +3955,10 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
return .action({
|
return .action({
|
||||||
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
||||||
})
|
})
|
||||||
|
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||||
|
return .action({
|
||||||
|
item.controllerInteraction.attemptedNavigationToPrivateQuote(attribute.peerId.flatMap { item.message.peers[$0] })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4159,6 +4163,10 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
|
|||||||
return .action({
|
return .action({
|
||||||
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
||||||
})
|
})
|
||||||
|
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||||
|
return .action({
|
||||||
|
item.controllerInteraction.attemptedNavigationToPrivateQuote(attribute.peerId.flatMap { item.message.peers[$0] })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -761,8 +761,10 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var replyBackgroundFrame: CGRect?
|
||||||
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
||||||
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: 8.0 + messageInfoSize.height), size: replyInfoSize)
|
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: 8.0 + messageInfoSize.height), size: replyInfoSize)
|
||||||
|
replyBackgroundFrame = replyInfoFrame
|
||||||
|
|
||||||
let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation)
|
let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation)
|
||||||
if strongSelf.replyInfoNode == nil {
|
if strongSelf.replyInfoNode == nil {
|
||||||
@ -777,8 +779,8 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco
|
|||||||
strongSelf.replyInfoNode = nil
|
strongSelf.replyInfoNode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
if let replyBackgroundNode = strongSelf.replyBackgroundNode, let replyBackgroundFrame {
|
||||||
replyBackgroundNode.frame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 10.0)) - 4.0, y: 6.0), size: CGSize(width: messageInfoSize.width + 8.0, height: messageInfoSize.height + 5.0))
|
replyBackgroundNode.frame = replyBackgroundFrame
|
||||||
|
|
||||||
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
||||||
replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate)
|
replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate)
|
||||||
@ -963,6 +965,10 @@ public class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureReco
|
|||||||
return .optionalAction({
|
return .optionalAction({
|
||||||
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text))
|
item.controllerInteraction.navigateToMessage(item.message.id, attribute.messageId, NavigateToMessageParams(timestamp: nil, quote: attribute.quote?.text))
|
||||||
})
|
})
|
||||||
|
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||||
|
return .action({
|
||||||
|
item.controllerInteraction.attemptedNavigationToPrivateQuote(attribute.peerId.flatMap { item.message.peers[$0] })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -999,8 +999,10 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var replyBackgroundFrame: CGRect?
|
||||||
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
||||||
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (displayVideoFrame.maxX - width + 5.0) : (width - messageInfoSize.width - bubbleEdgeInset - 9.0 + 10.0)), y: 8.0 + messageInfoSize.height), size: replyInfoSize)
|
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (displayVideoFrame.maxX - width + 5.0) : (width - messageInfoSize.width - bubbleEdgeInset - 9.0 + 10.0)), y: 8.0 + messageInfoSize.height), size: replyInfoSize)
|
||||||
|
replyBackgroundFrame = replyInfoFrame
|
||||||
|
|
||||||
let replyInfoNode = replyInfoApply(replyInfoFrame.size, false, animation)
|
let replyInfoNode = replyInfoApply(replyInfoFrame.size, false, animation)
|
||||||
if strongSelf.replyInfoNode == nil {
|
if strongSelf.replyInfoNode == nil {
|
||||||
@ -1015,8 +1017,8 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
strongSelf.replyInfoNode = nil
|
strongSelf.replyInfoNode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
if let replyBackgroundNode = strongSelf.replyBackgroundNode, let replyBackgroundFrame {
|
||||||
let replyBackgroundFrame = CGRect(origin: CGPoint(x: (!incoming ? (displayVideoFrame.maxX - width + 4.0) : (width - messageInfoSize.width - bubbleEdgeInset)) - 4.0, y: 6.0), size: CGSize(width: messageInfoSize.width + 8.0, height: messageInfoSize.height + 5.0))
|
let replyBackgroundFrame = replyBackgroundFrame
|
||||||
animation.animator.updateFrame(layer: replyBackgroundNode.layer, frame: replyBackgroundFrame, completion: nil)
|
animation.animator.updateFrame(layer: replyBackgroundNode.layer, frame: replyBackgroundFrame, completion: nil)
|
||||||
|
|
||||||
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
||||||
@ -1294,6 +1296,9 @@ public class ChatMessageInteractiveInstantVideoNode: ASDisplayNode {
|
|||||||
} else if let attribute = attribute as? ReplyStoryAttribute {
|
} else if let attribute = attribute as? ReplyStoryAttribute {
|
||||||
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
||||||
return
|
return
|
||||||
|
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||||
|
item.controllerInteraction.attemptedNavigationToPrivateQuote(attribute.peerId.flatMap { item.message.peers[$0] })
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,6 @@ public enum ChatMessageMerge: Int32 {
|
|||||||
|
|
||||||
public protocol ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
public protocol ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
|
||||||
func updateSelectionState(animated: Bool)
|
func updateSelectionState(animated: Bool)
|
||||||
func updateSublayerTransformOffset(layer: CALayer, offset: CGPoint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public protocol ChatMessageItem: ListViewItem {
|
public protocol ChatMessageItem: ListViewItem {
|
||||||
|
@ -436,7 +436,7 @@ private let avatarFont = avatarPlaceholderFont(size: 16.0)
|
|||||||
|
|
||||||
private let maxVideoLoopCount = 3
|
private let maxVideoLoopCount = 3
|
||||||
|
|
||||||
public final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode {
|
public final class ChatMessageAvatarHeaderNodeImpl: ListViewItemHeaderNode, ChatMessageAvatarHeaderNode {
|
||||||
private let context: AccountContext
|
private let context: AccountContext
|
||||||
private var presentationData: ChatPresentationData
|
private var presentationData: ChatPresentationData
|
||||||
private let controllerInteraction: ChatControllerInteraction
|
private let controllerInteraction: ChatControllerInteraction
|
||||||
|
@ -215,6 +215,9 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
case .standalone:
|
case .standalone:
|
||||||
let serviceColor = serviceMessageColorComponents(theme: arguments.presentationData.theme.theme, wallpaper: arguments.presentationData.theme.wallpaper)
|
let serviceColor = serviceMessageColorComponents(theme: arguments.presentationData.theme.theme, wallpaper: arguments.presentationData.theme.wallpaper)
|
||||||
titleColor = serviceColor.primaryText
|
titleColor = serviceColor.primaryText
|
||||||
|
if dashSecondaryColor != nil {
|
||||||
|
secondaryColor = .clear
|
||||||
|
}
|
||||||
|
|
||||||
mainColor = serviceMessageColorComponents(chatTheme: arguments.presentationData.theme.theme.chat, wallpaper: arguments.presentationData.theme.wallpaper).primaryText
|
mainColor = serviceMessageColorComponents(chatTheme: arguments.presentationData.theme.theme.chat, wallpaper: arguments.presentationData.theme.wallpaper).primaryText
|
||||||
dustColor = titleColor
|
dustColor = titleColor
|
||||||
@ -457,7 +460,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
imageDimensions = representation.dimensions.cgSize
|
imageDimensions = representation.dimensions.cgSize
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
} else if let file = media as? TelegramMediaFile, file.isVideo && !file.isVideoSticker {
|
} else if let file = media as? TelegramMediaFile, !file.isVideoSticker {
|
||||||
updatedMediaReference = .message(message: MessageReference(message), media: file)
|
updatedMediaReference = .message(message: MessageReference(message), media: file)
|
||||||
|
|
||||||
if let dimensions = file.dimensions {
|
if let dimensions = file.dimensions {
|
||||||
@ -527,14 +530,12 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
var textCutoutWidth: CGFloat = 0.0
|
var textCutoutWidth: CGFloat = 0.0
|
||||||
if arguments.quote != nil || arguments.replyForward?.quote != nil {
|
if arguments.quote != nil || arguments.replyForward?.quote != nil {
|
||||||
additionalTitleWidth += 10.0
|
additionalTitleWidth += 10.0
|
||||||
if case .bubble = arguments.type {
|
maxTitleNumberOfLines = 2
|
||||||
maxTitleNumberOfLines = 2
|
maxTextNumberOfLines = 5
|
||||||
maxTextNumberOfLines = 5
|
if imageTextInset != 0.0 {
|
||||||
if imageTextInset != 0.0 {
|
adjustedConstrainedTextSize.width += imageTextInset
|
||||||
adjustedConstrainedTextSize.width += imageTextInset
|
textCutout = TextNodeCutout(topLeft: CGSize(width: imageTextInset + 6.0, height: 10.0))
|
||||||
textCutout = TextNodeCutout(topLeft: CGSize(width: imageTextInset + 6.0, height: 10.0))
|
textCutoutWidth = imageTextInset + 6.0
|
||||||
textCutoutWidth = imageTextInset + 6.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,10 +724,7 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
node.contentNode.view.insertSubview(node.backgroundView, at: 0)
|
node.contentNode.view.insertSubview(node.backgroundView, at: 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: realSize.width, height: realSize.height + 2.0))
|
let backgroundFrame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: realSize.width, height: realSize.height))
|
||||||
if case .standalone = arguments.type {
|
|
||||||
backgroundFrame.size.height -= 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
node.backgroundView.frame = backgroundFrame
|
node.backgroundView.frame = backgroundFrame
|
||||||
|
|
||||||
@ -749,30 +747,6 @@ public class ChatMessageReplyInfoNode: ASDisplayNode {
|
|||||||
animation: animation
|
animation: animation
|
||||||
)
|
)
|
||||||
|
|
||||||
let _ = secondaryColor
|
|
||||||
/*if let secondaryColor {
|
|
||||||
let lineDashView: UIImageView
|
|
||||||
if let current = node.lineDashView {
|
|
||||||
lineDashView = current
|
|
||||||
} else {
|
|
||||||
lineDashView = UIImageView(image: PresentationResourcesChat.chatReplyLineDashTemplateImage(arguments.presentationData.theme.theme, incoming: isIncoming))
|
|
||||||
lineDashView.clipsToBounds = true
|
|
||||||
node.lineDashView = lineDashView
|
|
||||||
node.contentNode.view.addSubview(lineDashView)
|
|
||||||
}
|
|
||||||
lineDashView.tintColor = secondaryColor
|
|
||||||
lineDashView.frame = CGRect(origin: .zero, size: CGSize(width: 12.0, height: backgroundFrame.height))
|
|
||||||
lineDashView.layer.cornerRadius = 6.0
|
|
||||||
if #available(iOS 13.0, *) {
|
|
||||||
lineDashView.layer.cornerCurve = .continuous
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let lineDashView = node.lineDashView {
|
|
||||||
node.lineDashView = nil
|
|
||||||
lineDashView.removeFromSuperview()
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
if arguments.quote != nil || arguments.replyForward?.quote != nil {
|
if arguments.quote != nil || arguments.replyForward?.quote != nil {
|
||||||
let quoteIconView: UIImageView
|
let quoteIconView: UIImageView
|
||||||
if let current = node.quoteIconView {
|
if let current = node.quoteIconView {
|
||||||
|
@ -1068,8 +1068,10 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var replyBackgroundFrame: CGRect?
|
||||||
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
if let (replyInfoSize, replyInfoApply) = replyInfoApply {
|
||||||
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize)
|
let replyInfoFrame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 11.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 9.0)), y: headersOffset + 8.0 + messageInfoSize.height), size: replyInfoSize)
|
||||||
|
replyBackgroundFrame = replyInfoFrame
|
||||||
|
|
||||||
let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation)
|
let replyInfoNode = replyInfoApply(replyInfoFrame.size, synchronousLoads, animation)
|
||||||
if strongSelf.replyInfoNode == nil {
|
if strongSelf.replyInfoNode == nil {
|
||||||
@ -1084,8 +1086,8 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
strongSelf.replyInfoNode = nil
|
strongSelf.replyInfoNode = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if let replyBackgroundNode = strongSelf.replyBackgroundNode {
|
if let replyBackgroundNode = strongSelf.replyBackgroundNode, let replyBackgroundFrame {
|
||||||
replyBackgroundNode.frame = CGRect(origin: CGPoint(x: (!incoming ? (params.leftInset + layoutConstants.bubble.edgeInset + 10.0) : (params.width - params.rightInset - messageInfoSize.width - layoutConstants.bubble.edgeInset - 10.0)) - 4.0, y: headersOffset + 6.0), size: CGSize(width: messageInfoSize.width + 8.0, height: messageInfoSize.height + 5.0))
|
replyBackgroundNode.frame = replyBackgroundFrame
|
||||||
|
|
||||||
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
let cornerRadius = replyBackgroundNode.frame.height <= 22.0 ? replyBackgroundNode.frame.height / 2.0 : 8.0
|
||||||
replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate)
|
replyBackgroundNode.update(size: replyBackgroundNode.bounds.size, cornerRadius: cornerRadius, transition: .immediate)
|
||||||
@ -1341,6 +1343,10 @@ public class ChatMessageStickerItemNode: ChatMessageItemView {
|
|||||||
return .optionalAction({
|
return .optionalAction({
|
||||||
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
item.controllerInteraction.navigateToStory(item.message, attribute.storyId)
|
||||||
})
|
})
|
||||||
|
} else if let attribute = attribute as? QuotedReplyMessageAttribute {
|
||||||
|
return .optionalAction({
|
||||||
|
item.controllerInteraction.attemptedNavigationToPrivateQuote(attribute.peerId.flatMap { item.message.peers[$0] })
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1108,13 +1108,18 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
|
|||||||
let enableCopy = !item.associatedData.isCopyProtectionEnabled && !item.message.isCopyProtected()
|
let enableCopy = !item.associatedData.isCopyProtectionEnabled && !item.message.isCopyProtected()
|
||||||
textSelectionNode.enableCopy = enableCopy
|
textSelectionNode.enableCopy = enableCopy
|
||||||
|
|
||||||
let enableQuote = true
|
var enableQuote = !item.message.text.isEmpty
|
||||||
var enableOtherActions = true
|
var enableOtherActions = true
|
||||||
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info) = subject, case .reply = info {
|
if let subject = item.associatedData.subject, case let .messageOptions(_, _, info) = subject, case .reply = info {
|
||||||
enableOtherActions = false
|
enableOtherActions = false
|
||||||
} else if item.controllerInteraction.canSetupReply(item.message) == .reply {
|
} else if item.controllerInteraction.canSetupReply(item.message) == .reply {
|
||||||
enableOtherActions = false
|
enableOtherActions = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !item.controllerInteraction.canSendMessages() && !enableCopy {
|
||||||
|
enableQuote = false
|
||||||
|
}
|
||||||
|
|
||||||
textSelectionNode.enableQuote = enableQuote
|
textSelectionNode.enableQuote = enableQuote
|
||||||
textSelectionNode.enableTranslate = enableOtherActions
|
textSelectionNode.enableTranslate = enableOtherActions
|
||||||
textSelectionNode.enableShare = enableOtherActions
|
textSelectionNode.enableShare = enableOtherActions
|
||||||
|
@ -519,6 +519,8 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, setupReply: { _ in
|
}, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
|
}, canSendMessages: {
|
||||||
|
return false
|
||||||
}, navigateToFirstDateMessage: { _, _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
@ -571,6 +573,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
|
|||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
}, scrollToMessageId: { _ in
|
}, scrollToMessageId: { _ in
|
||||||
}, navigateToStory: { _, _ in
|
}, navigateToStory: { _, _ in
|
||||||
|
}, attemptedNavigationToPrivateQuote: { _ in
|
||||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings,
|
||||||
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: self.backgroundNode))
|
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: self.backgroundNode))
|
||||||
self.controllerInteraction = controllerInteraction
|
self.controllerInteraction = controllerInteraction
|
||||||
|
@ -155,6 +155,7 @@ public final class ChatControllerInteraction {
|
|||||||
public let openSearch: () -> Void
|
public let openSearch: () -> Void
|
||||||
public let setupReply: (MessageId) -> Void
|
public let setupReply: (MessageId) -> Void
|
||||||
public let canSetupReply: (Message) -> ChatControllerInteractionSwipeAction
|
public let canSetupReply: (Message) -> ChatControllerInteractionSwipeAction
|
||||||
|
public let canSendMessages: () -> Bool
|
||||||
public let navigateToFirstDateMessage: (Int32, Bool) -> Void
|
public let navigateToFirstDateMessage: (Int32, Bool) -> Void
|
||||||
public let requestRedeliveryOfFailedMessages: (MessageId) -> Void
|
public let requestRedeliveryOfFailedMessages: (MessageId) -> Void
|
||||||
public let addContact: (String) -> Void
|
public let addContact: (String) -> Void
|
||||||
@ -203,6 +204,7 @@ public final class ChatControllerInteraction {
|
|||||||
public let dismissTextInput: () -> Void
|
public let dismissTextInput: () -> Void
|
||||||
public let scrollToMessageId: (MessageIndex) -> Void
|
public let scrollToMessageId: (MessageIndex) -> Void
|
||||||
public let navigateToStory: (Message, StoryId) -> Void
|
public let navigateToStory: (Message, StoryId) -> Void
|
||||||
|
public let attemptedNavigationToPrivateQuote: (Peer?) -> Void
|
||||||
|
|
||||||
public var canPlayMedia: Bool = false
|
public var canPlayMedia: Bool = false
|
||||||
public var hiddenMedia: [MessageId: [Media]] = [:]
|
public var hiddenMedia: [MessageId: [Media]] = [:]
|
||||||
@ -270,6 +272,7 @@ public final class ChatControllerInteraction {
|
|||||||
openSearch: @escaping () -> Void,
|
openSearch: @escaping () -> Void,
|
||||||
setupReply: @escaping (MessageId) -> Void,
|
setupReply: @escaping (MessageId) -> Void,
|
||||||
canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction,
|
canSetupReply: @escaping (Message) -> ChatControllerInteractionSwipeAction,
|
||||||
|
canSendMessages: @escaping () -> Bool,
|
||||||
navigateToFirstDateMessage: @escaping(Int32, Bool) ->Void,
|
navigateToFirstDateMessage: @escaping(Int32, Bool) ->Void,
|
||||||
requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void,
|
requestRedeliveryOfFailedMessages: @escaping (MessageId) -> Void,
|
||||||
addContact: @escaping (String) -> Void,
|
addContact: @escaping (String) -> Void,
|
||||||
@ -317,6 +320,7 @@ public final class ChatControllerInteraction {
|
|||||||
dismissTextInput: @escaping () -> Void,
|
dismissTextInput: @escaping () -> Void,
|
||||||
scrollToMessageId: @escaping (MessageIndex) -> Void,
|
scrollToMessageId: @escaping (MessageIndex) -> Void,
|
||||||
navigateToStory: @escaping (Message, StoryId) -> Void,
|
navigateToStory: @escaping (Message, StoryId) -> Void,
|
||||||
|
attemptedNavigationToPrivateQuote: @escaping (Peer?) -> Void,
|
||||||
automaticMediaDownloadSettings: MediaAutoDownloadSettings,
|
automaticMediaDownloadSettings: MediaAutoDownloadSettings,
|
||||||
pollActionState: ChatInterfacePollActionState,
|
pollActionState: ChatInterfacePollActionState,
|
||||||
stickerSettings: ChatInterfaceStickerSettings,
|
stickerSettings: ChatInterfaceStickerSettings,
|
||||||
@ -367,6 +371,7 @@ public final class ChatControllerInteraction {
|
|||||||
self.openSearch = openSearch
|
self.openSearch = openSearch
|
||||||
self.setupReply = setupReply
|
self.setupReply = setupReply
|
||||||
self.canSetupReply = canSetupReply
|
self.canSetupReply = canSetupReply
|
||||||
|
self.canSendMessages = canSendMessages
|
||||||
self.navigateToFirstDateMessage = navigateToFirstDateMessage
|
self.navigateToFirstDateMessage = navigateToFirstDateMessage
|
||||||
self.requestRedeliveryOfFailedMessages = requestRedeliveryOfFailedMessages
|
self.requestRedeliveryOfFailedMessages = requestRedeliveryOfFailedMessages
|
||||||
self.addContact = addContact
|
self.addContact = addContact
|
||||||
@ -414,6 +419,7 @@ public final class ChatControllerInteraction {
|
|||||||
self.dismissTextInput = dismissTextInput
|
self.dismissTextInput = dismissTextInput
|
||||||
self.scrollToMessageId = scrollToMessageId
|
self.scrollToMessageId = scrollToMessageId
|
||||||
self.navigateToStory = navigateToStory
|
self.navigateToStory = navigateToStory
|
||||||
|
self.attemptedNavigationToPrivateQuote = attemptedNavigationToPrivateQuote
|
||||||
|
|
||||||
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
|
self.automaticMediaDownloadSettings = automaticMediaDownloadSettings
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ import ChatMessageTextBubbleContentNode
|
|||||||
import TextFormat
|
import TextFormat
|
||||||
import ChatMessageItemView
|
import ChatMessageItemView
|
||||||
import ChatMessageBubbleItemNode
|
import ChatMessageBubbleItemNode
|
||||||
|
import TelegramNotices
|
||||||
|
|
||||||
private enum OptionsId: Hashable {
|
private enum OptionsId: Hashable {
|
||||||
case reply
|
case reply
|
||||||
@ -286,12 +287,16 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||||||
return .complete()
|
return .complete()
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = selfController.context.account.postbox.messagesAtIds([replySubject.messageId])
|
let items = combineLatest(queue: .mainQueue(),
|
||||||
|
selfController.context.account.postbox.messagesAtIds([replySubject.messageId]),
|
||||||
|
ApplicationSpecificNotice.getReplyQuoteTextSelectionTips(accountManager: selfController.context.sharedContext.accountManager)
|
||||||
|
)
|
||||||
|> deliverOnMainQueue
|
|> deliverOnMainQueue
|
||||||
|> map { [weak selfController, weak chatController] messages -> [ContextMenuItem] in
|
|> map { [weak selfController, weak chatController] messages, quoteTextSelectionTips -> ContextController.Items in
|
||||||
guard let selfController, let chatController else {
|
guard let selfController, let chatController else {
|
||||||
return []
|
return ContextController.Items(content: .list([]))
|
||||||
}
|
}
|
||||||
|
|
||||||
var items: [ContextMenuItem] = []
|
var items: [ContextMenuItem] = []
|
||||||
|
|
||||||
if replySubject.quote != nil {
|
if replySubject.quote != nil {
|
||||||
@ -398,18 +403,21 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:localize
|
if selfController.presentationInterfaceState.copyProtectionEnabled || messages.first?.isCopyProtected() == true {
|
||||||
items.append(.action(ContextMenuActionItem(text: "Reply in Another Chat", icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Replace"), color: theme.contextMenu.primaryColor) }, action: { [weak selfController] c, f in
|
} else {
|
||||||
f(.default)
|
//TODO:localize
|
||||||
|
items.append(.action(ContextMenuActionItem(text: "Reply in Another Chat", icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Replace"), color: theme.contextMenu.primaryColor) }, action: { [weak selfController] c, f in
|
||||||
guard let selfController else {
|
f(.default)
|
||||||
return
|
|
||||||
}
|
guard let selfController else {
|
||||||
guard let replySubject = selfController.presentationInterfaceState.interfaceState.replyMessageSubject else {
|
return
|
||||||
return
|
}
|
||||||
}
|
guard let replySubject = selfController.presentationInterfaceState.interfaceState.replyMessageSubject else {
|
||||||
moveReplyMessageToAnotherChat(selfController: selfController, replySubject: replySubject)
|
return
|
||||||
})))
|
}
|
||||||
|
moveReplyMessageToAnotherChat(selfController: selfController, replySubject: replySubject)
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
|
||||||
items.append(.separator)
|
items.append(.separator)
|
||||||
|
|
||||||
@ -441,14 +449,17 @@ private func generateChatReplyOptionItems(selfController: ChatControllerImpl, ch
|
|||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
|
||||||
return items
|
var tip: ContextController.Tip?
|
||||||
|
if quoteTextSelectionTips <= 3, let message = messages.first, !message.text.isEmpty {
|
||||||
|
tip = .quoteSelection
|
||||||
|
}
|
||||||
|
|
||||||
|
return ContextController.Items(content: .list(items), tip: tip)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tip: ContextController.Tip?
|
let _ = ApplicationSpecificNotice.incrementReplyQuoteTextSelectionTips(accountManager: selfController.context.sharedContext.accountManager).startStandalone()
|
||||||
if "".isEmpty {
|
|
||||||
tip = .quoteSelection
|
return items
|
||||||
}
|
|
||||||
return items |> map { ContextController.Items(content: .list($0), tip: tip) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func chatReplyOptions(selfController: ChatControllerImpl, sourceNode: ASDisplayNode, getContextController: @escaping () -> ContextController?, selectionState: Promise<ChatControllerSubject.MessageOptionsInfo.SelectionState>) -> ContextController.Source? {
|
private func chatReplyOptions(selfController: ChatControllerImpl, sourceNode: ASDisplayNode, getContextController: @escaping () -> ContextController?, selectionState: Promise<ChatControllerSubject.MessageOptionsInfo.SelectionState>) -> ContextController.Source? {
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
import Foundation
|
||||||
|
import UIKit
|
||||||
|
import AsyncDisplayKit
|
||||||
|
import ContextUI
|
||||||
|
import Display
|
||||||
|
import SwiftSignalKit
|
||||||
|
import Postbox
|
||||||
|
import TelegramCore
|
||||||
|
import TelegramNotices
|
||||||
|
import ChatSendMessageActionUI
|
||||||
|
import AccountContext
|
||||||
|
|
||||||
|
func chatMessageDisplaySendMessageOptions(selfController: ChatControllerImpl, node: ASDisplayNode, gesture: ContextGesture) {
|
||||||
|
guard let peerId = selfController.chatLocation.peerId, let textInputView = selfController.chatDisplayNode.textInputView(), let layout = selfController.validLayout else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let previousSupportedOrientations = selfController.supportedOrientations
|
||||||
|
if layout.size.width > layout.size.height {
|
||||||
|
selfController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .landscape)
|
||||||
|
} else {
|
||||||
|
selfController.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = ApplicationSpecificNotice.incrementChatMessageOptionsTip(accountManager: selfController.context.sharedContext.accountManager, count: 4).startStandalone()
|
||||||
|
|
||||||
|
var hasEntityKeyboard = false
|
||||||
|
if case .media = selfController.presentationInterfaceState.inputMode {
|
||||||
|
hasEntityKeyboard = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = (selfController.context.account.viewTracker.peerView(peerId)
|
||||||
|
|> take(1)
|
||||||
|
|> deliverOnMainQueue).startStandalone(next: { [weak selfController] peerView in
|
||||||
|
guard let selfController, let peer = peerViewMainPeer(peerView) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var sendWhenOnlineAvailable = false
|
||||||
|
if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case let .present(until) = presence.status {
|
||||||
|
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
||||||
|
if currentTime > until {
|
||||||
|
sendWhenOnlineAvailable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 {
|
||||||
|
sendWhenOnlineAvailable = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if sendWhenOnlineAvailable {
|
||||||
|
let _ = ApplicationSpecificNotice.incrementSendWhenOnlineTip(accountManager: selfController.context.sharedContext.accountManager, count: 4).startStandalone()
|
||||||
|
}
|
||||||
|
|
||||||
|
let controller = ChatSendMessageActionSheetController(context: selfController.context, updatedPresentationData: selfController.updatedPresentationData, peerId: selfController.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: selfController.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputView: textInputView, canSendWhenOnline: sendWhenOnlineAvailable, completion: { [weak selfController] in
|
||||||
|
guard let selfController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selfController.supportedOrientations = previousSupportedOrientations
|
||||||
|
}, sendMessage: { [weak selfController] mode in
|
||||||
|
guard let selfController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch mode {
|
||||||
|
case .generic:
|
||||||
|
selfController.controllerInteraction?.sendCurrentMessage(false)
|
||||||
|
case .silently:
|
||||||
|
selfController.controllerInteraction?.sendCurrentMessage(true)
|
||||||
|
case .whenOnline:
|
||||||
|
selfController.chatDisplayNode.sendCurrentMessage(scheduleTime: scheduleWhenOnlineTimestamp) { [weak selfController] in
|
||||||
|
guard let selfController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selfController.updateChatPresentationInterfaceState(animated: true, interactive: false, saveInterfaceState: selfController.presentationInterfaceState.subject != .scheduledMessages, {
|
||||||
|
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
||||||
|
})
|
||||||
|
selfController.openScheduledMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, schedule: { [weak selfController] in
|
||||||
|
guard let selfController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
selfController.controllerInteraction?.scheduleCurrentMessage()
|
||||||
|
})
|
||||||
|
controller.emojiViewProvider = selfController.chatDisplayNode.textInputPanelNode?.emojiViewProvider
|
||||||
|
selfController.sendMessageActionsController = controller
|
||||||
|
if layout.isNonExclusive {
|
||||||
|
selfController.present(controller, in: .window(.root))
|
||||||
|
} else {
|
||||||
|
selfController.presentInGlobalOverlay(controller, with: nil)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -3448,7 +3448,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
})
|
})
|
||||||
}, openSearch: {
|
}, openSearch: {
|
||||||
}, setupReply: { [weak self] messageId in
|
}, setupReply: { [weak self] messageId in
|
||||||
self?.interfaceInteraction?.setupReplyMessage(messageId, { _, _ in })
|
self?.interfaceInteraction?.setupReplyMessage(messageId, { _, f in f() })
|
||||||
}, canSetupReply: { [weak self] message in
|
}, canSetupReply: { [weak self] message in
|
||||||
if !message.flags.contains(.Incoming) {
|
if !message.flags.contains(.Incoming) {
|
||||||
if !message.flags.intersection([.Failed, .Sending, .Unsent]).isEmpty {
|
if !message.flags.intersection([.Failed, .Sending, .Unsent]).isEmpty {
|
||||||
@ -3471,6 +3471,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return .none
|
return .none
|
||||||
|
}, canSendMessages: { [weak self] in
|
||||||
|
guard let self else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return canSendMessagesToChat(self.presentationInterfaceState)
|
||||||
}, navigateToFirstDateMessage: { [weak self] timestamp, alreadyThere in
|
}, navigateToFirstDateMessage: { [weak self] timestamp, alreadyThere in
|
||||||
guard let strongSelf = self else {
|
guard let strongSelf = self else {
|
||||||
return
|
return
|
||||||
@ -5011,6 +5016,24 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
)
|
)
|
||||||
self.push(storyContainerScreen)
|
self.push(storyContainerScreen)
|
||||||
})
|
})
|
||||||
|
}, attemptedNavigationToPrivateQuote: { [weak self] peer in
|
||||||
|
guard let self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//TODO:localize
|
||||||
|
let text: String
|
||||||
|
if let peer = peer as? TelegramChannel {
|
||||||
|
if case .broadcast = peer.info {
|
||||||
|
text = "This quote is from a private channel"
|
||||||
|
} else {
|
||||||
|
text = "This quote is from a private group"
|
||||||
|
}
|
||||||
|
} else if peer is TelegramGroup {
|
||||||
|
text = "This quote is from a private group"
|
||||||
|
} else {
|
||||||
|
text = "This quote is from a private chat"
|
||||||
|
}
|
||||||
|
self.controllerInteraction?.displayUndo(.info(title: nil, text: text, timeout: nil))
|
||||||
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: self.stickerSettings, presentationContext: ChatPresentationContext(context: context, backgroundNode: self.chatBackgroundNode))
|
}, automaticMediaDownloadSettings: self.automaticMediaDownloadSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: self.stickerSettings, presentationContext: ChatPresentationContext(context: context, backgroundNode: self.chatBackgroundNode))
|
||||||
controllerInteraction.enableFullTranslucency = context.sharedContext.energyUsageSettings.fullTranslucency
|
controllerInteraction.enableFullTranslucency = context.sharedContext.energyUsageSettings.fullTranslucency
|
||||||
|
|
||||||
@ -10547,78 +10570,10 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
|
|||||||
|
|
||||||
strongSelf.window?.presentInGlobalOverlay(slowmodeTooltipController)
|
strongSelf.window?.presentInGlobalOverlay(slowmodeTooltipController)
|
||||||
}, displaySendMessageOptions: { [weak self] node, gesture in
|
}, displaySendMessageOptions: { [weak self] node, gesture in
|
||||||
if let strongSelf = self, let peerId = strongSelf.chatLocation.peerId, let textInputView = strongSelf.chatDisplayNode.textInputView(), let layout = strongSelf.validLayout {
|
guard let self else {
|
||||||
let previousSupportedOrientations = strongSelf.supportedOrientations
|
return
|
||||||
if layout.size.width > layout.size.height {
|
|
||||||
strongSelf.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .landscape)
|
|
||||||
} else {
|
|
||||||
strongSelf.supportedOrientations = ViewControllerSupportedOrientations(regularSize: .all, compactSize: .portrait)
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = ApplicationSpecificNotice.incrementChatMessageOptionsTip(accountManager: strongSelf.context.sharedContext.accountManager, count: 4).startStandalone()
|
|
||||||
|
|
||||||
var hasEntityKeyboard = false
|
|
||||||
if case .media = strongSelf.presentationInterfaceState.inputMode {
|
|
||||||
hasEntityKeyboard = true
|
|
||||||
}
|
|
||||||
|
|
||||||
let _ = (strongSelf.context.account.viewTracker.peerView(peerId)
|
|
||||||
|> take(1)
|
|
||||||
|> deliverOnMainQueue).startStandalone(next: { [weak self] peerView in
|
|
||||||
guard let strongSelf = self, let peer = peerViewMainPeer(peerView) else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var sendWhenOnlineAvailable = false
|
|
||||||
if let presence = peerView.peerPresences[peer.id] as? TelegramUserPresence, case let .present(until) = presence.status {
|
|
||||||
let currentTime = Int32(CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970)
|
|
||||||
if currentTime > until {
|
|
||||||
sendWhenOnlineAvailable = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if peer.id.namespace == Namespaces.Peer.CloudUser && peer.id.id._internalGetInt64Value() == 777000 {
|
|
||||||
sendWhenOnlineAvailable = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if sendWhenOnlineAvailable {
|
|
||||||
let _ = ApplicationSpecificNotice.incrementSendWhenOnlineTip(accountManager: strongSelf.context.sharedContext.accountManager, count: 4).startStandalone()
|
|
||||||
}
|
|
||||||
|
|
||||||
let controller = ChatSendMessageActionSheetController(context: strongSelf.context, updatedPresentationData: strongSelf.updatedPresentationData, peerId: strongSelf.presentationInterfaceState.chatLocation.peerId, forwardMessageIds: strongSelf.presentationInterfaceState.interfaceState.forwardMessageIds, hasEntityKeyboard: hasEntityKeyboard, gesture: gesture, sourceSendButton: node, textInputView: textInputView, canSendWhenOnline: sendWhenOnlineAvailable, completion: { [weak self] in
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.supportedOrientations = previousSupportedOrientations
|
|
||||||
}
|
|
||||||
}, sendMessage: { [weak self] mode in
|
|
||||||
if let strongSelf = self {
|
|
||||||
switch mode {
|
|
||||||
case .generic:
|
|
||||||
strongSelf.controllerInteraction?.sendCurrentMessage(false)
|
|
||||||
case .silently:
|
|
||||||
strongSelf.controllerInteraction?.sendCurrentMessage(true)
|
|
||||||
case .whenOnline:
|
|
||||||
strongSelf.chatDisplayNode.sendCurrentMessage(scheduleTime: scheduleWhenOnlineTimestamp) { [weak self] in
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, saveInterfaceState: strongSelf.presentationInterfaceState.subject != .scheduledMessages, {
|
|
||||||
$0.updatedInterfaceState { $0.withUpdatedReplyMessageSubject(nil).withUpdatedForwardMessageIds(nil).withUpdatedForwardOptionsState(nil).withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) }
|
|
||||||
})
|
|
||||||
strongSelf.openScheduledMessages()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, schedule: { [weak self] in
|
|
||||||
if let strongSelf = self {
|
|
||||||
strongSelf.controllerInteraction?.scheduleCurrentMessage()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
controller.emojiViewProvider = strongSelf.chatDisplayNode.textInputPanelNode?.emojiViewProvider
|
|
||||||
strongSelf.sendMessageActionsController = controller
|
|
||||||
if layout.isNonExclusive {
|
|
||||||
strongSelf.present(controller, in: .window(.root))
|
|
||||||
} else {
|
|
||||||
strongSelf.presentInGlobalOverlay(controller, with: nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
chatMessageDisplaySendMessageOptions(selfController: self, node: node, gesture: gesture)
|
||||||
}, openScheduledMessages: { [weak self] in
|
}, openScheduledMessages: { [weak self] in
|
||||||
if let strongSelf = self {
|
if let strongSelf = self {
|
||||||
strongSelf.openScheduledMessages()
|
strongSelf.openScheduledMessages()
|
||||||
|
@ -649,6 +649,10 @@ func contextMenuForChatPresentationInterfaceState(chatPresentationInterfaceState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !canSendMessagesToChat(chatPresentationInterfaceState) && (chatPresentationInterfaceState.copyProtectionEnabled || message.isCopyProtected()) {
|
||||||
|
canReply = false
|
||||||
|
}
|
||||||
|
|
||||||
for media in messages[0].media {
|
for media in messages[0].media {
|
||||||
if let story = media as? TelegramMediaStory {
|
if let story = media as? TelegramMediaStory {
|
||||||
if let story = message.associatedStories[story.storyId], story.data.isEmpty {
|
if let story = message.associatedStories[story.storyId], story.data.isEmpty {
|
||||||
|
@ -123,6 +123,8 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}, setupReply: { _ in
|
}, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
|
}, canSendMessages: {
|
||||||
|
return false
|
||||||
}, navigateToFirstDateMessage: { _, _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
@ -172,6 +174,7 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, UIGestu
|
|||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
}, scrollToMessageId: { _ in
|
}, scrollToMessageId: { _ in
|
||||||
}, navigateToStory: { _, _ in
|
}, navigateToStory: { _, _ in
|
||||||
|
}, attemptedNavigationToPrivateQuote: { _ in
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil))
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings, pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil))
|
||||||
|
|
||||||
self.dimNode = ASDisplayNode()
|
self.dimNode = ASDisplayNode()
|
||||||
|
@ -2874,6 +2874,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}, setupReply: { _ in
|
}, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
|
}, canSendMessages: {
|
||||||
|
return false
|
||||||
}, navigateToFirstDateMessage: { _, _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
@ -2923,6 +2925,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
|
|||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
}, scrollToMessageId: { _ in
|
}, scrollToMessageId: { _ in
|
||||||
}, navigateToStory: { _, _ in
|
}, navigateToStory: { _, _ in
|
||||||
|
}, attemptedNavigationToPrivateQuote: { _ in
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil))
|
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: nil))
|
||||||
self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().startStrict(next: { [weak self] ids in
|
self.hiddenMediaDisposable = context.sharedContext.mediaManager.galleryHiddenMediaManager.hiddenIds().startStrict(next: { [weak self] ids in
|
||||||
|
@ -1512,6 +1512,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
}, presentGlobalOverlayController: { _, _ in }, callPeer: { _, _ in }, longTap: { _, _ in }, openCheckoutOrReceipt: { _ in }, openSearch: { }, setupReply: { _ in
|
||||||
}, canSetupReply: { _ in
|
}, canSetupReply: { _ in
|
||||||
return .none
|
return .none
|
||||||
|
}, canSendMessages: {
|
||||||
|
return false
|
||||||
}, navigateToFirstDateMessage: { _, _ in
|
}, navigateToFirstDateMessage: { _, _ in
|
||||||
}, requestRedeliveryOfFailedMessages: { _ in
|
}, requestRedeliveryOfFailedMessages: { _ in
|
||||||
}, addContact: { _ in
|
}, addContact: { _ in
|
||||||
@ -1561,6 +1563,7 @@ public final class SharedAccountContextImpl: SharedAccountContext {
|
|||||||
}, dismissTextInput: {
|
}, dismissTextInput: {
|
||||||
}, scrollToMessageId: { _ in
|
}, scrollToMessageId: { _ in
|
||||||
}, navigateToStory: { _, _ in
|
}, navigateToStory: { _, _ in
|
||||||
|
}, attemptedNavigationToPrivateQuote: { _ in
|
||||||
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
}, automaticMediaDownloadSettings: MediaAutoDownloadSettings.defaultSettings,
|
||||||
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: backgroundNode as? WallpaperBackgroundNode))
|
pollActionState: ChatInterfacePollActionState(), stickerSettings: ChatInterfaceStickerSettings(), presentationContext: ChatPresentationContext(context: context, backgroundNode: backgroundNode as? WallpaperBackgroundNode))
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user