Skip to content

Commit

Permalink
Merge pull request #5 from quipper/fix_cell_bottom_view
Browse files Browse the repository at this point in the history
Fix cell bottom view
  • Loading branch information
m-sugawara authored Sep 4, 2019
2 parents 4fd7037 + cac815a commit 6c40cd6
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class AnnouncementExampleViewController: MessagesViewController {
private let deleteButtonWidth: CGFloat = 40
private let retryButtonWidth: CGFloat = 40

private let outgoingAvatarSize = CGSize(width: 20, height: 20)
private let outgoingMessagePadding = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 10)

override func viewDidLoad() {
super.viewDidLoad()

Expand All @@ -33,11 +36,9 @@ class AnnouncementExampleViewController: MessagesViewController {
if let layout = messagesCollectionView.collectionViewLayout as? MessagesCollectionViewFlowLayout {
layout.sectionInset = UIEdgeInsets(top: 1, left: 8, bottom: 1, right: 8)

layout.setMessageOutgoingAvatarSize(CGSize(width: 20, height: 20))
layout.setMessageOutgoingAvatarSize(outgoingAvatarSize)
layout.setMessageOutgoingAvatarPosition(.init(horizontal: .cellTrailing, vertical: .messageBottom))
layout.setMessageOutgoingMessagePadding(.init(top: 0, left: 0, bottom: 0, right: 10))

layout.setMessageOutgoingCellBottomViewSize(CGSize(width: failedLabelWidth + deleteButtonWidth + retryButtonWidth, height: 24))
layout.setMessageOutgoingMessagePadding(outgoingMessagePadding)
}

messagesCollectionView.messagesDataSource = self
Expand Down Expand Up @@ -94,6 +95,11 @@ class AnnouncementExampleViewController: MessagesViewController {
size: CGSize(width: 182, height: 182))
}

private func isfailedToSendMessage(at indexPath: IndexPath) -> Bool {
let conversationMessage = conversationMessages[indexPath.row]
return currentSender().senderId == conversationMessage.sender.senderId && conversationMessage.isFailed
}

func displayMessageSource(from message: ConversationMessage) -> MessageDisplaySource {
let sender = message.sender
let sentDate = Date(timeIntervalSince1970: message.createdTs)
Expand Down Expand Up @@ -164,33 +170,18 @@ extension AnnouncementExampleViewController: MessagesDataSource {
}

extension AnnouncementExampleViewController: MessagesDisplayDelegate {
func cellTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
guard shouldShowTopDateLabel(at: indexPath) else { return 0 }

return 40
}

func messageTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
guard shouldShowSenderInfo(for: message, at: indexPath) else { return 0 }

return 24
}

func messageBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 0
}

func cellBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 0
@objc func didTapDelete(sender: UIButton) {
print("didTapDelete index: \(sender.tag)")
}

func timeLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 20
@objc func didTapRetry(sender: UIButton) {
print("didTapRetry index: \(sender.tag)")
}

func configureCellBottomView(_ cellBottomView: UIView, for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) {
cellBottomView.subviews.forEach { $0.removeFromSuperview() }
guard currentSender().senderId == conversationMessages[indexPath.row].sender.senderId else {
guard isfailedToSendMessage(at: indexPath) else {
return
}

Expand All @@ -213,18 +204,12 @@ extension AnnouncementExampleViewController: MessagesDisplayDelegate {
cellBottomView.addSubview(deleteButton)
cellBottomView.addSubview(retryButton)

let maxX = cellBottomView.frame.maxX - outgoingMessagePadding.right - outgoingAvatarSize.width
let height = cellBottomView.bounds.height
label.frame = CGRect(x: 0, y: 0, width: failedLabelWidth, height: height)
deleteButton.frame = CGRect(x: failedLabelWidth, y: 0, width: deleteButtonWidth, height: height)
retryButton.frame = CGRect(x: failedLabelWidth + deleteButtonWidth, y: 0, width: retryButtonWidth, height: height)
}

@objc func didTapDelete(sender: UIButton) {
print("didTapDelete index: \(sender.tag)")
}

@objc func didTapRetry(sender: UIButton) {
print("didTapRetry index: \(sender.tag)")
label.frame = CGRect(x: maxX - (failedLabelWidth + retryButtonWidth + deleteButtonWidth), y: 0, width: failedLabelWidth, height: height)
deleteButton.frame = CGRect(x: maxX - (deleteButtonWidth + retryButtonWidth), y: 0, width: deleteButtonWidth, height: height)
retryButton.frame = CGRect(x: maxX - retryButtonWidth, y: 0, width: retryButtonWidth, height: height)
}

func configureAvatarView(_ avatarView: AvatarView, for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) {
Expand All @@ -245,9 +230,7 @@ extension AnnouncementExampleViewController: MessagesDisplayDelegate {
let avatar = Avatar(image: nil, initials: "S")
avatarView.set(avatar: avatar)
}
}

extension AnnouncementExampleViewController: MessagesLayoutDelegate {
func detectorAttributes(for detector: DetectorType, and message: MessageType, at indexPath: IndexPath) -> [NSAttributedString.Key: Any] {
return [
NSAttributedString.Key.foregroundColor: UIColor.white,
Expand All @@ -260,6 +243,40 @@ extension AnnouncementExampleViewController: MessagesLayoutDelegate {
return [.url]
}

}

extension AnnouncementExampleViewController: MessagesLayoutDelegate {
func cellTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
guard shouldShowTopDateLabel(at: indexPath) else { return 0 }

return 40
}

func messageTopLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
guard shouldShowSenderInfo(for: message, at: indexPath) else { return 0 }

return 24
}

func messageBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 0
}

func cellBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 0
}

func timeLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 20
}

func cellBottomViewHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
guard isfailedToSendMessage(at: indexPath) else {
return 0
}
return 24
}

// MARK: - All Messages
func textColor(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> UIColor {
guard conversationMessages.count > indexPath.row else { fatalError("message couldn't find") }
Expand Down Expand Up @@ -300,8 +317,20 @@ extension AnnouncementExampleViewController: MessagesLayoutDelegate {
return isFromCurrentSender(message: message) ? .rightBubble : .leftBubble
}
}
}

extension AnnouncementExampleViewController: MessageCellDelegate {
func didTapMessage(in cell: MessageCollectionViewCell) {
guard let indexPath = messagesCollectionView.indexPath(for: cell),
let message = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else { return }
didSelectMessage(at: indexPath, message: message)
}

func didSelectURL(_ url: URL) {
print("url selected: \(url.absoluteString)")
}

func didSelectMessage(at indexPath: IndexPath, message: MessageType) {
private func didSelectMessage(at indexPath: IndexPath, message: MessageType) {
switch message.kind {
case .text:
break
Expand All @@ -317,19 +346,6 @@ extension AnnouncementExampleViewController: MessagesLayoutDelegate {
break
}
}

}

extension AnnouncementExampleViewController: MessageCellDelegate {
func didTapMessage(in cell: MessageCollectionViewCell) {
guard let indexPath = messagesCollectionView.indexPath(for: cell),
let message = messagesCollectionView.messagesDataSource?.messageForItem(at: indexPath, in: messagesCollectionView) else { return }
print("message selected: \(message.messageId)")
}

func didSelectURL(_ url: URL) {
print("url selected: \(url.absoluteString)")
}
}

extension UICollectionViewCell {
Expand Down Expand Up @@ -370,7 +386,8 @@ enum ConversationMessageMockFactory {
createdTs: Date().timeIntervalSince1970),
ConversationMessage(sender: me,
text: "Thanks",
createdTs: Date().timeIntervalSince1970),
createdTs: Date().timeIntervalSince1970,
isFailed: true),
ConversationMessage(sender: other,
text: "Last announcement",
image: nil,
Expand All @@ -392,15 +409,18 @@ struct ConversationMessage {
let createdTs: TimeInterval
let isAnnouncement: Bool
let isWarning: Bool
let isFailed: Bool

init(sender: User, text: String? = nil, image: UIImage? = nil,
createdTs: TimeInterval, isAnnouncement: Bool = false, isWarning: Bool = false) {
createdTs: TimeInterval, isAnnouncement: Bool = false, isWarning: Bool = false,
isFailed: Bool = false) {
self.sender = sender
self.text = text
self.image = image
self.createdTs = createdTs
self.isAnnouncement = isAnnouncement
self.isWarning = isWarning
self.isFailed = isFailed
}
}

Expand Down
16 changes: 7 additions & 9 deletions Sources/Layout/MessageSizeCalculator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ open class MessageSizeCalculator: CellSizeCalculator {
public var incomingAccessoryViewSize = CGSize.zero
public var outgoingAccessoryViewSize = CGSize.zero

public var incomingCellBottomViewSize = CGSize.zero
public var outgoingCellBottomViewSize = CGSize.zero

public var incomingAccessoryViewPadding = HorizontalEdgeInsets.zero
public var outgoingAccessoryViewPadding = HorizontalEdgeInsets.zero

Expand Down Expand Up @@ -92,7 +89,7 @@ open class MessageSizeCalculator: CellSizeCalculator {
attributes.messageBottomLabelAlignment = messageBottomLabelAlignment(for: message)
attributes.messageBottomLabelSize = messageBottomLabelSize(for: message, at: indexPath)

attributes.cellBottomViewSize = cellBottomViewSize(for: message)
attributes.cellBottomViewSize = cellBottomViewSize(for: message, at: indexPath)

attributes.accessoryViewSize = accessoryViewSize(for: message)
attributes.accessoryViewPadding = accessoryViewPadding(for: message)
Expand All @@ -117,7 +114,7 @@ open class MessageSizeCalculator: CellSizeCalculator {
let cellTopLabelHeight = cellTopLabelSize(for: message, at: indexPath).height
let messageTopLabelHeight = messageTopLabelSize(for: message, at: indexPath).height
let messageVerticalPadding = messageContainerPadding(for: message).vertical
let cellBottomViewHeight = cellBottomViewSize(for: message).height
let cellBottomViewHeight = cellBottomViewSize(for: message, at: indexPath).height
let avatarHeight = avatarSize(for: message).height
let avatarVerticalPosition = avatarPosition(for: message).vertical
let accessoryViewHeight = accessoryViewSize(for: message).height
Expand Down Expand Up @@ -242,10 +239,11 @@ open class MessageSizeCalculator: CellSizeCalculator {

// MARK: - Cell Bottom View

public func cellBottomViewSize(for message: MessageType) -> CGSize {
let dataSource = messagesLayout.messagesDataSource
let isFromCurrentSender = dataSource.isFromCurrentSender(message: message)
return isFromCurrentSender ? outgoingCellBottomViewSize : incomingCellBottomViewSize
public func cellBottomViewSize(for message: MessageType, at indexPath: IndexPath) -> CGSize {
let layoutDelegate = messagesLayout.messagesLayoutDelegate
let collectionView = messagesLayout.messagesCollectionView
let height = layoutDelegate.cellBottomViewHeight(for: message, at: indexPath, in: collectionView)
return CGSize(width: messagesLayout.itemWidth, height: height)
}

// MARK: - Accessory View
Expand Down
10 changes: 0 additions & 10 deletions Sources/Layout/MessagesCollectionViewFlowLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -285,16 +285,6 @@ open class MessagesCollectionViewFlowLayout: UICollectionViewFlowLayout {
messageSizeCalculators().forEach { $0.outgoingMessageBottomLabelAlignment = newAlignment }
}

/// Set `incomingCellBottomViewSize` of all `MessageSizeCalculator`s
public func setMessageIncomingCellBottomViewSize(_ newSize: CGSize) {
messageSizeCalculators().forEach { $0.incomingCellBottomViewSize = newSize }
}

/// Set `outgoingCellBottomViewSize` of all `MessageSizeCalculator`s
public func setMessageOutgoingCellBottomViewSize(_ newSize: CGSize) {
messageSizeCalculators().forEach { $0.outgoingCellBottomViewSize = newSize }
}

/// Set `incomingAccessoryViewSize` of all `MessageSizeCalculator`s
public func setMessageIncomingAccessoryViewSize(_ newSize: CGSize) {
messageSizeCalculators().forEach { $0.incomingAccessoryViewSize = newSize }
Expand Down
15 changes: 15 additions & 0 deletions Sources/Protocols/MessagesLayoutDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,17 @@ public protocol MessagesLayoutDelegate: AnyObject {
/// The default value returned by this method is zero.
func messageBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat

/// Specifies the height for the bottom view of messageCotentainerCell.
///
/// - Parameters:
/// - message: The `MessageType` that will be displayed for this cell.
/// - indexPath: The `IndexPath` of the cell.
/// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed.
///
/// - Note:
/// The default value returned by this method is zero.
func cellBottomViewHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat

/// Specifies the height for the time label.
func timeLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat

Expand Down Expand Up @@ -159,6 +170,10 @@ public extension MessagesLayoutDelegate {
func messageBottomLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 0
}

func cellBottomViewHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 0
}

func timeLabelHeight(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGFloat {
return 0
Expand Down
3 changes: 1 addition & 2 deletions Sources/Views/Cells/MessageContentCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,8 @@ open class MessageContentCell: MessageCollectionViewCell {
/// Positions the cell's bottom view.
/// - attributes: The `MessagesCollectionViewLayoutAttributes` for the cell.
open func layoutCellBottomView(with attributes: MessagesCollectionViewLayoutAttributes) {
let x = messageContainerView.frame.maxX - attributes.cellBottomViewSize.width
let y = cellBottomLabel.frame.maxY
let origin = CGPoint(x: x, y: y)
let origin = CGPoint(x: 0, y: y)

cellBottomView.frame = CGRect(origin: origin, size: attributes.cellBottomViewSize)
}
Expand Down

0 comments on commit 6c40cd6

Please sign in to comment.