diff --git a/Example/Sources/ConversationViewController.swift b/Example/Sources/ConversationViewController.swift index 61850a12..1a8448c5 100644 --- a/Example/Sources/ConversationViewController.swift +++ b/Example/Sources/ConversationViewController.swift @@ -145,11 +145,7 @@ extension ConversationViewController: MessagesDisplayDataSource { func messageStyle(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageStyle { let corner: MessageStyle.TailCorner = isFromCurrentSender(message: message) ? .bottomRight : .bottomLeft - return .bubbleTail(corner, .pointedEdge) - } - - func messageHeaderView(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageHeaderView? { - return messagesCollectionView.dequeueMessageHeaderView(for: indexPath) + return .bubbleTail(corner, .curved) } func messageFooterView(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageFooterView? { @@ -174,12 +170,9 @@ extension ConversationViewController: MessagesDisplayDataSource { extension ConversationViewController: MessagesLayoutDelegate { - func headerViewSize(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGSize { - return CGSize(width: messagesCollectionView.bounds.width, height: 4) - } - func footerViewSize(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> CGSize { - return CGSize(width: messagesCollectionView.bounds.width, height: 4) + + return CGSize(width: messagesCollectionView.bounds.width, height: 10) } } diff --git a/Example/Sources/SampleData.swift b/Example/Sources/SampleData.swift index 8e022bbd..50f5c4f8 100644 --- a/Example/Sources/SampleData.swift +++ b/Example/Sources/SampleData.swift @@ -31,14 +31,15 @@ struct SampleData { let Cook = Sender(id: "656361", displayName: "Tim Cook") func getMessages() -> [MockMessage] { + let msg1 = MockMessage(text: "Check out this awesome UI library for Chat", sender: Dan, messageId: UUID().uuidString) - let msg2 = MockMessage(text: "This is insane.", sender: Steven, messageId: UUID().uuidString) - let msg3 = MockMessage(text: "Companies that get confused, that think their goal is revenue or stock price or something. You have to focus on the things that lead to those.", sender: Cook, messageId: UUID().uuidString) - let msg4 = MockMessage(text: "My favorite things in life don’t cost any money. It’s really clear that the most precious resource we all have is time.", sender: Jobs, messageId: UUID().uuidString) - let msg5 = MockMessage(text: "You know, this iPhone, as a matter of fact, the engine in here is made in America. And not only are the engines in here made in America, but engines are made in America and are exported. The glass on this phone is made in Kentucky. And so we've been working for years on doing more and more in the United States.", sender: Cook, messageId: UUID().uuidString) - let msg6 = MockMessage(text: "I think if you do something and it turns out pretty good, then you should go do something else wonderful, not dwell on it for too long. Just figure out what’s next.", sender: Jobs, messageId: UUID().uuidString) - let msg7 = MockMessage(text: "Remembering that I'll be dead soon is the most important tool I've ever encountered to help me make the big choices in life. Because almost everything - all external expectations, all pride, all fear of embarrassment or failure - these things just fall away in the face of death, leaving only what is truly important.", sender: Jobs, messageId: UUID().uuidString) - let msg8 = MockMessage(text: "Price is rarely the most important thing. A cheap product might sell some units. Somebody gets it home and they feel great when they pay the money, but then they get it home and use it and the joy is gone.", sender: Cook, messageId: UUID().uuidString) + var msg2 = MockMessage(text: "This is insane.", sender: Steven, messageId: UUID().uuidString) + var msg3 = MockMessage(text: "Companies that get confused, that think their goal is revenue or stock price or something. You have to focus on the things that lead to those.", sender: Cook, messageId: UUID().uuidString) + var msg4 = MockMessage(text: "My favorite things in life don’t cost any money. It’s really clear that the most precious resource we all have is time.", sender: Jobs, messageId: UUID().uuidString) + var msg5 = MockMessage(text: "You know, this iPhone, as a matter of fact, the engine in here is made in America. And not only are the engines in here made in America, but engines are made in America and are exported. The glass on this phone is made in Kentucky. And so we've been working for years on doing more and more in the United States.", sender: Cook, messageId: UUID().uuidString) + var msg6 = MockMessage(text: "I think if you do something and it turns out pretty good, then you should go do something else wonderful, not dwell on it for too long. Just figure out what’s next.", sender: Jobs, messageId: UUID().uuidString) + var msg7 = MockMessage(text: "Remembering that I'll be dead soon is the most important tool I've ever encountered to help me make the big choices in life. Because almost everything - all external expectations, all pride, all fear of embarrassment or failure - these things just fall away in the face of death, leaving only what is truly important.", sender: Jobs, messageId: UUID().uuidString) + var msg8 = MockMessage(text: "Price is rarely the most important thing. A cheap product might sell some units. Somebody gets it home and they feel great when they pay the money, but then they get it home and use it and the joy is gone.", sender: Cook, messageId: UUID().uuidString) let msg9String = "Use .attributedText() to add bold, italic, colored text and more..." let msg9Text = NSString(string: msg9String) @@ -60,12 +61,25 @@ struct SampleData { msg9AttributedText.addAttributes([NSForegroundColorAttributeName: UIColor.red], range: msg9Text.range(of: "colored")) - let msg9 = MockMessage(attributedText: msg9AttributedText, sender: Jobs, messageId: UUID().uuidString) + var msg9 = MockMessage(attributedText: msg9AttributedText, sender: Jobs, messageId: UUID().uuidString) - let msg10 = MockMessage(text: "1-800-555-0000", sender: Steven, messageId: UUID().uuidString) - let msg11 = MockMessage(text: "One Infinite Loop Cupertino, CA 95014 This is some extra text that should not be detected.", sender: Cook, messageId: UUID().uuidString) - let msg12 = MockMessage(text: "This is an example of the date detector 11/11/2017. April 1st is April Fools Day. Next Friday is not Friday the 13th.", sender: Steven, messageId: UUID().uuidString) - let msg13 = MockMessage(text: "https//:github.com/SD10", sender: Steven, messageId: UUID().uuidString) + var msg10 = MockMessage(text: "1-800-555-0000", sender: Steven, messageId: UUID().uuidString) + var msg11 = MockMessage(text: "One Infinite Loop Cupertino, CA 95014 This is some extra text that should not be detected.", sender: Cook, messageId: UUID().uuidString) + var msg12 = MockMessage(text: "This is an example of the date detector 11/11/2017. April 1st is April Fools Day. Next Friday is not Friday the 13th.", sender: Steven, messageId: UUID().uuidString) + var msg13 = MockMessage(text: "https//:github.com/SD10", sender: Steven, messageId: UUID().uuidString) + + msg2.sentDate = Calendar.current.date(byAdding: .hour, value: 2, to: msg1.sentDate)! + msg3.sentDate = Calendar.current.date(byAdding: .hour, value: 1, to: msg2.sentDate)! + msg4.sentDate = Calendar.current.date(byAdding: .minute, value: 37, to: msg3.sentDate)! + msg5.sentDate = Calendar.current.date(byAdding: .minute, value: 3, to: msg4.sentDate)! + msg6.sentDate = Calendar.current.date(byAdding: .hour, value: 2, to: msg5.sentDate)! + msg7.sentDate = Calendar.current.date(byAdding: .minute, value: 12, to: msg6.sentDate)! + msg8.sentDate = Calendar.current.date(byAdding: .minute, value: 23, to: msg7.sentDate)! + msg9.sentDate = Calendar.current.date(byAdding: .hour, value: 300, to: msg8.sentDate)! + msg10.sentDate = Calendar.current.date(byAdding: .hour, value: 11, to: msg9.sentDate)! + msg11.sentDate = Calendar.current.date(byAdding: .hour, value: 2, to: msg10.sentDate)! + msg12.sentDate = Calendar.current.date(byAdding: .minute, value: 59, to: msg11.sentDate)! + msg13.sentDate = Calendar.current.date(byAdding: .hour, value: 7, to: msg12.sentDate)! return [msg1, msg2, msg3, msg4, msg5, msg6, msg7, msg8, msg9, msg10, msg11, msg12, msg13] } @@ -73,6 +87,7 @@ struct SampleData { func getCurrentSender() -> Sender { return Dan } + func getAvatarFor(sender: Sender) -> Avatar { switch sender { diff --git a/MessageKit.xcodeproj/project.pbxproj b/MessageKit.xcodeproj/project.pbxproj index 45455210..369fef0e 100644 --- a/MessageKit.xcodeproj/project.pbxproj +++ b/MessageKit.xcodeproj/project.pbxproj @@ -25,7 +25,8 @@ 88916B471CF0DFE600469F91 /* MessageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88916B461CF0DFE600469F91 /* MessageType.swift */; }; B01280F31F4E8798004BCD3E /* MessageLabelDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B01280F21F4E8798004BCD3E /* MessageLabelDelegate.swift */; }; B0147C831F5BE9220035B36E /* Bundle+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0147C821F5BE9220035B36E /* Bundle+Extensions.swift */; }; - B0147C871F5C129C0035B36E /* TailCorner.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0147C861F5C129C0035B36E /* TailCorner.swift */; }; + B0147C901F5ED0810035B36E /* MessageDateHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0147C8F1F5ED0810035B36E /* MessageDateHeaderView.swift */; }; + B0147C921F6002150035B36E /* MessageKitDateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0147C911F6002140035B36E /* MessageKitDateFormatter.swift */; }; B015E8191F24623D007EDFB6 /* MessagesCollectionViewLayoutAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015E8181F24623D007EDFB6 /* MessagesCollectionViewLayoutAttributes.swift */; }; B015E81F1F259D8E007EDFB6 /* MessageInputBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015E81E1F259D8E007EDFB6 /* MessageInputBarDelegate.swift */; }; B01E2DD81F5BBDB800E4FA1C /* MessageStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B01E2DD71F5BBDB800E4FA1C /* MessageStyle.swift */; }; @@ -83,7 +84,8 @@ 88916B461CF0DFE600469F91 /* MessageType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageType.swift; sourceTree = ""; }; B01280F21F4E8798004BCD3E /* MessageLabelDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageLabelDelegate.swift; sourceTree = ""; }; B0147C821F5BE9220035B36E /* Bundle+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Bundle+Extensions.swift"; sourceTree = ""; }; - B0147C861F5C129C0035B36E /* TailCorner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TailCorner.swift; sourceTree = ""; }; + B0147C8F1F5ED0810035B36E /* MessageDateHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageDateHeaderView.swift; sourceTree = ""; }; + B0147C911F6002140035B36E /* MessageKitDateFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageKitDateFormatter.swift; sourceTree = ""; }; B015E8181F24623D007EDFB6 /* MessagesCollectionViewLayoutAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagesCollectionViewLayoutAttributes.swift; sourceTree = ""; }; B015E81E1F259D8E007EDFB6 /* MessageInputBarDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageInputBarDelegate.swift; sourceTree = ""; }; B01E2DD71F5BBDB800E4FA1C /* MessageStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageStyle.swift; sourceTree = ""; }; @@ -213,8 +215,8 @@ B0AA1F501F42E91A00BAE583 /* AvatarPosition.swift */, B05530B41F493CFA008BB420 /* DetectorType.swift */, B01E2DD71F5BBDB800E4FA1C /* MessageStyle.swift */, - B0147C861F5C129C0035B36E /* TailCorner.swift */, 38C867981F50EA1000811974 /* NSConstraintLayoutSet.swift */, + B0147C911F6002140035B36E /* MessageKitDateFormatter.swift */, ); name = Models; sourceTree = ""; @@ -232,6 +234,7 @@ B074EE941F35588A00ABB8C8 /* MessageFooterView.swift */, B074EEA71F3971A600ABB8C8 /* MessageLabel.swift */, E8586DB41F59A1C300C9BE9D /* MessageContainerView.swift */, + B0147C8F1F5ED0810035B36E /* MessageDateHeaderView.swift */, ); name = Views; sourceTree = ""; @@ -404,6 +407,7 @@ buildActionMask = 2147483647; files = ( 171D5AB91F36712B0053DF69 /* InputTextView.swift in Sources */, + B0147C901F5ED0810035B36E /* MessageDateHeaderView.swift in Sources */, 38C8679E1F50EA4A00811974 /* InputBarItem.swift in Sources */, B074EE971F355FBC00ABB8C8 /* MessagesLayoutDelegate.swift in Sources */, 38C8679A1F50EA1000811974 /* NSConstraintLayoutSet.swift in Sources */, @@ -413,7 +417,6 @@ E8586DB51F59A1C300C9BE9D /* MessageContainerView.swift in Sources */, B0655A4F1F245C5A00542A83 /* MessagesCollectionViewFlowLayout.swift in Sources */, B0655A2C1F23D81600542A83 /* MessageData.swift in Sources */, - B0147C871F5C129C0035B36E /* TailCorner.swift in Sources */, B09643861F286C9E004D0129 /* String+Extensions.swift in Sources */, B0655A281F23D71400542A83 /* MessageDirection.swift in Sources */, B015E81F1F259D8E007EDFB6 /* MessageInputBarDelegate.swift in Sources */, @@ -423,6 +426,7 @@ B074EE931F35587100ABB8C8 /* MessageHeaderView.swift in Sources */, 376AD1821F4258D80083072A /* TestMessageModel.swift in Sources */, B0655A4D1F244C0600542A83 /* MessageCollectionViewCell.swift in Sources */, + B0147C921F6002150035B36E /* MessageKitDateFormatter.swift in Sources */, B0655A2E1F23D8BC00542A83 /* MessagesCollectionView.swift in Sources */, B0AA1F531F44388C00BAE583 /* NSAttributedString+Extensions.swift in Sources */, B074EE951F35588A00ABB8C8 /* MessageFooterView.swift in Sources */, diff --git a/Sources/MessageDateHeader.swift b/Sources/MessageDateHeaderView.swift similarity index 95% rename from Sources/MessageDateHeader.swift rename to Sources/MessageDateHeaderView.swift index 1455e46a..f0632bc8 100644 --- a/Sources/MessageDateHeader.swift +++ b/Sources/MessageDateHeaderView.swift @@ -24,13 +24,13 @@ import UIKit -open class MessageDateHeader: MessageHeaderView { +open class MessageDateHeaderView: MessageHeaderView { // MARK: - Properties open let dateLabel = UILabel() - // MARK: - Initializer + // MARK: - Initializers override init(frame: CGRect) { super.init(frame: frame) diff --git a/Sources/MessageFooterView.swift b/Sources/MessageFooterView.swift index cff8fe1c..57a26a11 100644 --- a/Sources/MessageFooterView.swift +++ b/Sources/MessageFooterView.swift @@ -26,7 +26,9 @@ import UIKit open class MessageFooterView: UICollectionReusableView { - override init(frame: CGRect) { + // MARK: - Initializers + + public override init(frame: CGRect) { super.init(frame: frame) } diff --git a/Sources/MessageHeaderView.swift b/Sources/MessageHeaderView.swift index c2070517..0a37c18e 100644 --- a/Sources/MessageHeaderView.swift +++ b/Sources/MessageHeaderView.swift @@ -26,6 +26,10 @@ import UIKit open class MessageHeaderView: UICollectionReusableView { + // MARK: - Properties + + static let identifier = "MessageHeaderView" + override init(frame: CGRect) { super.init(frame: frame) } diff --git a/Sources/MessagesCollectionView.swift b/Sources/MessagesCollectionView.swift index f584b925..883ca4e7 100644 --- a/Sources/MessagesCollectionView.swift +++ b/Sources/MessagesCollectionView.swift @@ -64,12 +64,12 @@ open class MessagesCollectionView: UICollectionView { scrollToItem(at: indexPath, at: .bottom, animated: animated) } - open func dequeueMessageHeaderView(withReuseIdentifier identifier: String = "MessageHeader", for indexPath: IndexPath) -> MessageHeaderView { + open func dequeueMessageHeaderView(withReuseIdentifier identifier: String = "MessageHeaderView", for indexPath: IndexPath) -> MessageHeaderView { let header = dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: identifier, for: indexPath) return header as? MessageHeaderView ?? MessageHeaderView() } - open func dequeueMessageFooterView(withReuseIdentifier identifier: String = "MessageFooter", for indexPath: IndexPath) -> MessageFooterView { + open func dequeueMessageFooterView(withReuseIdentifier identifier: String = "MessageFooterView", for indexPath: IndexPath) -> MessageFooterView { let footer = dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionFooter, withReuseIdentifier: identifier, for: indexPath) return footer as? MessageFooterView ?? MessageFooterView() } diff --git a/Sources/MessagesDisplayDataSource.swift b/Sources/MessagesDisplayDataSource.swift index 348b8cee..5b8b2ba0 100644 --- a/Sources/MessagesDisplayDataSource.swift +++ b/Sources/MessagesDisplayDataSource.swift @@ -71,7 +71,7 @@ public extension MessagesDisplayDataSource { } func messageHeaderView(for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageHeaderView? { - let header = messagesCollectionView.dequeueMessageHeaderView(withReuseIdentifier: "MessageDateHeader", for: indexPath) as? MessageDateHeader + let header = messagesCollectionView.dequeueMessageHeaderView(withReuseIdentifier: "MessageDateHeaderView", for: indexPath) as? MessageDateHeaderView header?.dateLabel.text = MessageKitDateFormatter.shared.string(from: message.sentDate) return header } diff --git a/Sources/MessagesViewController.swift b/Sources/MessagesViewController.swift index 4578e97a..73522983 100644 --- a/Sources/MessagesViewController.swift +++ b/Sources/MessagesViewController.swift @@ -57,11 +57,7 @@ open class MessagesViewController: UIViewController { setupSubviews() setupConstraints() - - registerReusableCells() - registerReusableHeaders() - registerReusableFooters() - + registerReusableViews() setupDelegates() } @@ -94,20 +90,21 @@ open class MessagesViewController: UIViewController { messagesCollectionView.dataSource = self } - open func registerReusableCells() { - messagesCollectionView.register(MessageCollectionViewCell.self, forCellWithReuseIdentifier: "MessageCell") - } + private func registerReusableViews() { + messagesCollectionView.register(MessageCollectionViewCell.self, + forCellWithReuseIdentifier: "MessageCell") - open func registerReusableFooters() { messagesCollectionView.register(MessageFooterView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter, - withReuseIdentifier: "MessageFooter") - } + withReuseIdentifier: "MessageFooterView") - open func registerReusableHeaders() { messagesCollectionView.register(MessageHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, - withReuseIdentifier: "MessageHeader") + withReuseIdentifier: "MessageHeaderView") + + messagesCollectionView.register(MessageDateHeaderView.self, + forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, + withReuseIdentifier: "MessageDateHeaderView") } private func setupSubviews() {