Comment updates

This commit is contained in:
Ali
2020-09-09 22:37:40 +01:00
parent d5a7be3800
commit c17cedf494
14 changed files with 122 additions and 77 deletions

View File

@@ -8346,6 +8346,11 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.loadingMessage.set(false)
}
}))
} else {
if let navigationController = self.effectiveNavigationController {
self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(messageLocation.peerId), subject: messageLocation.messageId.flatMap { .message($0) }))
}
completion?()
}
}
} else {

View File

@@ -297,7 +297,7 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
let message = messages[0]
if Namespaces.Message.allScheduled.contains(message.id.namespace) {
if Namespaces.Message.allScheduled.contains(message.id.namespace) || message.id.peerId.isReplies {
canReply = false
canPin = false
} else if messages[0].flags.intersection([.Failed, .Unsent]).isEmpty {
@@ -758,7 +758,15 @@ func contextMenuForChatPresentationIntefaceState(chatPresentationInterfaceState:
UIPasteboard.general.string = link
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
if channel.addressName == nil {
var warnAboutPrivate = false
if case let .peer = chatPresentationInterfaceState.chatLocation {
if channel.addressName == nil {
warnAboutPrivate = true
}
}
if warnAboutPrivate {
controllerInteraction.presentGlobalOverlayController(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.Conversation_PrivateMessageLinkCopied, true)), nil)
} else {
controllerInteraction.presentGlobalOverlayController(OverlayStatusController(theme: presentationData.theme, type: .genericSuccess(presentationData.strings.GroupInfo_InviteLink_CopyAlert_Success, false)), nil)
@@ -1050,7 +1058,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
}
}
} else if let user = peer as? TelegramUser {
if !isScheduled && message.id.peerId.namespace != Namespaces.Peer.SecretChat && !message.containsSecretMedia && !isAction {
if !isScheduled && message.id.peerId.namespace != Namespaces.Peer.SecretChat && !message.containsSecretMedia && !isAction && !message.id.peerId.isReplies {
if !(message.flags.isSending || message.flags.contains(.Failed)) {
optionsMap[id]!.insert(.forward)
}
@@ -1073,7 +1081,7 @@ func chatAvailableMessageActionsImpl(postbox: Postbox, accountPeerId: PeerId, me
if canDeleteGlobally {
optionsMap[id]!.insert(.deleteGlobally)
}
if user.botInfo != nil {
if user.botInfo != nil && !user.id.isReplies {
optionsMap[id]!.insert(.report)
}
} else if let _ = peer as? TelegramSecretChat {

View File

@@ -27,6 +27,9 @@ 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 .replyThread = presentationInterfaceState.chatLocation {
return nil
}
if let currentButton = currentButton, currentButton.action == .clearHistory {
return currentButton
} else if let peer = presentationInterfaceState.renderedPeer?.peer {
@@ -64,6 +67,14 @@ func leftNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Cha
}
func rightNavigationButtonForChatInterfaceState(_ presentationInterfaceState: ChatPresentationInterfaceState, strings: PresentationStrings, currentButton: ChatNavigationButton?, target: Any?, selector: Selector?, chatInfoNavigationButton: ChatNavigationButton?) -> ChatNavigationButton? {
if let _ = presentationInterfaceState.interfaceState.selectionState {
if let currentButton = currentButton, currentButton.action == .cancelMessageSelection {
return currentButton
} else {
return ChatNavigationButton(action: .cancelMessageSelection, buttonItem: UIBarButtonItem(title: strings.Common_Cancel, style: .plain, target: target, action: selector))
}
}
if case .replyThread = presentationInterfaceState.chatLocation {
if case .search = currentButton?.action {
return currentButton
@@ -84,13 +95,6 @@ func rightNavigationButtonForChatInterfaceState(_ presentationInterfaceState: Ch
}
}
}
if let _ = presentationInterfaceState.interfaceState.selectionState {
if let currentButton = currentButton, currentButton.action == .cancelMessageSelection {
return currentButton
} else {
return ChatNavigationButton(action: .cancelMessageSelection, buttonItem: UIBarButtonItem(title: strings.Common_Cancel, style: .plain, target: target, action: selector))
}
}
if presentationInterfaceState.isScheduledMessages {
return chatInfoNavigationButton

View File

@@ -531,7 +531,7 @@ final class ChatMessageAttachedContentNode: ASDisplayNode {
var additionalImageBadgeContent: ChatMessageInteractiveMediaBadgeContent?
switch position {
case .linear(_, .None):
case .linear(_, .None), .linear(_, .Neighbour(true, _)):
let imageMode = !((refineContentImageLayout == nil && refineContentFileLayout == nil && contentInstantVideoSizeAndApply == nil) || preferMediaBeforeText)
statusInText = !imageMode

View File

@@ -29,8 +29,13 @@ enum InternalBubbleTapAction {
case openContextMenu(tapMessage: Message, selectAll: Bool, subFrame: CGRect)
}
private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(Message, AnyClass, ChatMessageEntryAttributes, Bool)] {
var result: [(Message, AnyClass, ChatMessageEntryAttributes, Bool)] = []
private struct BubbleItemAttributes {
var isAttachment: Bool
var neighborType: ChatMessageBubbleRelativePosition.NeighbourType
}
private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(Message, AnyClass, ChatMessageEntryAttributes, BubbleItemAttributes)] {
var result: [(Message, AnyClass, ChatMessageEntryAttributes, BubbleItemAttributes)] = []
var skipText = false
var messageWithCaptionToAdd: (Message, ChatMessageEntryAttributes)?
var isUnsupportedMedia = false
@@ -39,46 +44,46 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(
outer: for (message, itemAttributes) in item.content {
for attribute in message.attributes {
if let attribute = attribute as? RestrictedContentMessageAttribute, attribute.platformText(platform: "ios", contentSettings: item.context.currentContentSettings.with { $0 }) != nil {
result.append((message, ChatMessageRestrictedBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageRestrictedBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
break outer
}
}
inner: for media in message.media {
if let _ = media as? TelegramMediaImage {
result.append((message, ChatMessageMediaBubbleContentNode.self, itemAttributes, true))
result.append((message, ChatMessageMediaBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .media)))
} else if let file = media as? TelegramMediaFile {
let isVideo = file.isVideo || (file.isAnimated && file.dimensions != nil)
if isVideo {
result.append((message, ChatMessageMediaBubbleContentNode.self, itemAttributes, true))
result.append((message, ChatMessageMediaBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .media)))
} else {
result.append((message, ChatMessageFileBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageFileBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
}
} else if let action = media as? TelegramMediaAction {
isAction = true
if case .phoneCall = action.action {
result.append((message, ChatMessageCallBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageCallBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
} else {
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
}
} else if let _ = media as? TelegramMediaMap {
result.append((message, ChatMessageMapBubbleContentNode.self, itemAttributes, true))
result.append((message, ChatMessageMapBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .media)))
} else if let _ = media as? TelegramMediaGame {
skipText = true
result.append((message, ChatMessageGameBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageGameBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
break inner
} else if let _ = media as? TelegramMediaInvoice {
skipText = true
result.append((message, ChatMessageInvoiceBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageInvoiceBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
break inner
} else if let _ = media as? TelegramMediaContact {
result.append((message, ChatMessageContactBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageContactBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
} else if let _ = media as? TelegramMediaExpiredContent {
result.removeAll()
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageActionBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
return result
} else if let _ = media as? TelegramMediaPoll {
result.append((message, ChatMessagePollBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessagePollBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
} else if let _ = media as? TelegramMediaUnsupported {
isUnsupportedMedia = true
}
@@ -95,7 +100,7 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(
messageWithCaptionToAdd = (message, itemAttributes)
skipText = true
} else {
result.append((message, ChatMessageTextBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageTextBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
}
} else {
if case .group = item.content {
@@ -107,34 +112,34 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(
inner: for media in message.media {
if let webpage = media as? TelegramMediaWebpage {
if case .Loaded = webpage.content {
result.append((message, ChatMessageWebpageBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageWebpageBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
}
break inner
}
}
if isUnsupportedMedia {
result.append((message, ChatMessageUnsupportedBubbleContentNode.self, itemAttributes, false))
result.append((message, ChatMessageUnsupportedBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
}
}
if let (messageWithCaptionToAdd, itemAttributes) = messageWithCaptionToAdd {
result.append((messageWithCaptionToAdd, ChatMessageTextBubbleContentNode.self, itemAttributes, false))
result.append((messageWithCaptionToAdd, ChatMessageTextBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
}
if let additionalContent = item.additionalContent {
switch additionalContent {
case let .eventLogPreviousMessage(previousMessage):
result.append((previousMessage, ChatMessageEventLogPreviousMessageContentNode.self, ChatMessageEntryAttributes(), false))
result.append((previousMessage, ChatMessageEventLogPreviousMessageContentNode.self, ChatMessageEntryAttributes(), BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
case let .eventLogPreviousDescription(previousMessage):
result.append((previousMessage, ChatMessageEventLogPreviousDescriptionContentNode.self, ChatMessageEntryAttributes(), false))
result.append((previousMessage, ChatMessageEventLogPreviousDescriptionContentNode.self, ChatMessageEntryAttributes(), BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
case let .eventLogPreviousLink(previousMessage):
result.append((previousMessage, ChatMessageEventLogPreviousLinkContentNode.self, ChatMessageEntryAttributes(), false))
result.append((previousMessage, ChatMessageEventLogPreviousLinkContentNode.self, ChatMessageEntryAttributes(), BubbleItemAttributes(isAttachment: false, neighborType: .freeform)))
}
}
let firstMessage = item.content.firstMessage
if !isAction {
if !isAction && !Namespaces.Message.allScheduled.contains(firstMessage.id.namespace) {
var hasDiscussion = false
if let channel = firstMessage.peers[firstMessage.id.peerId] as? TelegramChannel, case let .broadcast(info) = channel.info, info.flags.contains(.hasDiscussionGroup) {
hasDiscussion = true
@@ -159,10 +164,10 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> [(
}
if canComment {
result.append((firstMessage, ChatMessageCommentFooterContentNode.self, ChatMessageEntryAttributes(), false))
result.append((firstMessage, ChatMessageCommentFooterContentNode.self, ChatMessageEntryAttributes(), BubbleItemAttributes(isAttachment: true, neighborType: .freeform)))
}
} else if firstMessage.id.peerId.isReplies {
result.append((firstMessage, ChatMessageCommentFooterContentNode.self, ChatMessageEntryAttributes(), false))
result.append((firstMessage, ChatMessageCommentFooterContentNode.self, ChatMessageEntryAttributes(), BubbleItemAttributes(isAttachment: true, neighborType: .freeform)))
}
}
@@ -981,22 +986,22 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
let maximumContentWidth = floor(tmpWidth - layoutConstants.bubble.edgeInset - layoutConstants.bubble.edgeInset - layoutConstants.bubble.contentInsets.left - layoutConstants.bubble.contentInsets.right - avatarInset)
var contentPropertiesAndPrepareLayouts: [(Message, Bool, ChatMessageEntryAttributes, Bool, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))))] = []
var contentPropertiesAndPrepareLayouts: [(Message, Bool, ChatMessageEntryAttributes, BubbleItemAttributes, (_ item: ChatMessageBubbleContentItem, _ layoutConstants: ChatMessageItemLayoutConstants, _ preparePosition: ChatMessageBubblePreparePosition, _ messageSelection: Bool?, _ constrainedSize: CGSize) -> (ChatMessageBubbleContentProperties, CGSize?, CGFloat, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void))))] = []
var addedContentNodes: [(Message, ChatMessageBubbleContentNode)]?
let contentNodeMessagesAndClasses = contentNodeMessagesAndClassesForItem(item)
for (contentNodeMessage, contentNodeClass, attributes, isAttachment) in contentNodeMessagesAndClasses {
for (contentNodeMessage, contentNodeClass, attributes, bubbleAttributes) in contentNodeMessagesAndClasses {
var found = false
for (currentMessage, currentClass, supportsMosaic, currentLayout) in currentContentClassesPropertiesAndLayouts {
if currentClass == contentNodeClass && currentMessage.stableId == contentNodeMessage.stableId {
contentPropertiesAndPrepareLayouts.append((contentNodeMessage, supportsMosaic, attributes, isAttachment, currentLayout))
contentPropertiesAndPrepareLayouts.append((contentNodeMessage, supportsMosaic, attributes, bubbleAttributes, currentLayout))
found = true
break
}
}
if !found {
let contentNode = (contentNodeClass as! ChatMessageBubbleContentNode.Type).init()
contentPropertiesAndPrepareLayouts.append((contentNodeMessage, contentNode.supportsMosaic, attributes, isAttachment, contentNode.asyncLayoutContent()))
contentPropertiesAndPrepareLayouts.append((contentNodeMessage, contentNode.supportsMosaic, attributes, bubbleAttributes, contentNode.asyncLayoutContent()))
if addedContentNodes == nil {
addedContentNodes = []
}
@@ -1052,7 +1057,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
inlineBotNameString = nil
}
var contentPropertiesAndLayouts: [(CGSize?, ChatMessageBubbleContentProperties, ChatMessageBubblePreparePosition, Bool, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void)))] = []
var contentPropertiesAndLayouts: [(CGSize?, ChatMessageBubbleContentProperties, ChatMessageBubblePreparePosition, BubbleItemAttributes, (CGSize, ChatMessageBubbleContentPosition) -> (CGFloat, (CGFloat) -> (CGSize, (ListViewItemUpdateAnimation, Bool) -> Void)))] = []
let topNodeMergeStatus: ChatMessageBubbleMergeStatus = mergedTop.merged ? (incoming ? .Left : .Right) : .None(incoming ? .Incoming : .Outgoing)
let bottomNodeMergeStatus: ChatMessageBubbleMergeStatus = mergedBottom.merged ? (incoming ? .Left : .Right) : .None(incoming ? .Incoming : .Outgoing)
@@ -1100,16 +1105,21 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
}
var index = 0
for (message, _, attributes, isAttachment, prepareLayout) in contentPropertiesAndPrepareLayouts {
for (message, _, attributes, bubbleAttributes, prepareLayout) in contentPropertiesAndPrepareLayouts {
let topPosition: ChatMessageBubbleRelativePosition
let bottomPosition: ChatMessageBubbleRelativePosition
if index != 0 && contentPropertiesAndPrepareLayouts[index - 1].3 {
topPosition = .Neighbour(true, .freeform)
} else {
topPosition = .Neighbour(false, .freeform)
var topBubbleAttributes = BubbleItemAttributes(isAttachment: false, neighborType: .freeform)
var bottomBubbleAttributes = BubbleItemAttributes(isAttachment: false, neighborType: .freeform)
if index != 0 {
topBubbleAttributes = contentPropertiesAndPrepareLayouts[index - 1].3
}
bottomPosition = .Neighbour(false, .freeform)
if index != contentPropertiesAndPrepareLayouts.count - 1 {
bottomBubbleAttributes = contentPropertiesAndPrepareLayouts[index + 1].3
}
topPosition = .Neighbour(topBubbleAttributes.isAttachment, topBubbleAttributes.neighborType)
bottomPosition = .Neighbour(bottomBubbleAttributes.isAttachment, bottomBubbleAttributes.neighborType)
let prepareContentPosition: ChatMessageBubblePreparePosition
if let mosaicRange = mosaicRange, mosaicRange.contains(index) {
@@ -1118,7 +1128,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
let refinedBottomPosition: ChatMessageBubbleRelativePosition
if index == contentPropertiesAndPrepareLayouts.count - 1 {
refinedBottomPosition = .None(.Left)
} else if index == contentPropertiesAndPrepareLayouts.count - 2 && contentPropertiesAndPrepareLayouts[contentPropertiesAndPrepareLayouts.count - 1].3 {
} else if index == contentPropertiesAndPrepareLayouts.count - 2 && contentPropertiesAndPrepareLayouts[contentPropertiesAndPrepareLayouts.count - 1].3.isAttachment {
refinedBottomPosition = .None(.Left)
} else {
refinedBottomPosition = bottomPosition
@@ -1151,7 +1161,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
let (properties, unboundSize, maxNodeWidth, nodeLayout) = prepareLayout(contentItem, layoutConstants, prepareContentPosition, itemSelection, CGSize(width: maximumContentWidth, height: CGFloat.greatestFiniteMagnitude))
maximumNodeWidth = min(maximumNodeWidth, maxNodeWidth)
contentPropertiesAndLayouts.append((unboundSize, properties, prepareContentPosition, isAttachment, nodeLayout))
contentPropertiesAndLayouts.append((unboundSize, properties, prepareContentPosition, bubbleAttributes, nodeLayout))
switch properties.hidesBackground {
case .never:
@@ -1266,7 +1276,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
maximumNodeWidth = size.width
if mosaicRange.upperBound == contentPropertiesAndLayouts.count {
if mosaicRange.upperBound == contentPropertiesAndLayouts.count || contentPropertiesAndLayouts[contentPropertiesAndLayouts.count - 1].3.isAttachment {
let message = item.content.firstMessage
var edited = false
@@ -1601,19 +1611,26 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
case .linear:
let topPosition: ChatMessageBubbleRelativePosition
let bottomPosition: ChatMessageBubbleRelativePosition
var topBubbleAttributes = BubbleItemAttributes(isAttachment: false, neighborType: .freeform)
var bottomBubbleAttributes = BubbleItemAttributes(isAttachment: false, neighborType: .freeform)
if i != 0 {
topBubbleAttributes = contentPropertiesAndLayouts[i - 1].3
}
if i != contentPropertiesAndLayouts.count - 1 {
bottomBubbleAttributes = contentPropertiesAndLayouts[i + 1].3
}
if i == 0 {
topPosition = firstNodeTopPosition
} else if i == contentNodeCount - 1 && i != 0 && contentPropertiesAndLayouts[i - 1].3 {
topPosition = .Neighbour(true, .freeform)
} else {
topPosition = .Neighbour(false, .freeform)
topPosition = .Neighbour(topBubbleAttributes.isAttachment, topBubbleAttributes.neighborType)
}
if i == contentNodeCount - 1 {
bottomPosition = lastNodeTopPosition
} else {
bottomPosition = .Neighbour(false, .freeform)
bottomPosition = .Neighbour(bottomBubbleAttributes.isAttachment, bottomBubbleAttributes.neighborType)
}
contentPosition = .linear(top: topPosition, bottom: bottomPosition)
@@ -1832,7 +1849,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
replyInfoOriginY: CGFloat,
removedContentNodeIndices: [Int]?,
addedContentNodes: [(Message, ChatMessageBubbleContentNode)]?,
contentNodeMessagesAndClasses: [(Message, AnyClass, ChatMessageEntryAttributes, Bool)],
contentNodeMessagesAndClasses: [(Message, AnyClass, ChatMessageEntryAttributes, BubbleItemAttributes)],
contentNodeFramesPropertiesAndApply: [(CGRect, ChatMessageBubbleContentProperties, (ListViewItemUpdateAnimation, Bool) -> Void)],
mosaicStatusOrigin: CGPoint?,
mosaicStatusSizeAndApply: (CGSize, (Bool) -> ChatMessageDateAndStatusNode)?,
@@ -2475,8 +2492,10 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePrevewItemNode
if item.content.firstMessage.id.peerId.isRepliesOrSavedMessages(accountPeerId: item.context.account.peerId) {
navigate = .chat(textInputState: nil, subject: nil, peekData: nil)
} else {
} else if openPeerId.namespace == Namespaces.Peer.CloudUser {
navigate = .info
} else {
navigate = .chat(textInputState: nil, subject: nil, peekData: nil)
}
for attribute in item.content.firstMessage.attributes {

View File

@@ -100,10 +100,13 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: false, headerSpacing: 0.0, hidesBackground: .never, forceFullCorners: false, forceAlignment: .none)
let displaySeparator: Bool
if case let .linear(top, _) = preparePosition, case .Neighbour(true, _) = top {
let topOffset: CGFloat
if case let .linear(top, _) = preparePosition, case .Neighbour(_, .media) = top {
displaySeparator = false
topOffset = 2.0
} else {
displaySeparator = true
topOffset = 0.0
}
return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in
@@ -163,7 +166,7 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
let (textLayout, textApply) = textLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: textConstrainedSize, alignment: .natural, cutout: nil, insets: textInsets, lineColor: messageTheme.accentControlColor))
var textFrame = CGRect(origin: CGPoint(x: -textInsets.left + textLeftInset, y: -textInsets.top + 5.0), size: textLayout.size)
var textFrame = CGRect(origin: CGPoint(x: -textInsets.left + textLeftInset, y: -textInsets.top + 5.0 + topOffset), size: textLayout.size)
var textFrameWithoutInsets = CGRect(origin: CGPoint(x: textFrame.origin.x + textInsets.left, y: textFrame.origin.y + textInsets.top), size: CGSize(width: textFrame.width - textInsets.left - textInsets.right, height: textFrame.height - textInsets.top - textInsets.bottom))
textFrame = textFrame.offsetBy(dx: layoutConstants.text.bubbleInsets.left, dy: layoutConstants.text.bubbleInsets.top - 5.0 + UIScreenPixel)
@@ -189,7 +192,7 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
boundingSize = textFrameWithoutInsets.size
boundingSize.width += layoutConstants.text.bubbleInsets.left + layoutConstants.text.bubbleInsets.right
boundingSize.height = 40.0
boundingSize.height = 40.0 + topOffset
return (boundingSize, { [weak self] animation, synchronousLoad in
if let strongSelf = self {
@@ -225,17 +228,17 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
if let iconImage = iconImage {
strongSelf.iconNode.image = iconImage
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: 15.0 + iconOffset.x, y: 6.0 + iconOffset.y), size: iconImage.size)
strongSelf.iconNode.frame = CGRect(origin: CGPoint(x: 15.0 + iconOffset.x, y: 6.0 + iconOffset.y + topOffset), size: iconImage.size)
}
if let arrowImage = arrowImage {
strongSelf.arrowNode.image = arrowImage
strongSelf.arrowNode.frame = CGRect(origin: CGPoint(x: boundingWidth - 33.0, y: 6.0), size: arrowImage.size)
strongSelf.arrowNode.frame = CGRect(origin: CGPoint(x: boundingWidth - 33.0, y: 6.0 + topOffset), size: arrowImage.size)
}
strongSelf.iconNode.isHidden = !replyPeers.isEmpty
let avatarsFrame = CGRect(origin: CGPoint(x: 13.0, y: 3.0), size: CGSize(width: imageSize * 3.0, height: imageSize))
let avatarsFrame = CGRect(origin: CGPoint(x: 13.0, y: 3.0 + topOffset), size: CGSize(width: imageSize * 3.0, height: imageSize))
strongSelf.avatarsNode.frame = avatarsFrame
strongSelf.avatarsNode.updateLayout(size: avatarsFrame.size)
strongSelf.avatarsNode.update(context: item.context, peers: replyPeers, synchronousLoad: synchronousLoad, imageSize: imageSize, imageSpacing: imageSpacing, borderWidth: 2.0 - UIScreenPixel)
@@ -245,6 +248,8 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
strongSelf.separatorNode.frame = CGRect(origin: CGPoint(x: layoutConstants.bubble.strokeInsets.left, y: -3.0), size: CGSize(width: boundingWidth - layoutConstants.bubble.strokeInsets.left - layoutConstants.bubble.strokeInsets.right, height: UIScreenPixel))
strongSelf.buttonNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: boundingWidth, height: boundingSize.height))
strongSelf.buttonNode.isUserInteractionEnabled = item.message.id.namespace == Namespaces.Message.Cloud
}
})
})
@@ -276,7 +281,7 @@ final class ChatMessageCommentFooterContentNode: ChatMessageBubbleContentNode {
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if self.buttonNode.frame.contains(point) {
if self.buttonNode.isUserInteractionEnabled && self.buttonNode.frame.contains(point) {
return self.buttonNode.view
}
return nil

View File

@@ -176,7 +176,7 @@ class ChatMessageContactBubbleContentNode: ChatMessageBubbleContentNode {
let statusType: ChatMessageDateAndStatusType?
switch position {
case .linear(_, .None):
case .linear(_, .None), .linear(_, .Neighbour(true, _)):
if item.message.effectivelyIncoming(item.context.account.peerId) {
statusType = .BubbleIncoming
} else {

View File

@@ -69,7 +69,7 @@ class ChatMessageFileBubbleContentNode: ChatMessageBubbleContentNode {
let incoming = item.message.effectivelyIncoming(item.context.account.peerId)
let statusType: ChatMessageDateAndStatusType?
switch preparePosition {
case .linear(_, .None):
case .linear(_, .None), .linear(_, .Neighbour(true, _)):
if incoming {
statusType = .BubbleIncoming
} else {

View File

@@ -212,7 +212,7 @@ class ChatMessageMapBubbleContentNode: ChatMessageBubbleContentNode {
let statusType: ChatMessageDateAndStatusType?
switch position {
case .linear(_, .None):
case .linear(_, .None), .linear(_, .Neighbour(true, _)):
if selectedMedia?.venue != nil || activeLiveBroadcastingTimeout != nil {
if item.message.effectivelyIncoming(item.context.account.peerId) {
statusType = .BubbleIncoming

View File

@@ -207,7 +207,7 @@ class ChatMessageMediaBubbleContentNode: ChatMessageBubbleContentNode {
let statusType: ChatMessageDateAndStatusType?
switch position {
case .linear(_, .None):
case .linear(_, .None), .linear(_, .Neighbour(true, _)):
if item.message.effectivelyIncoming(item.context.account.peerId) {
statusType = .ImageIncoming
} else {

View File

@@ -1054,7 +1054,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
let statusType: ChatMessageDateAndStatusType?
switch position {
case .linear(_, .None):
case .linear(_, .None), .linear(_, .Neighbour(true, _)):
if incoming {
statusType = .BubbleIncoming
} else {

View File

@@ -85,7 +85,7 @@ class ChatMessageRestrictedBubbleContentNode: ChatMessageBubbleContentNode {
let statusType: ChatMessageDateAndStatusType?
switch position {
case .linear(_, .None):
case .linear(_, .None), .linear(_, .Neighbour(true, _)):
if incoming {
statusType = .BubbleIncoming
} else {

View File

@@ -140,14 +140,14 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
let statusType: ChatMessageDateAndStatusType?
var displayStatus = false
switch position {
case let .linear(_, neighbor):
if case .None = neighbor {
displayStatus = true
} else if case .Neighbour(true, _) = neighbor {
displayStatus = true
}
default:
break
case let .linear(_, neighbor):
if case .None = neighbor {
displayStatus = true
} else if case .Neighbour(true, _) = neighbor {
displayStatus = true
}
default:
break
}
if displayStatus {
if incoming {

View File

@@ -203,6 +203,7 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
self.setNeedsLayout()
}
self.isUserInteractionEnabled = isEnabled
self.button.isUserInteractionEnabled = isEnabled
self.updateStatus()
}
}
@@ -635,6 +636,9 @@ final class ChatTitleView: UIView, NavigationBarTitleView {
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if !self.isUserInteractionEnabled {
return nil
}
if self.button.frame.contains(point) {
return self.button.view
}