2023-10-22 22:06:14 +04:00

171 lines
5.7 KiB
Swift

import Foundation
import UIKit
import Postbox
import AsyncDisplayKit
import Display
import SwiftSignalKit
import TelegramCore
import AccountContext
import ChatHistoryEntry
import ChatControllerInteraction
import TelegramPresentationData
import ChatMessageItemCommon
public enum ChatMessageItemContent: Sequence {
case message(message: Message, read: Bool, selection: ChatHistoryMessageSelection, attributes: ChatMessageEntryAttributes, location: MessageHistoryEntryLocation?)
case group(messages: [(Message, Bool, ChatHistoryMessageSelection, ChatMessageEntryAttributes, MessageHistoryEntryLocation?)])
public func effectivelyIncoming(_ accountPeerId: PeerId, associatedData: ChatMessageItemAssociatedData? = nil) -> Bool {
if let subject = associatedData?.subject, case let .messageOptions(_, _, info) = subject, case .forward = info {
return false
}
switch self {
case let .message(message, _, _, _, _):
return message.effectivelyIncoming(accountPeerId)
case let .group(messages):
return messages[0].0.effectivelyIncoming(accountPeerId)
}
}
public var index: MessageIndex {
switch self {
case let .message(message, _, _, _, _):
return message.index
case let .group(messages):
return messages[0].0.index
}
}
public var firstMessage: Message {
switch self {
case let .message(message, _, _, _, _):
return message
case let .group(messages):
return messages[0].0
}
}
public var firstMessageAttributes: ChatMessageEntryAttributes {
switch self {
case let .message(_, _, _, attributes, _):
return attributes
case let .group(messages):
return messages[0].3
}
}
public func makeIterator() -> AnyIterator<(Message, ChatMessageEntryAttributes)> {
var index = 0
return AnyIterator { () -> (Message, ChatMessageEntryAttributes)? in
switch self {
case let .message(message, _, _, attributes, _):
if index == 0 {
index += 1
return (message, attributes)
} else {
index += 1
return nil
}
case let .group(messages):
if index < messages.count {
let currentIndex = index
index += 1
return (messages[currentIndex].0, messages[currentIndex].3)
} else {
return nil
}
}
}
}
}
public enum ChatMessageItemAdditionalContent {
case eventLogPreviousMessage(Message)
case eventLogPreviousDescription(Message)
case eventLogPreviousLink(Message)
}
public enum ChatMessageMerge: Int32 {
case none = 0
case fullyMerged = 1
case semanticallyMerged = 2
public var merged: Bool {
if case .none = self {
return false
} else {
return true
}
}
}
public protocol ChatMessageAvatarHeaderNode: ListViewItemHeaderNode {
func updateSelectionState(animated: Bool)
}
public protocol ChatMessageItem: ListViewItem {
var presentationData: ChatPresentationData { get }
var context: AccountContext { get }
var chatLocation: ChatLocation { get }
var associatedData: ChatMessageItemAssociatedData { get }
var controllerInteraction: ChatControllerInteraction { get }
var content: ChatMessageItemContent { get }
var disableDate: Bool { get }
var effectiveAuthorId: PeerId? { get }
var additionalContent: ChatMessageItemAdditionalContent? { get }
var headers: [ListViewItemHeader] { get }
var message: Message { get }
var read: Bool { get }
var unsent: Bool { get }
var sending: Bool { get }
var failed: Bool { get }
func mergedWithItems(top: ListViewItem?, bottom: ListViewItem?) -> (top: ChatMessageMerge, bottom: ChatMessageMerge, dateAtBottom: Bool)
}
public func hasCommentButton(item: ChatMessageItem) -> Bool {
let firstMessage = item.content.firstMessage
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
}
if case let .replyThread(replyThreadMessage) = item.chatLocation, replyThreadMessage.effectiveTopId == firstMessage.id {
hasDiscussion = false
}
if firstMessage.adAttribute != nil {
hasDiscussion = false
}
if hasDiscussion {
var canComment = false
if case .pinnedMessages = item.associatedData.subject {
canComment = false
} else if firstMessage.id.namespace == Namespaces.Message.Local {
canComment = true
} else {
for attribute in firstMessage.attributes {
if let attribute = attribute as? ReplyThreadMessageAttribute, let commentsPeerId = attribute.commentsPeerId {
switch item.associatedData.channelDiscussionGroup {
case .unknown:
canComment = true
case let .known(groupId):
canComment = groupId == commentsPeerId
}
break
}
}
}
if canComment {
return true
}
} else if firstMessage.id.peerId.isReplies {
return true
}
return false
}