FileMessageCell.swift 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import UIKit
  2. // A subclass of `MessageContentCell` used to display mixed media messages.
  3. open class FileMessageCell: MessageContentCell {
  4. public static let insetBottom: CGFloat = 12
  5. public static let insetHorizontalBig: CGFloat = 23
  6. public static let insetHorizontalSmall: CGFloat = 12
  7. var fileViewLeadingPadding: CGFloat = 0 {
  8. didSet {
  9. fileViewLeadingAlignment.constant = fileViewLeadingPadding
  10. }
  11. }
  12. private lazy var fileViewLeadingAlignment: NSLayoutConstraint = {
  13. return fileView.constraintAlignLeadingTo(messageContainerView, paddingLeading: 0)
  14. }()
  15. private var mediaItem: MediaItem?
  16. // MARK: - Properties
  17. /// The `MessageCellDelegate` for the cell.
  18. open override weak var delegate: MessageCellDelegate? {
  19. didSet {
  20. messageLabel.delegate = delegate
  21. }
  22. }
  23. /// The label used to display the message's text.
  24. open var messageLabel = MessageLabel()
  25. lazy var fileView: FileView = {
  26. let fileView = FileView()
  27. fileView.translatesAutoresizingMaskIntoConstraints = false
  28. return fileView
  29. }()
  30. // MARK: - Methods
  31. /// Responsible for setting up the constraints of the cell's subviews.
  32. open func setupConstraints(for messageKind: MessageKind) {
  33. messageContainerView.removeConstraints(messageContainerView.constraints)
  34. let fileViewConstraints = [fileView.constraintHeightTo(FileView.defaultHeight),
  35. fileViewLeadingAlignment,
  36. fileView.constraintAlignTrailingTo(messageContainerView),
  37. fileView.constraintAlignTopTo(messageContainerView),
  38. ]
  39. messageContainerView.addConstraints(fileViewConstraints)
  40. messageLabel.frame = CGRect(x: 0,
  41. y: FileView.defaultHeight,
  42. width: messageContainerView.frame.width,
  43. height: getMessageLabelHeight())
  44. }
  45. func getMessageLabelHeight() -> CGFloat {
  46. if let text = messageLabel.attributedText, !text.string.isEmpty {
  47. let height = (text.height(withConstrainedWidth:
  48. messageContainerView.frame.width -
  49. FileMessageCell.insetHorizontalSmall -
  50. FileMessageCell.insetHorizontalBig))
  51. return height + FileMessageCell.insetBottom
  52. }
  53. return 0
  54. }
  55. open override func setupSubviews() {
  56. super.setupSubviews()
  57. messageContainerView.addSubview(fileView)
  58. messageContainerView.addSubview(messageLabel)
  59. }
  60. open override func prepareForReuse() {
  61. super.prepareForReuse()
  62. self.messageLabel.attributedText = nil
  63. self.fileView.prepareForReuse()
  64. }
  65. open override func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
  66. super.apply(layoutAttributes)
  67. if let attributes = layoutAttributes as? MessagesCollectionViewLayoutAttributes {
  68. messageLabel.textInsets = attributes.messageLabelInsets
  69. messageLabel.messageLabelFont = attributes.messageLabelFont
  70. fileViewLeadingPadding = attributes.messageLabelInsets.left
  71. }
  72. }
  73. // MARK: - Configure Cell
  74. open override func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) {
  75. super.configure(with: message, at: indexPath, and: messagesCollectionView)
  76. guard let displayDelegate = messagesCollectionView.messagesDisplayDelegate else {
  77. fatalError(MessageKitError.nilMessagesDisplayDelegate)
  78. }
  79. switch message.kind {
  80. case .fileText(let mediaItem):
  81. configureFileView(for: mediaItem)
  82. configureMessageLabel(for: mediaItem,
  83. with: displayDelegate,
  84. message: message,
  85. at: indexPath,
  86. in: messagesCollectionView)
  87. default:
  88. fatalError("Unexpected message kind in FileMessageCell")
  89. }
  90. setupConstraints(for: message.kind)
  91. }
  92. func configureFileView(for mediaItem: MediaItem) {
  93. fileView.configureFor(mediaItem: mediaItem)
  94. }
  95. func configureMessageLabel(for mediaItem: MediaItem,
  96. with displayDelegate: MessagesDisplayDelegate,
  97. message: MessageType,
  98. at indexPath: IndexPath,
  99. in messagesCollectionView: MessagesCollectionView) {
  100. let enabledDetectors = displayDelegate.enabledDetectors(for: message, at: indexPath, in: messagesCollectionView)
  101. messageLabel.configure {
  102. messageLabel.enabledDetectors = enabledDetectors
  103. for detector in enabledDetectors {
  104. let attributes = displayDelegate.detectorAttributes(for: detector, and: message, at: indexPath)
  105. messageLabel.setAttributes(attributes, detector: detector)
  106. }
  107. messageLabel.attributedText = mediaItem.text?[MediaItemConstants.messageText]
  108. }
  109. }
  110. /// Used to handle the cell's contentView's tap gesture.
  111. /// Return false when the contentView does not need to handle the gesture.
  112. open override func cellContentView(canHandle touchPoint: CGPoint) -> Bool {
  113. let touchPointWithoutImageHeight = CGPoint(x: touchPoint.x,
  114. y: touchPoint.y - fileView.frame.height)
  115. return messageLabel.handleGesture(touchPointWithoutImageHeight)
  116. }
  117. }