diff --git a/.MessageKit.podspec.un~ b/.MessageKit.podspec.un~ new file mode 100644 index 00000000..2e8f446f Binary files /dev/null and b/.MessageKit.podspec.un~ differ diff --git a/CHANGELOG.md b/CHANGELOG.md index c76d8991..6f0395d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,16 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/MessageKit/MessageKit/releases) on GitHub. --------------------------------------- +## 3.0.0 +### Dependency Changes -## Upcoming Release +- **Breaking Change** The dependency `MessageInputBar` was replaced with `InputBarAccessoryView`. As `MessageInputBar` was previously a fork this means no functionality has been lost but improvements and bug fixes will be present. `InputBarAccessoryView` has more of a following outside of `MessageKit` making its development faster than `MessageInputBar`. Maintaining two versions only increased the workload. You can find the changelog for `InputBarAccessoryView` [here](https://github.com/nathantannar4/InputBarAccessoryView/blob/master/CHANGELOG.md). ### Changed +- **Breaking Change** Deprecated the Sender struct in favor of the `SenderType` protocol. [#909](https://github.com/MessageKit/MessageKit/pull/909) by [@nathantannar4](https://github.com/nathantannar4) + - **Breaking Change** Add support for audio messages [#892](https://github.com/MessageKit/MessageKit/pull/892) by [@moldovaniosif](https://github.com/moldovaniosif). Added new protocols `AudioControllerDelegate`, `AudioItem` a new cell `AudioMessageCell` and a new controller `BasicAudioController`. - **Breaking Change** Moved `handleTapGesture` method to `MessageCollectionViewCell` [#950](https://github.com/MessageKit/MessageKit/pull/950) by [@nathantannar4](https://github.com/nathantannar4) @@ -18,6 +21,18 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa ### Added +- Added `AccessoryPosition` class. +[#989](https://github.com/MessageKit/MessageKit/pull/989) by [@subdiox](https://github.com/subdiox) + +- Added `incomingAccessoryViewPosition` and `outgoingAccessoryViewPosition` variables to `MessageSizeCalculator` class. +[#989](https://github.com/MessageKit/MessageKit/pull/989) by [@subdiox](https://github.com/subdiox) + +- Added `setMessageIncomingAccessoryViewPosition(_:)` and `setMessageOutgoingAccessoryViewPosition(_:)` functions to `MessagesCollectionViewFlowLayout` class. +[#989](https://github.com/MessageKit/MessageKit/pull/989) by [@subdiox](https://github.com/subdiox) + +- **Breaking Change** Added `avatarLeadingTrailingPadding` as a property of `CellSizeCalculator` and `MessagesCollectionViewLayoutAttributes` to inset the `AvatarView` layout +[#944](https://github.com/MessageKit/MessageKit/pull/944) by [@nathantannar4](https://github.com/nathantannar4) + - **Breaking Change** Added `didTapBackground(in:)` function to `MessageCellDelegate` protocol. [#922](https://github.com/MessageKit/MessageKit/pull/922) by [@kpennacchia](https://github.com/kpennacchia) @@ -50,6 +65,11 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa ## [2.0.0](https://github.com/MessageKit/MessageKit/releases/tag/2.0.0) +### Added + +- **Breaking Change** Added new methods to simplify using of custom messages: `customCellSizeCalculator(for:at:in:)` for `MessagesLayoutDelegate` and `customCell(for:at:in:)` for `MessagesDataSource`. +[#879](https://github.com/MessageKit/MessageKit/pull/879) by [@realbonus](https://github.com/RealBonus) + ### Changed - Change acl of `handleGesture(touchLocation:)` in `MessageLabel` from internal to open. @@ -78,9 +98,6 @@ The changelog for `MessageKit`. Also see the [releases](https://github.com/Messa - Added `additionalBottomInset` property that allows to adjust the bottom content inset automatically set on the messages collection view by the view controller. [#787](https://github.com/MessageKit/MessageKit/pull/787) by [@andreyvit](https://github.com/andreyvit) -- Added new methods to simplify using of custom messages: `customCellSizeCalculator(for:at:in:)` for `MessagesLayoutDelegate` and `customCell(for:at:in:)` for `MessagesDataSource`. -[#879](https://github.com/MessageKit/MessageKit/pull/879) by [@realbonus](https://github.com/RealBonus) - ### Fixed - **Breaking Change** Fixed typo of `scrollsToBottomOnKeybordBeginsEditing` to `scrollsToBottomOnKeyboardBeginsEditing`. diff --git a/Cartfile b/Cartfile index 00560f59..50814158 100644 --- a/Cartfile +++ b/Cartfile @@ -1 +1 @@ -github "MessageKit/MessageInputBar" "0.4.0" +github "nathantannar4/InputBarAccessoryView" "4.2.1" diff --git a/Cartfile.resolved b/Cartfile.resolved index 6f050b16..c12c3fca 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1,3 +1,3 @@ -github "MessageKit/MessageInputBar" "0.4.0" -github "Quick/Nimble" "v7.3.2" -github "Quick/Quick" "v1.3.2" +github "Quick/Nimble" "v7.3.4" +github "Quick/Quick" "v1.3.4" +github "nathantannar4/InputBarAccessoryView" "4.2.1" diff --git a/Example/.Podfile.un~ b/Example/.Podfile.un~ new file mode 100644 index 00000000..8e635e87 Binary files /dev/null and b/Example/.Podfile.un~ differ diff --git a/Example/ChatExample.xcodeproj/project.pbxproj b/Example/ChatExample.xcodeproj/project.pbxproj index 010c2846..7be14b8c 100644 --- a/Example/ChatExample.xcodeproj/project.pbxproj +++ b/Example/ChatExample.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 383B9EB32172A1C4008AB91A /* MockUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 383B9EB22172A1C4008AB91A /* MockUser.swift */; }; 385C2922211FF32E0010B4BA /* CustomCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 385C2920211FF32E0010B4BA /* CustomCell.swift */; }; 385C2923211FF32E0010B4BA /* TableViewCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 385C2921211FF32E0010B4BA /* TableViewCells.swift */; }; 385C2927211FF33B0010B4BA /* MockSocket.swift in Sources */ = {isa = PBXBuildFile; fileRef = 385C2925211FF33A0010B4BA /* MockSocket.swift */; }; @@ -70,6 +71,7 @@ /* Begin PBXFileReference section */ 0364943D08CDBE656E6F6DF8 /* Pods-ChatExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ChatExampleTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ChatExampleTests/Pods-ChatExampleTests.debug.xcconfig"; sourceTree = ""; }; 2AC6E3F5C11E39F57598DBE6 /* Pods_ChatExampleUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ChatExampleUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 383B9EB22172A1C4008AB91A /* MockUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUser.swift; sourceTree = ""; }; 385C2920211FF32E0010B4BA /* CustomCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomCell.swift; sourceTree = ""; }; 385C2921211FF32E0010B4BA /* TableViewCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewCells.swift; sourceTree = ""; }; 385C2925211FF33A0010B4BA /* MockSocket.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockSocket.swift; sourceTree = ""; }; @@ -152,6 +154,7 @@ children = ( 385C2926211FF33B0010B4BA /* MockMessage.swift */, 385C2925211FF33A0010B4BA /* MockSocket.swift */, + 383B9EB22172A1C4008AB91A /* MockUser.swift */, ); path = Models; sourceTree = ""; @@ -475,12 +478,12 @@ ); inputPaths = ( "${SRCROOT}/Pods/Target Support Files/Pods-ChatExample/Pods-ChatExample-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/MessageInputBar/MessageInputBar.framework", + "${BUILT_PRODUCTS_DIR}/InputBarAccessoryView/InputBarAccessoryView.framework", "${BUILT_PRODUCTS_DIR}/MessageKit/MessageKit.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MessageInputBar.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/InputBarAccessoryView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MessageKit.framework", ); runOnlyForDeploymentPostprocessing = 0; @@ -540,6 +543,7 @@ 385C2945211FF38F0010B4BA /* NavigationController.swift in Sources */, 385C2948211FF38F0010B4BA /* ChatViewController.swift in Sources */, 385C2944211FF38F0010B4BA /* MessageContainerController.swift in Sources */, + 383B9EB32172A1C4008AB91A /* MockUser.swift in Sources */, 385C2943211FF38F0010B4BA /* SettingsViewController.swift in Sources */, 385C2927211FF33B0010B4BA /* MockSocket.swift in Sources */, 385C2947211FF38F0010B4BA /* BasicExampleViewController.swift in Sources */, diff --git a/Example/ChatExample.xcodeproj/xcshareddata/xcschemes/ChatExample.xcscheme b/Example/ChatExample.xcodeproj/xcshareddata/xcschemes/ChatExample.xcscheme index 0fa1ed4f..e34206a1 100644 --- a/Example/ChatExample.xcodeproj/xcshareddata/xcschemes/ChatExample.xcscheme +++ b/Example/ChatExample.xcodeproj/xcshareddata/xcschemes/ChatExample.xcscheme @@ -1,6 +1,6 @@ '../' - pod 'MessageInputBar', :git => 'https://github.com/MessageKit/MessageInputBar.git', :branch => 'master' target 'ChatExampleTests' do inherit! :search_paths diff --git a/Example/Podfile.lock b/Example/Podfile.lock index f272a510..ee6d8c08 100644 --- a/Example/Podfile.lock +++ b/Example/Podfile.lock @@ -1,30 +1,23 @@ PODS: - - MessageInputBar (0.4.1): - - MessageInputBar/Core (= 0.4.1) - - MessageInputBar/Core (0.4.1) - - MessageKit (2.0.0): - - MessageInputBar/Core + - InputBarAccessoryView (4.2.1) + - MessageKit (3.0.0-beta): + - InputBarAccessoryView DEPENDENCIES: - - MessageInputBar (from `https://github.com/MessageKit/MessageInputBar.git`, branch `master`) - MessageKit (from `../`) +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - InputBarAccessoryView + EXTERNAL SOURCES: - MessageInputBar: - :branch: master - :git: https://github.com/MessageKit/MessageInputBar.git MessageKit: :path: "../" -CHECKOUT OPTIONS: - MessageInputBar: - :commit: faebe27f2dd8f39ea145e75b7296ef48133c099a - :git: https://github.com/MessageKit/MessageInputBar.git - SPEC CHECKSUMS: - MessageInputBar: e81c7535347f1f7b923de7080409a535a004b6e4 - MessageKit: e86b06ad2eb2d4ddea3ba29c4d9d13edf78843d1 + InputBarAccessoryView: 37175becdced159cd9ea335f47ae001b1e112909 + MessageKit: 30a1e0b112c44361904016e7add631a78c5128e0 -PODFILE CHECKSUM: 04c1a805e1997e83bacab1a34787e71e9fe4432b +PODFILE CHECKSUM: cecdb7bc8129cf99f66de9f68eea3256fec30c3d COCOAPODS: 1.5.3 diff --git a/Example/Podfile~ b/Example/Podfile~ new file mode 100644 index 00000000..bf44d23b --- /dev/null +++ b/Example/Podfile~ @@ -0,0 +1,16 @@ +platform :ios, '9.0' + +target 'ChatExample' do + use_frameworks! + pod 'MessageKit', :path => '../' + pod 'MessageInputBar', :git => 'https://github.com/MessageKit/MessageInputBar.git', :branch => 'master' + +target 'ChatExampleTests' do + inherit! :search_paths +end + +target 'ChatExampleUITests' do + inherit! :search_paths +end + +end diff --git a/Example/Sources/Data Generation/SampleData.swift b/Example/Sources/Data Generation/SampleData.swift index 67291de4..4d7fc040 100644 --- a/Example/Sources/Data Generation/SampleData.swift +++ b/Example/Sources/Data Generation/SampleData.swift @@ -52,10 +52,10 @@ final internal class SampleData { } } - let system = Sender(id: "000000", displayName: "System") - let nathan = Sender(id: "000001", displayName: "Nathan Tannar") - let steven = Sender(id: "000002", displayName: "Steven Deutsch") - let wu = Sender(id: "000003", displayName: "Wu Zhong") + let system = MockUser(id: "000000", displayName: "System") + let nathan = MockUser(id: "000001", displayName: "Nathan Tannar") + let steven = MockUser(id: "000002", displayName: "Steven Deutsch") + let wu = MockUser(id: "000003", displayName: "Wu Zhong") lazy var senders = [nathan, steven, wu] @@ -68,7 +68,7 @@ final internal class SampleData { MockContactItem(emails: ["test@test.com"]) ] - var currentSender: Sender { + var currentSender: MockUser { return nathan } @@ -159,72 +159,53 @@ final internal class SampleData { } // swiftlint:disable cyclomatic_complexity - func randomMessage(allowedSenders: [Sender]) -> MockMessage { - + func randomMessage(allowedSenders: [MockUser]) -> MockMessage { let randomNumberSender = Int(arc4random_uniform(UInt32(allowedSenders.count))) let uniqueID = NSUUID().uuidString - let sender = allowedSenders[randomNumberSender] + let user = allowedSenders[randomNumberSender] let date = dateAddingRandomTime() switch randomMessageType() { case .Text: let randomSentence = Lorem.sentence() - return MockMessage(text: randomSentence, sender: sender, messageId: uniqueID, date: date) + return MockMessage(text: randomSentence, user: user, messageId: uniqueID, date: date) case .AttributedText: let randomSentence = Lorem.sentence() let attributedText = attributedString(with: randomSentence) - return MockMessage(attributedText: attributedText, sender: senders[randomNumberSender], messageId: uniqueID, date: date) + return MockMessage(attributedText: attributedText, user: user, messageId: uniqueID, date: date) case .Photo: let randomNumberImage = Int(arc4random_uniform(UInt32(messageImages.count))) let image = messageImages[randomNumberImage] - return MockMessage(image: image, sender: sender, messageId: uniqueID, date: date) + return MockMessage(image: image, user: user, messageId: uniqueID, date: date) case .Video: let randomNumberImage = Int(arc4random_uniform(UInt32(messageImages.count))) let image = messageImages[randomNumberImage] - return MockMessage(thumbnail: image, sender: sender, messageId: uniqueID, date: date) + return MockMessage(thumbnail: image, user: user, messageId: uniqueID, date: date) case .Audio: let randomNumberSound = Int(arc4random_uniform(UInt32(sounds.count))) let soundURL = sounds[randomNumberSound] - return MockMessage(audioURL: soundURL, sender: sender, messageId: uniqueID, date: date) + return MockMessage(audioURL: soundURL, user: user, messageId: uniqueID, date: date) case .Emoji: let randomNumberEmoji = Int(arc4random_uniform(UInt32(emojis.count))) - return MockMessage(emoji: emojis[randomNumberEmoji], sender: sender, messageId: uniqueID, date: date) + return MockMessage(emoji: emojis[randomNumberEmoji], user: user, messageId: uniqueID, date: date) case .Location: let randomNumberLocation = Int(arc4random_uniform(UInt32(locations.count))) - return MockMessage(location: locations[randomNumberLocation], sender: sender, messageId: uniqueID, date: date) + return MockMessage(location: locations[randomNumberLocation], user: user, messageId: uniqueID, date: date) case .Url: - return MockMessage(text: "https://github.com/MessageKit", sender: sender, messageId: uniqueID, date: date) + return MockMessage(text: "https://github.com/MessageKit", user: user, messageId: uniqueID, date: date) case .Phone: - return MockMessage(text: "123-456-7890", sender: sender, messageId: uniqueID, date: date) + return MockMessage(text: "123-456-7890", user: user, messageId: uniqueID, date: date) case .Custom: - return MockMessage(custom: "Someone left the conversation", sender: system, messageId: uniqueID, date: date) + return MockMessage(custom: "Someone left the conversation", user: system, messageId: uniqueID, date: date) case .ShareContact: let randomContact = Int(arc4random_uniform(UInt32(contactsToShare.count))) - return MockMessage(contact: contactsToShare[randomContact], sender: sender, messageId: uniqueID, date: date) + return MockMessage(contact: contactsToShare[randomContact], user: user, messageId: uniqueID, date: date) } } // swiftlint:enable cyclomatic_complexity func getMessages(count: Int, completion: ([MockMessage]) -> Void) { -// -// let firstContact = MockContactItem(firstName: "Quite a long name", lastName: "For testing purpose", phoneNumbers: ["0754324"]) -// let secondContact = MockContactItem(firstName: "Steven", lastName: "Deutsch", emails: ["test@test.com"]) -// let thirdContact = MockContactItem(phoneNumbers: ["+40 123 123"]) -// let fourthContact = MockContactItem(emails: ["test@test.com"]) -// -// let contacts = [firstContact, secondContact, thirdContact, fourthContact] -// var messages = [MockMessage]() -// for contact in contacts { -// let randomNumberSender = Int(arc4random_uniform(UInt32(senders.count))) -// let sender = senders[randomNumberSender] -// let date = dateAddingRandomTime() -// let uniqueID = NSUUID().uuidString -// let message = MockMessage(contact: contact, sender: sender, messageId: uniqueID, date: date) -// messages.append(message) -// } -// completion(messages) - var messages: [MockMessage] = [] // Disable Custom Messages UserDefaults.standard.set(false, forKey: "Custom Messages") @@ -245,8 +226,8 @@ final internal class SampleData { } completion(messages) } - - func getMessages(count: Int, allowedSenders: [Sender], completion: ([MockMessage]) -> Void) { + + func getMessages(count: Int, allowedSenders: [MockUser], completion: ([MockMessage]) -> Void) { var messages: [MockMessage] = [] // Disable Custom Messages UserDefaults.standard.set(false, forKey: "Custom Messages") @@ -257,18 +238,18 @@ final internal class SampleData { completion(messages) } - func getAvatarFor(sender: Sender) -> Avatar { + func getAvatarFor(sender: SenderType) -> Avatar { let firstName = sender.displayName.components(separatedBy: " ").first let lastName = sender.displayName.components(separatedBy: " ").first let initials = "\(firstName?.first ?? "A")\(lastName?.first ?? "A")" - switch sender { - case nathan: + switch sender.id { + case "000001": return Avatar(image: #imageLiteral(resourceName: "Nathan-Tannar"), initials: initials) - case steven: + case "000002": return Avatar(image: #imageLiteral(resourceName: "Steven-Deutsch"), initials: initials) - case wu: + case "000003": return Avatar(image: #imageLiteral(resourceName: "Wu-Zhong"), initials: initials) - case system: + case "000000": return Avatar(image: nil, initials: "SS") default: return Avatar(image: nil, initials: initials) diff --git a/Example/Sources/Models/MockMessage.swift b/Example/Sources/Models/MockMessage.swift index dfb53507..b188d20a 100644 --- a/Example/Sources/Models/MockMessage.swift +++ b/Example/Sources/Models/MockMessage.swift @@ -89,54 +89,58 @@ struct MockContactItem: ContactItem { internal struct MockMessage: MessageType { var messageId: String - var sender: Sender + var sender: SenderType { + return user + } var sentDate: Date var kind: MessageKind - private init(kind: MessageKind, sender: Sender, messageId: String, date: Date) { + var user: MockUser + + private init(kind: MessageKind, user: MockUser, messageId: String, date: Date) { self.kind = kind - self.sender = sender + self.user = user self.messageId = messageId self.sentDate = date } - init(custom: Any?, sender: Sender, messageId: String, date: Date) { - self.init(kind: .custom(custom), sender: sender, messageId: messageId, date: date) + init(custom: Any?, user: MockUser, messageId: String, date: Date) { + self.init(kind: .custom(custom), user: user, messageId: messageId, date: date) } - init(text: String, sender: Sender, messageId: String, date: Date) { - self.init(kind: .text(text), sender: sender, messageId: messageId, date: date) + init(text: String, user: MockUser, messageId: String, date: Date) { + self.init(kind: .text(text), user: user, messageId: messageId, date: date) } - init(attributedText: NSAttributedString, sender: Sender, messageId: String, date: Date) { - self.init(kind: .attributedText(attributedText), sender: sender, messageId: messageId, date: date) + init(attributedText: NSAttributedString, user: MockUser, messageId: String, date: Date) { + self.init(kind: .attributedText(attributedText), user: user, messageId: messageId, date: date) } - init(image: UIImage, sender: Sender, messageId: String, date: Date) { + init(image: UIImage, user: MockUser, messageId: String, date: Date) { let mediaItem = ImageMediaItem(image: image) - self.init(kind: .photo(mediaItem), sender: sender, messageId: messageId, date: date) + self.init(kind: .photo(mediaItem), user: user, messageId: messageId, date: date) } - init(thumbnail: UIImage, sender: Sender, messageId: String, date: Date) { + init(thumbnail: UIImage, user: MockUser, messageId: String, date: Date) { let mediaItem = ImageMediaItem(image: thumbnail) - self.init(kind: .video(mediaItem), sender: sender, messageId: messageId, date: date) + self.init(kind: .video(mediaItem), user: user, messageId: messageId, date: date) } - init(location: CLLocation, sender: Sender, messageId: String, date: Date) { + init(location: CLLocation, user: MockUser, messageId: String, date: Date) { let locationItem = CoordinateItem(location: location) - self.init(kind: .location(locationItem), sender: sender, messageId: messageId, date: date) + self.init(kind: .location(locationItem), user: user, messageId: messageId, date: date) } - init(emoji: String, sender: Sender, messageId: String, date: Date) { - self.init(kind: .emoji(emoji), sender: sender, messageId: messageId, date: date) + init(emoji: String, user: MockUser, messageId: String, date: Date) { + self.init(kind: .emoji(emoji), user: user, messageId: messageId, date: date) } - init(audioURL: URL, sender: Sender, messageId: String, date: Date) { + init(audioURL: URL, user: MockUser, messageId: String, date: Date) { let audioItem = MockAudiotem(url: audioURL) - self.init(kind: .audio(audioItem), sender: sender, messageId: messageId, date: date) + self.init(kind: .audio(audioItem), user: user, messageId: messageId, date: date) } - init(contact: MockContactItem, sender: Sender, messageId: String, date: Date) { - self.init(kind: .contact(contact), sender: sender, messageId: messageId, date: date) + init(contact: MockContactItem, user: MockUser, messageId: String, date: Date) { + self.init(kind: .contact(contact), user: user, messageId: messageId, date: date) } } diff --git a/Example/Sources/Models/MockSocket.swift b/Example/Sources/Models/MockSocket.swift index 0585d9dc..c3bc2996 100644 --- a/Example/Sources/Models/MockSocket.swift +++ b/Example/Sources/Models/MockSocket.swift @@ -37,12 +37,12 @@ final class MockSocket { private var onTypingStatusCode: (() -> Void)? - private var connectedUsers: [Sender] = [] + private var connectedUsers: [MockUser] = [] private init() {} @discardableResult - func connect(with senders: [Sender]) -> Self { + func connect(with senders: [MockUser]) -> Self { disconnect() connectedUsers = senders timer = Timer.scheduledTimer(timeInterval: 2.5, target: self, selector: #selector(handleTimer), userInfo: nil, repeats: true) diff --git a/Example/Sources/Models/MockUser.swift b/Example/Sources/Models/MockUser.swift new file mode 100644 index 00000000..de17c097 --- /dev/null +++ b/Example/Sources/Models/MockUser.swift @@ -0,0 +1,31 @@ +/* + MIT License + + Copyright (c) 2017-2018 MessageKit + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import Foundation +import MessageKit + +struct MockUser: SenderType, Equatable { + var id: String + var displayName: String +} diff --git a/Example/Sources/View Controllers/AdvancedExampleViewController.swift b/Example/Sources/View Controllers/AdvancedExampleViewController.swift index b8d1c4fd..d9274957 100644 --- a/Example/Sources/View Controllers/AdvancedExampleViewController.swift +++ b/Example/Sources/View Controllers/AdvancedExampleViewController.swift @@ -25,7 +25,7 @@ import UIKit import MapKit import MessageKit -import MessageInputBar +import InputBarAccessoryView final class AdvancedExampleViewController: ChatViewController { @@ -100,9 +100,11 @@ final class AdvancedExampleViewController: ChatViewController { layout?.setMessageIncomingAccessoryViewSize(CGSize(width: 30, height: 30)) layout?.setMessageIncomingAccessoryViewPadding(HorizontalEdgeInsets(left: 8, right: 0)) + layout?.setMessageIncomingAccessoryViewPosition(.messageBottom) layout?.setMessageOutgoingAccessoryViewSize(CGSize(width: 30, height: 30)) layout?.setMessageOutgoingAccessoryViewPadding(HorizontalEdgeInsets(left: 0, right: 8)) - + layout?.setMessageOutgoingAccessoryViewPosition(.messageBottom) + messagesCollectionView.messagesLayoutDelegate = self messagesCollectionView.messagesDisplayDelegate = self } @@ -133,7 +135,7 @@ final class AdvancedExampleViewController: ChatViewController { messageInputBar.sendButton.image = #imageLiteral(resourceName: "ic_up") messageInputBar.sendButton.title = nil messageInputBar.sendButton.imageView?.layer.cornerRadius = 16 - messageInputBar.textViewPadding.right = -38 + messageInputBar.middleContentViewPadding.right = -38 let charCountButton = InputBarButtonItem() .configure { $0.title = "0/140" @@ -144,15 +146,15 @@ final class AdvancedExampleViewController: ChatViewController { }.onTextViewDidChange { (item, textView) in item.title = "\(textView.text.count)/140" let isOverLimit = textView.text.count > 140 - item.messageInputBar?.shouldManageSendButtonEnabledState = !isOverLimit // Disable automated management when over limit + item.inputBarAccessoryView?.shouldManageSendButtonEnabledState = !isOverLimit // Disable automated management when over limit if isOverLimit { - item.messageInputBar?.sendButton.isEnabled = false + item.inputBarAccessoryView?.sendButton.isEnabled = false } let color = isOverLimit ? .red : UIColor(white: 0.6, alpha: 1) item.setTitleColor(color, for: .normal) } let bottomItems = [makeButton(named: "ic_at"), makeButton(named: "ic_hashtag"), makeButton(named: "ic_library"), .flexibleSpace, charCountButton] - messageInputBar.textViewPadding.bottom = 8 + messageInputBar.middleContentViewPadding.bottom = 8 messageInputBar.setStackViewItems(bottomItems, forStack: .bottom, animated: false) // This just adds some more flare @@ -176,12 +178,12 @@ final class AdvancedExampleViewController: ChatViewController { func isPreviousMessageSameSender(at indexPath: IndexPath) -> Bool { guard indexPath.section - 1 >= 0 else { return false } - return messageList[indexPath.section].sender == messageList[indexPath.section - 1].sender + return messageList[indexPath.section].user == messageList[indexPath.section - 1].user } func isNextMessageSameSender(at indexPath: IndexPath) -> Bool { guard indexPath.section + 1 < messageList.count else { return false } - return messageList[indexPath.section].sender == messageList[indexPath.section + 1].sender + return messageList[indexPath.section].user == messageList[indexPath.section + 1].user } func setTypingIndicatorHidden(_ isHidden: Bool, performUpdates updates: (() -> Void)? = nil) { @@ -205,8 +207,16 @@ final class AdvancedExampleViewController: ChatViewController { $0.tintColor = .primaryColor }.onDeselected { $0.tintColor = UIColor(white: 0.8, alpha: 1) - }.onTouchUpInside { _ in + }.onTouchUpInside { print("Item Tapped") + let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) + let action = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) + actionSheet.addAction(action) + if let popoverPresentationController = actionSheet.popoverPresentationController { + popoverPresentationController.sourceView = $0 + popoverPresentationController.sourceRect = $0.frame + } + self.navigationController?.present(actionSheet, animated: true, completion: nil) } } @@ -326,7 +336,8 @@ extension AdvancedExampleViewController: MessagesDisplayDelegate { func configureAccessoryView(_ accessoryView: UIView, for message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) { // Cells are reused, so only add a button here once. For real use you would need to // ensure any subviews are removed if not needed - guard accessoryView.subviews.isEmpty else { return } + accessoryView.subviews.forEach { $0.removeFromSuperview() } + let button = UIButton(type: .infoLight) button.tintColor = .primaryColor accessoryView.addSubview(button) diff --git a/Example/Sources/View Controllers/BasicExampleViewController.swift b/Example/Sources/View Controllers/BasicExampleViewController.swift index b418d97f..d4445831 100644 --- a/Example/Sources/View Controllers/BasicExampleViewController.swift +++ b/Example/Sources/View Controllers/BasicExampleViewController.swift @@ -25,7 +25,6 @@ import UIKit import MapKit import MessageKit -import MessageInputBar final class BasicExampleViewController: ChatViewController { diff --git a/Example/Sources/View Controllers/ChatViewController.swift b/Example/Sources/View Controllers/ChatViewController.swift index af107d10..7975afa1 100644 --- a/Example/Sources/View Controllers/ChatViewController.swift +++ b/Example/Sources/View Controllers/ChatViewController.swift @@ -24,7 +24,7 @@ SOFTWARE. import UIKit import MessageKit -import MessageInputBar +import InputBarAccessoryView /// A base class for the example controllers class ChatViewController: MessagesViewController, MessagesDataSource { @@ -111,7 +111,7 @@ class ChatViewController: MessagesViewController, MessagesDataSource { func configureMessageInputBar() { messageInputBar.delegate = self messageInputBar.inputTextView.tintColor = .primaryColor - messageInputBar.sendButton.tintColor = .primaryColor + messageInputBar.sendButton.setTitleColor(.primaryColor, for: .normal) } // MARK: - Helpers @@ -142,7 +142,7 @@ class ChatViewController: MessagesViewController, MessagesDataSource { // MARK: - MessagesDataSource - func currentSender() -> Sender { + func currentSender() -> SenderType { return SampleData.shared.currentSender } @@ -278,23 +278,23 @@ extension ChatViewController: MessageLabelDelegate { // MARK: - MessageInputBarDelegate -extension ChatViewController: MessageInputBarDelegate { - - func messageInputBar(_ inputBar: MessageInputBar, didPressSendButtonWith text: String) { - +extension ChatViewController: InputBarAccessoryViewDelegate { + + func inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith text: String) { + for component in inputBar.inputTextView.components { - + + let user = SampleData.shared.currentSender if let str = component as? String { - let message = MockMessage(text: str, sender: currentSender(), messageId: UUID().uuidString, date: Date()) + let message = MockMessage(text: str, user: user, messageId: UUID().uuidString, date: Date()) insertMessage(message) } else if let img = component as? UIImage { - let message = MockMessage(image: img, sender: currentSender(), messageId: UUID().uuidString, date: Date()) + let message = MockMessage(image: img, user: user, messageId: UUID().uuidString, date: Date()) insertMessage(message) } - + } inputBar.inputTextView.text = String() messagesCollectionView.scrollToBottom(animated: true) } - } diff --git a/Example/Sources/View Controllers/LaunchViewController.swift b/Example/Sources/View Controllers/LaunchViewController.swift index 8340af1a..109db593 100644 --- a/Example/Sources/View Controllers/LaunchViewController.swift +++ b/Example/Sources/View Controllers/LaunchViewController.swift @@ -24,7 +24,6 @@ import UIKit import MessageKit -import MessageInputBar import SafariServices final internal class LaunchViewController: UITableViewController { diff --git a/Example/Sources/View Controllers/SettingsViewController.swift b/Example/Sources/View Controllers/SettingsViewController.swift index 1830eb15..302d105c 100644 --- a/Example/Sources/View Controllers/SettingsViewController.swift +++ b/Example/Sources/View Controllers/SettingsViewController.swift @@ -24,7 +24,6 @@ import UIKit import MessageKit -import MessageInputBar final internal class SettingsViewController: UITableViewController { diff --git a/MessageKit.podspec b/MessageKit.podspec index 0d2e1b65..77b38f0c 100644 --- a/MessageKit.podspec +++ b/MessageKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'MessageKit' - s.version = '2.0.0' + s.version = '3.0.0-beta' s.license = { :type => "MIT", :file => "LICENSE.md" } s.summary = 'An elegant messages UI library for iOS.' @@ -12,14 +12,16 @@ Pod::Spec.new do |s| s.source_files = 'Sources/**/*.swift' s.pod_target_xcconfig = { - "SWIFT_VERSION" => "4.0", + "SWIFT_VERSION" => "4.2", } + s.swift_version = '4.2' + s.ios.deployment_target = '9.0' s.ios.resource_bundle = { 'MessageKitAssets' => 'Assets/MessageKitAssets.bundle/Images' } s.requires_arc = true - s.dependency 'MessageInputBar/Core' + s.dependency 'InputBarAccessoryView' end diff --git a/MessageKit.podspec~ b/MessageKit.podspec~ new file mode 100644 index 00000000..4a4007e6 --- /dev/null +++ b/MessageKit.podspec~ @@ -0,0 +1,27 @@ +Pod::Spec.new do |s| + s.name = 'MessageKit' + s.version = '3.0.0' + s.license = { :type => "MIT", :file => "LICENSE.md" } + + s.summary = 'An elegant messages UI library for iOS.' + s.homepage = 'https://github.com/MessageKit/MessageKit' + s.social_media_url = 'https://twitter.com/_SD10_' + s.author = { "Steven Deutsch" => "stevensdeutsch@yahoo.com" } + + s.source = { :git => 'https://github.com/MessageKit/MessageKit.git', :tag => s.version } + s.source_files = 'Sources/**/*.swift' + + s.pod_target_xcconfig = { + "SWIFT_VERSION" => "4.2", + } + + s.swift_version = '4.2' + + s.ios.deployment_target = '9.0' + s.ios.resource_bundle = { 'MessageKitAssets' => 'Assets/MessageKitAssets.bundle/Images' } + + s.requires_arc = true + + s.dependency 'InputBarAccessoryView' + +end diff --git a/MessageKit.xcodeproj/project.pbxproj b/MessageKit.xcodeproj/project.pbxproj index 0579ea9c..6ed27369 100644 --- a/MessageKit.xcodeproj/project.pbxproj +++ b/MessageKit.xcodeproj/project.pbxproj @@ -35,7 +35,12 @@ 1FF377AA20087D78004FD648 /* MessagesViewController+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FF377A920087D78004FD648 /* MessagesViewController+Menu.swift */; }; 1FF377AC20087DA2004FD648 /* MessagesViewController+Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FF377AB20087DA2004FD648 /* MessagesViewController+Keyboard.swift */; }; 382C794221705D2000F4FAF5 /* HorizontalEdgeInsets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 382C794121705D2000F4FAF5 /* HorizontalEdgeInsets.swift */; }; - 38C2AE7C20D4878D00F8079E /* MessageInputBar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38C2AE7B20D4878D00F8079E /* MessageInputBar.framework */; }; + 4C508649221C0BBA0043943C /* AccessoryPosition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C508648221C0BBA0043943C /* AccessoryPosition.swift */; }; + 383B9EB121728BAD008AB91A /* SenderType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 383B9EB021728BAD008AB91A /* SenderType.swift */; }; + 38A2230F221FB8A300D14DAF /* MessageInputBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38A2230E221FB8A300D14DAF /* MessageInputBar.swift */; }; + 38A223112223493500D14DAF /* InputBarAccessoryView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38A223102223493400D14DAF /* InputBarAccessoryView.framework */; }; + 38C2AE7C20D4878D00F8079E /* MessageInputBar.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 38C2AE7B20D4878D00F8079E /* MessageInputBar.framework */; }; + 38F8062F2173CD8F00CDB9DB /* MockUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38F8062D2173CD4300CDB9DB /* MockUser.swift */; }; 5073C1152175BE750040EAD5 /* AudioItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5073C1142175BE750040EAD5 /* AudioItem.swift */; }; 5073C1192175BE960040EAD5 /* AudioMessageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5073C1182175BE950040EAD5 /* AudioMessageCell.swift */; }; 5073C11D2175BEC60040EAD5 /* AudioMessageSizeCalculator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5073C11C2175BEC60040EAD5 /* AudioMessageSizeCalculator.swift */; }; @@ -134,7 +139,12 @@ 1FF377A920087D78004FD648 /* MessagesViewController+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessagesViewController+Menu.swift"; sourceTree = ""; }; 1FF377AB20087DA2004FD648 /* MessagesViewController+Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MessagesViewController+Keyboard.swift"; sourceTree = ""; }; 382C794121705D2000F4FAF5 /* HorizontalEdgeInsets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HorizontalEdgeInsets.swift; sourceTree = ""; }; + 383B9EB021728BAD008AB91A /* SenderType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SenderType.swift; sourceTree = ""; }; + 38A2230E221FB8A300D14DAF /* MessageInputBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageInputBar.swift; sourceTree = ""; }; + 38A223102223493400D14DAF /* InputBarAccessoryView.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = InputBarAccessoryView.framework; path = Carthage/Build/iOS/InputBarAccessoryView.framework; sourceTree = ""; }; 38C2AE7B20D4878D00F8079E /* MessageInputBar.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageInputBar.framework; path = Carthage/Build/iOS/MessageInputBar.framework; sourceTree = ""; }; + 4C508648221C0BBA0043943C /* AccessoryPosition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessoryPosition.swift; sourceTree = ""; }; + 38F8062D2173CD4300CDB9DB /* MockUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockUser.swift; sourceTree = ""; }; 5073C1142175BE750040EAD5 /* AudioItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioItem.swift; sourceTree = ""; }; 5073C1182175BE950040EAD5 /* AudioMessageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioMessageCell.swift; sourceTree = ""; }; 5073C11C2175BEC60040EAD5 /* AudioMessageSizeCalculator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AudioMessageSizeCalculator.swift; sourceTree = ""; }; @@ -193,7 +203,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 38C2AE7C20D4878D00F8079E /* MessageInputBar.framework in Frameworks */, + 38A223112223493500D14DAF /* InputBarAccessoryView.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -213,6 +223,7 @@ 1F7FC8C21FD26F22006CC979 /* Frameworks */ = { isa = PBXGroup; children = ( + 38A223102223493400D14DAF /* InputBarAccessoryView.framework */, 38C2AE7B20D4878D00F8079E /* MessageInputBar.framework */, 1F7FC8C71FD26F49006CC979 /* Nimble.framework */, 1F7FC8C51FD26F33006CC979 /* Quick.framework */, @@ -316,6 +327,7 @@ children = ( 8962AC7B1F87AB230030B058 /* MockMessage.swift */, 8962AC7A1F87AB230030B058 /* MockMessagesDataSource.swift */, + 38F8062D2173CD4300CDB9DB /* MockUser.swift */, ); path = Mocks; sourceTree = ""; @@ -381,6 +393,7 @@ B09643991F295D58004D0129 /* Models */ = { isa = PBXGroup; children = ( + 4C508648221C0BBA0043943C /* AccessoryPosition.swift */, B7A03F1C1F866895006AEF79 /* Avatar.swift */, 1F82D1421FB1B75B00B81A88 /* AvatarPosition.swift */, B7A03F211F866895006AEF79 /* DetectorType.swift */, @@ -421,6 +434,7 @@ B7A03F561F8669C9006AEF79 /* MessagesDisplayDelegate.swift */, B7A03F541F8669C9006AEF79 /* MessagesLayoutDelegate.swift */, B7A03F511F8669C9006AEF79 /* MessageType.swift */, + 383B9EB021728BAD008AB91A /* SenderType.swift */, 1FD5895F2064E08A004B5081 /* MediaItem.swift */, 1FD5896320660C1C004B5081 /* LocationItem.swift */, 5073C1142175BE750040EAD5 /* AudioItem.swift */, @@ -459,6 +473,7 @@ B7A03F711F866A06006AEF79 /* Info.plist */, B7A03F721F866A06006AEF79 /* MessageKit.h */, B7A03F701F866A06006AEF79 /* MessageKit+Availability.swift */, + 38A2230E221FB8A300D14DAF /* MessageInputBar.swift */, ); path = Supporting; sourceTree = ""; @@ -605,8 +620,10 @@ B7A03F4B1F86694F006AEF79 /* MessageContainerView.swift in Sources */, B7A03F281F866895006AEF79 /* LocationMessageSnapshotOptions.swift in Sources */, B7A03F6C1F8669EB006AEF79 /* UIView+Extensions.swift in Sources */, + 383B9EB121728BAD008AB91A /* SenderType.swift in Sources */, B7A03F3A1F866946006AEF79 /* TextMessageCell.swift in Sources */, B7A03F191F86682C006AEF79 /* MessagesCollectionViewLayoutAttributes.swift in Sources */, + 38A2230F221FB8A300D14DAF /* MessageInputBar.swift in Sources */, B7A03F461F86694F006AEF79 /* AvatarView.swift in Sources */, 1FCA6D30201C1CC900BC3480 /* UIEdgeInsets+Extensions.swift in Sources */, B7A03F3D1F866946006AEF79 /* MediaMessageCell.swift in Sources */, @@ -614,6 +631,7 @@ B7A03F2E1F866895006AEF79 /* MessageKind.swift in Sources */, B7A03F7B1F866B85006AEF79 /* MessageCollectionViewCell.swift in Sources */, B7A03F6B1F8669EB006AEF79 /* UIColor+Extensions.swift in Sources */, + 4C508649221C0BBA0043943C /* AccessoryPosition.swift in Sources */, B7A03F5E1F8669CA006AEF79 /* MessagesLayoutDelegate.swift in Sources */, B7A03F261F866895006AEF79 /* MessageKitDateFormatter.swift in Sources */, B7A03F6D1F8669EB006AEF79 /* Bundle+Extensions.swift in Sources */, @@ -661,6 +679,7 @@ 1F066E131FD90BB600E11013 /* MessagesViewControllerSpec.swift in Sources */, 1F066E1D1FDA3C1700E11013 /* SenderSpec.swift in Sources */, 8962AC8A1F87AB7D0030B058 /* MessagesCollectionViewTests.swift in Sources */, + 38F8062F2173CD8F00CDB9DB /* MockUser.swift in Sources */, 8962AC8D1F87AB7D0030B058 /* MessageCollectionViewCellTests.swift in Sources */, 8962AC991F87AB860030B058 /* MessagesDisplayDelegateTests.swift in Sources */, 1FD589622064E1B9004B5081 /* MockMessage.swift in Sources */, diff --git a/README.md b/README.md index 55b22a7b..491730b6 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,13 @@ To integrate MessageKit using Carthage, add the following to your `Cartfile`: github "MessageKit/MessageKit" ```` +## Getting Started + +Please have a look at the [Quick Start guide](https://github.com/MessageKit/MessageKit/blob/master/Documentation/QuickStart.md), the [FAQs](https://github.com/MessageKit/MessageKit/blob/master/Documentation/FAQs.md) and the [MessageInputBar docs](https://github.com/MessageKit/MessageKit/blob/master/Documentation/MessageInputBar.md). + +If you have any issues have a look at the [Example](https://github.com/MessageKit/MessageKit/tree/master/Example) project or write a question with the "messagekit" tag on [Stack Overflow](https://stackoverflow.com/questions/tagged/messagekit). + + ## Requirements - **iOS9** or later diff --git a/Sources/Controllers/MessagesViewController+Keyboard.swift b/Sources/Controllers/MessagesViewController+Keyboard.swift index 881b6aaa..5a3777a1 100644 --- a/Sources/Controllers/MessagesViewController+Keyboard.swift +++ b/Sources/Controllers/MessagesViewController+Keyboard.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,7 @@ */ import Foundation -import MessageInputBar +import InputBarAccessoryView extension MessagesViewController { @@ -56,7 +56,7 @@ extension MessagesViewController { guard !isMessagesControllerBeingDismissed else { return } guard let keyboardStartFrameInScreenCoords = notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? CGRect else { return } - guard !keyboardStartFrameInScreenCoords.isEmpty else { + guard !keyboardStartFrameInScreenCoords.isEmpty || UIDevice.current.userInterfaceIdiom != .pad else { // WORKAROUND for what seems to be a bug in iPad's keyboard handling in iOS 11: we receive an extra spurious frame change // notification when undocking the keyboard, with a zero starting frame and an incorrect end frame. The workaround is to // ignore this notification. diff --git a/Sources/Controllers/MessagesViewController+Menu.swift b/Sources/Controllers/MessagesViewController+Menu.swift index 49c87315..fc1cb5a2 100644 --- a/Sources/Controllers/MessagesViewController+Menu.swift +++ b/Sources/Controllers/MessagesViewController+Menu.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,6 @@ */ import Foundation -import MessageInputBar extension MessagesViewController { diff --git a/Sources/Controllers/MessagesViewController.swift b/Sources/Controllers/MessagesViewController.swift index 9b0e1247..b022aaf9 100644 --- a/Sources/Controllers/MessagesViewController.swift +++ b/Sources/Controllers/MessagesViewController.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,6 @@ */ import UIKit -import MessageInputBar /// A subclass of `UIViewController` with a `MessagesCollectionView` object /// that is used to display conversation interfaces. @@ -71,12 +70,12 @@ UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { } } + public var selectedIndexPathForMenu: IndexPath? + private var isFirstLayout: Bool = true internal var isMessagesControllerBeingDismissed: Bool = false - internal var selectedIndexPathForMenu: IndexPath? - internal var messageCollectionViewBottomInset: CGFloat = 0 { didSet { messagesCollectionView.contentInset.bottom = messageCollectionViewBottomInset @@ -121,6 +120,13 @@ UICollectionViewDelegateFlowLayout, UICollectionViewDataSource { adjustScrollViewTopInset() } + open override func viewSafeAreaInsetsDidChange() { + if #available(iOS 11.0, *) { + super.viewSafeAreaInsetsDidChange() + } + messageCollectionViewBottomInset = requiredInitialScrollViewBottomInset() + } + // MARK: - Initializers deinit { diff --git a/Sources/Extensions/Bundle+Extensions.swift b/Sources/Extensions/Bundle+Extensions.swift index 0cda64b9..17dda2e8 100644 --- a/Sources/Extensions/Bundle+Extensions.swift +++ b/Sources/Extensions/Bundle+Extensions.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Extensions/CGRect+Extensions.swift b/Sources/Extensions/CGRect+Extensions.swift index 1a1177b5..17e4347e 100644 --- a/Sources/Extensions/CGRect+Extensions.swift +++ b/Sources/Extensions/CGRect+Extensions.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Extensions/NSAttributedString+Extensions.swift b/Sources/Extensions/NSAttributedString+Extensions.swift index a6a8f749..430a64c5 100644 --- a/Sources/Extensions/NSAttributedString+Extensions.swift +++ b/Sources/Extensions/NSAttributedString+Extensions.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Extensions/UIColor+Extensions.swift b/Sources/Extensions/UIColor+Extensions.swift index 79c4f4fc..02f5819c 100644 --- a/Sources/Extensions/UIColor+Extensions.swift +++ b/Sources/Extensions/UIColor+Extensions.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Extensions/UIEdgeInsets+Extensions.swift b/Sources/Extensions/UIEdgeInsets+Extensions.swift index 4d99e081..8e259f56 100644 --- a/Sources/Extensions/UIEdgeInsets+Extensions.swift +++ b/Sources/Extensions/UIEdgeInsets+Extensions.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Extensions/UIView+Extensions.swift b/Sources/Extensions/UIView+Extensions.swift index 81df7c35..8eb50bbf 100644 --- a/Sources/Extensions/UIView+Extensions.swift +++ b/Sources/Extensions/UIView+Extensions.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Layout/AudioMessageSizeCalculator.swift b/Sources/Layout/AudioMessageSizeCalculator.swift index 7fe646ed..93700ede 100644 --- a/Sources/Layout/AudioMessageSizeCalculator.swift +++ b/Sources/Layout/AudioMessageSizeCalculator.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Layout/CellSizeCalculator.swift b/Sources/Layout/CellSizeCalculator.swift index 7037b571..3bff16cb 100644 --- a/Sources/Layout/CellSizeCalculator.swift +++ b/Sources/Layout/CellSizeCalculator.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Layout/LocationMessageSizeCalculator.swift b/Sources/Layout/LocationMessageSizeCalculator.swift index 0efc0260..031281d4 100644 --- a/Sources/Layout/LocationMessageSizeCalculator.swift +++ b/Sources/Layout/LocationMessageSizeCalculator.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Layout/MediaMessageSizeCalculator.swift b/Sources/Layout/MediaMessageSizeCalculator.swift index 020bbd62..b7cff3d2 100644 --- a/Sources/Layout/MediaMessageSizeCalculator.swift +++ b/Sources/Layout/MediaMessageSizeCalculator.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Layout/MessageSizeCalculator.swift b/Sources/Layout/MessageSizeCalculator.swift index 504a6719..4cca7e1c 100644 --- a/Sources/Layout/MessageSizeCalculator.swift +++ b/Sources/Layout/MessageSizeCalculator.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -38,6 +38,8 @@ open class MessageSizeCalculator: CellSizeCalculator { public var incomingAvatarPosition = AvatarPosition(vertical: .cellBottom) public var outgoingAvatarPosition = AvatarPosition(vertical: .cellBottom) + public var avatarLeadingTrailingPadding: CGFloat = 0 + public var incomingMessagePadding = UIEdgeInsets(top: 0, left: 4, bottom: 0, right: 30) public var outgoingMessagePadding = UIEdgeInsets(top: 0, left: 30, bottom: 0, right: 4) @@ -58,6 +60,9 @@ open class MessageSizeCalculator: CellSizeCalculator { public var incomingAccessoryViewPadding = HorizontalEdgeInsets.zero public var outgoingAccessoryViewPadding = HorizontalEdgeInsets.zero + + public var incomingAccessoryViewPosition: AccessoryPosition = .messageCenter + public var outgoingAccessoryViewPosition: AccessoryPosition = .messageCenter open override func configure(attributes: UICollectionViewLayoutAttributes) { guard let attributes = attributes as? MessagesCollectionViewLayoutAttributes else { return } @@ -68,6 +73,7 @@ open class MessageSizeCalculator: CellSizeCalculator { attributes.avatarSize = avatarSize(for: message) attributes.avatarPosition = avatarPosition(for: message) + attributes.avatarLeadingTrailingPadding = avatarLeadingTrailingPadding attributes.messageContainerPadding = messageContainerPadding(for: message) attributes.messageContainerSize = messageContainerSize(for: message) @@ -82,6 +88,7 @@ open class MessageSizeCalculator: CellSizeCalculator { attributes.accessoryViewSize = accessoryViewSize(for: message) attributes.accessoryViewPadding = accessoryViewPadding(for: message) + attributes.accessoryViewPosition = accessoryViewPosition(for: message) } open override func sizeForItem(at indexPath: IndexPath) -> CGSize { @@ -232,6 +239,12 @@ open class MessageSizeCalculator: CellSizeCalculator { let isFromCurrentSender = dataSource.isFromCurrentSender(message: message) return isFromCurrentSender ? outgoingAccessoryViewPadding : incomingAccessoryViewPadding } + + public func accessoryViewPosition(for message: MessageType) -> AccessoryPosition { + let dataSource = messagesLayout.messagesDataSource + let isFromCurrentSender = dataSource.isFromCurrentSender(message: message) + return isFromCurrentSender ? outgoingAccessoryViewPosition : incomingAccessoryViewPosition + } // MARK: - MessageContainer @@ -251,7 +264,7 @@ open class MessageSizeCalculator: CellSizeCalculator { let messagePadding = messageContainerPadding(for: message) let accessoryWidth = accessoryViewSize(for: message).width let accessoryPadding = accessoryViewPadding(for: message) - return messagesLayout.itemWidth - avatarWidth - messagePadding.horizontal - accessoryWidth - accessoryPadding.horizontal + return messagesLayout.itemWidth - avatarWidth - messagePadding.horizontal - accessoryWidth - accessoryPadding.horizontal - avatarLeadingTrailingPadding } // MARK: - Helpers diff --git a/Sources/Layout/MessagesCollectionViewFlowLayout.swift b/Sources/Layout/MessagesCollectionViewFlowLayout.swift index e73a5c6d..a7d60456 100644 --- a/Sources/Layout/MessagesCollectionViewFlowLayout.swift +++ b/Sources/Layout/MessagesCollectionViewFlowLayout.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -199,6 +199,11 @@ open class MessagesCollectionViewFlowLayout: UICollectionViewFlowLayout { public func setMessageOutgoingAvatarPosition(_ newPosition: AvatarPosition) { messageSizeCalculators().forEach { $0.outgoingAvatarPosition = newPosition } } + + /// Set `avatarLeadingTrailingPadding` of all `MessageSizeCalculator`s + public func setAvatarLeadingTrailingPadding(_ newPadding: CGFloat) { + messageSizeCalculators().forEach { $0.avatarLeadingTrailingPadding = newPadding } + } /// Set `incomingMessagePadding` of all `MessageSizeCalculator`s public func setMessageIncomingMessagePadding(_ newPadding: UIEdgeInsets) { @@ -255,20 +260,30 @@ open class MessagesCollectionViewFlowLayout: UICollectionViewFlowLayout { messageSizeCalculators().forEach { $0.incomingAccessoryViewSize = newSize } } - /// Set `outgoingAvatarSize` of all `MessageSizeCalculator`s + /// Set `outgoingAccessoryViewSize` of all `MessageSizeCalculator`s public func setMessageOutgoingAccessoryViewSize(_ newSize: CGSize) { messageSizeCalculators().forEach { $0.outgoingAccessoryViewSize = newSize } } - /// Set `incomingAccessoryViewSize` of all `MessageSizeCalculator`s + /// Set `incomingAccessoryViewPadding` of all `MessageSizeCalculator`s public func setMessageIncomingAccessoryViewPadding(_ newPadding: HorizontalEdgeInsets) { messageSizeCalculators().forEach { $0.incomingAccessoryViewPadding = newPadding } } - /// Set `outgoingAvatarSize` of all `MessageSizeCalculator`s + /// Set `outgoingAccessoryViewPadding` of all `MessageSizeCalculator`s public func setMessageOutgoingAccessoryViewPadding(_ newPadding: HorizontalEdgeInsets) { messageSizeCalculators().forEach { $0.outgoingAccessoryViewPadding = newPadding } } + + /// Set `incomingAccessoryViewPosition` of all `MessageSizeCalculator`s + public func setMessageIncomingAccessoryViewPosition(_ newPosition: AccessoryPosition) { + messageSizeCalculators().forEach { $0.incomingAccessoryViewPosition = newPosition } + } + + /// Set `outgoingAccessoryViewPosition` of all `MessageSizeCalculator`s + public func setMessageOutgoingAccessoryViewPosition(_ newPosition: AccessoryPosition) { + messageSizeCalculators().forEach { $0.outgoingAccessoryViewPosition = newPosition } + } /// Get all `MessageSizeCalculator`s open func messageSizeCalculators() -> [MessageSizeCalculator] { diff --git a/Sources/Layout/MessagesCollectionViewLayoutAttributes.swift b/Sources/Layout/MessagesCollectionViewLayoutAttributes.swift index 88699f30..fc4541b0 100644 --- a/Sources/Layout/MessagesCollectionViewLayoutAttributes.swift +++ b/Sources/Layout/MessagesCollectionViewLayoutAttributes.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -31,6 +31,7 @@ open class MessagesCollectionViewLayoutAttributes: UICollectionViewLayoutAttribu public var avatarSize: CGSize = .zero public var avatarPosition = AvatarPosition(vertical: .cellBottom) + public var avatarLeadingTrailingPadding: CGFloat = 0 public var messageContainerSize: CGSize = .zero public var messageContainerPadding: UIEdgeInsets = .zero @@ -51,7 +52,8 @@ open class MessagesCollectionViewLayoutAttributes: UICollectionViewLayoutAttribu public var accessoryViewSize: CGSize = .zero public var accessoryViewPadding: HorizontalEdgeInsets = .zero - + public var accessoryViewPosition: AccessoryPosition = .messageCenter + // MARK: - Methods open override func copy(with zone: NSZone? = nil) -> Any { @@ -59,6 +61,7 @@ open class MessagesCollectionViewLayoutAttributes: UICollectionViewLayoutAttribu let copy = super.copy(with: zone) as! MessagesCollectionViewLayoutAttributes copy.avatarSize = avatarSize copy.avatarPosition = avatarPosition + copy.avatarLeadingTrailingPadding = avatarLeadingTrailingPadding copy.messageContainerSize = messageContainerSize copy.messageContainerPadding = messageContainerPadding copy.messageLabelFont = messageLabelFont @@ -73,6 +76,7 @@ open class MessagesCollectionViewLayoutAttributes: UICollectionViewLayoutAttribu copy.messageBottomLabelSize = messageBottomLabelSize copy.accessoryViewSize = accessoryViewSize copy.accessoryViewPadding = accessoryViewPadding + copy.accessoryViewPosition = accessoryViewPosition return copy // swiftlint:enable force_cast } @@ -81,7 +85,8 @@ open class MessagesCollectionViewLayoutAttributes: UICollectionViewLayoutAttribu // MARK: - LEAVE this as is if let attributes = object as? MessagesCollectionViewLayoutAttributes { return super.isEqual(object) && attributes.avatarSize == avatarSize - && attributes.avatarPosition == attributes.avatarPosition + && attributes.avatarPosition == avatarPosition + && attributes.avatarLeadingTrailingPadding == avatarLeadingTrailingPadding && attributes.messageContainerSize == messageContainerSize && attributes.messageContainerPadding == messageContainerPadding && attributes.messageLabelFont == messageLabelFont @@ -96,6 +101,7 @@ open class MessagesCollectionViewLayoutAttributes: UICollectionViewLayoutAttribu && attributes.messageBottomLabelSize == messageBottomLabelSize && attributes.accessoryViewSize == accessoryViewSize && attributes.accessoryViewPadding == accessoryViewPadding + && attributes.accessoryViewPosition == accessoryViewPosition } else { return false } diff --git a/Sources/Layout/TextMessageSizeCalculator.swift b/Sources/Layout/TextMessageSizeCalculator.swift index 9f2b5cc1..65479f8d 100644 --- a/Sources/Layout/TextMessageSizeCalculator.swift +++ b/Sources/Layout/TextMessageSizeCalculator.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/AccessoryPosition.swift b/Sources/Models/AccessoryPosition.swift new file mode 100644 index 00000000..d0496220 --- /dev/null +++ b/Sources/Models/AccessoryPosition.swift @@ -0,0 +1,48 @@ +/* + MIT License + + Copyright (c) 2017-2018 MessageKit + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import Foundation + +/// Used to determine the `Horizontal` and `Vertical` position of +// an `AccessoryView` in a `MessageCollectionViewCell`. +public enum AccessoryPosition { + + /// Aligns the `AccessoryView`'s top edge to the cell's top edge. + case cellTop + + /// Aligns the `AccessoryView`'s top edge to the `messageTopLabel`'s top edge. + case messageLabelTop + + /// Aligns the `AccessoryView`'s top edge to the `MessageContainerView`'s top edge. + case messageTop + + /// Aligns the `AccessoryView` center to the `MessageContainerView` center. + case messageCenter + + /// Aligns the `AccessoryView`'s bottom edge to the `MessageContainerView`s bottom edge. + case messageBottom + + /// Aligns the `AccessoryView`'s bottom edge to the cell's bottom edge. + case cellBottom +} diff --git a/Sources/Models/Avatar.swift b/Sources/Models/Avatar.swift index 29fa1694..a9de31c1 100644 --- a/Sources/Models/Avatar.swift +++ b/Sources/Models/Avatar.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/AvatarPosition.swift b/Sources/Models/AvatarPosition.swift index e887e782..6421e48f 100644 --- a/Sources/Models/AvatarPosition.swift +++ b/Sources/Models/AvatarPosition.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/DetectorType.swift b/Sources/Models/DetectorType.swift index a49b7b6d..33d6c24f 100644 --- a/Sources/Models/DetectorType.swift +++ b/Sources/Models/DetectorType.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/HorizontalEdgeInsets.swift b/Sources/Models/HorizontalEdgeInsets.swift index 9ec2f0f5..7e92b030 100644 --- a/Sources/Models/HorizontalEdgeInsets.swift +++ b/Sources/Models/HorizontalEdgeInsets.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/LabelAlignment.swift b/Sources/Models/LabelAlignment.swift index 320971fc..2c6b0ba2 100644 --- a/Sources/Models/LabelAlignment.swift +++ b/Sources/Models/LabelAlignment.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/LocationMessageSnapshotOptions.swift b/Sources/Models/LocationMessageSnapshotOptions.swift index 21628fcb..ccef50c5 100644 --- a/Sources/Models/LocationMessageSnapshotOptions.swift +++ b/Sources/Models/LocationMessageSnapshotOptions.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/MessageKind.swift b/Sources/Models/MessageKind.swift index 2b8d46f2..8a8eea48 100644 --- a/Sources/Models/MessageKind.swift +++ b/Sources/Models/MessageKind.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/MessageKitDateFormatter.swift b/Sources/Models/MessageKitDateFormatter.swift index c0d02bc2..76e1f94e 100644 --- a/Sources/Models/MessageKitDateFormatter.swift +++ b/Sources/Models/MessageKitDateFormatter.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/MessageStyle.swift b/Sources/Models/MessageStyle.swift index f8abd50e..7814a2f5 100644 --- a/Sources/Models/MessageStyle.swift +++ b/Sources/Models/MessageStyle.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/NSConstraintLayoutSet.swift b/Sources/Models/NSConstraintLayoutSet.swift index cd063dfd..79140928 100644 --- a/Sources/Models/NSConstraintLayoutSet.swift +++ b/Sources/Models/NSConstraintLayoutSet.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Models/Sender.swift b/Sources/Models/Sender.swift index 8fc5e944..22ea0a1e 100644 --- a/Sources/Models/Sender.swift +++ b/Sources/Models/Sender.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -25,7 +25,8 @@ import Foundation /// An object that groups the metadata of a messages sender. -public struct Sender { +@available(*, deprecated: 3.0.0, message: "`Sender` has been replaced with the `SenderType` protocol in 3.0.0") +public struct Sender: SenderType { /// MARK: - Properties @@ -44,14 +45,3 @@ public struct Sender { self.displayName = displayName } } - -// MARK: - Equatable Conformance - -extension Sender: Equatable { - - /// Two senders are considered equal if they have the same id. - public static func == (left: Sender, right: Sender) -> Bool { - return left.id == right.id - } - -} diff --git a/Sources/Protocols/AudioItem.swift b/Sources/Protocols/AudioItem.swift index 54868adc..9e7ba659 100644 --- a/Sources/Protocols/AudioItem.swift +++ b/Sources/Protocols/AudioItem.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Protocols/LocationItem.swift b/Sources/Protocols/LocationItem.swift index f08fccb3..51b4225a 100644 --- a/Sources/Protocols/LocationItem.swift +++ b/Sources/Protocols/LocationItem.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Protocols/MediaItem.swift b/Sources/Protocols/MediaItem.swift index cddb94c7..4242f376 100644 --- a/Sources/Protocols/MediaItem.swift +++ b/Sources/Protocols/MediaItem.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Protocols/MessageCellDelegate.swift b/Sources/Protocols/MessageCellDelegate.swift index d9f9a3ff..dd07f5d6 100644 --- a/Sources/Protocols/MessageCellDelegate.swift +++ b/Sources/Protocols/MessageCellDelegate.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Protocols/MessageLabelDelegate.swift b/Sources/Protocols/MessageLabelDelegate.swift index e84ea622..06a123e8 100644 --- a/Sources/Protocols/MessageLabelDelegate.swift +++ b/Sources/Protocols/MessageLabelDelegate.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Protocols/MessageType.swift b/Sources/Protocols/MessageType.swift index 627b7f50..664be32a 100644 --- a/Sources/Protocols/MessageType.swift +++ b/Sources/Protocols/MessageType.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,7 @@ import Foundation public protocol MessageType { /// The sender of the message. - var sender: Sender { get } + var sender: SenderType { get } /// The unique identifier for the message. var messageId: String { get } diff --git a/Sources/Protocols/MessagesDataSource.swift b/Sources/Protocols/MessagesDataSource.swift index 939a4ad4..0c58a813 100644 --- a/Sources/Protocols/MessagesDataSource.swift +++ b/Sources/Protocols/MessagesDataSource.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -28,17 +28,17 @@ import UIKit /// the data required by a `MessagesCollectionView`. public protocol MessagesDataSource: AnyObject { - /// The `Sender` of new messages in the `MessagesCollectionView`. - func currentSender() -> Sender + /// The `SenderType` of new messages in the `MessagesCollectionView`. + func currentSender() -> SenderType - /// A helper method to determine if a given message is from the current `Sender`. + /// A helper method to determine if a given message is from the current `SenderType`. /// /// - Parameters: - /// - message: The message to check if it was sent by the current `Sender`. + /// - message: The message to check if it was sent by the current `SenderType`. /// /// - Note: /// The default implementation of this method checks for equality between - /// the message's `Sender` and the current `Sender`. + /// the message's `SenderType` and the current `SenderType`. func isFromCurrentSender(message: MessageType) -> Bool /// The message to be used for a `MessageCollectionViewCell` at the given `IndexPath`. @@ -118,7 +118,7 @@ public protocol MessagesDataSource: AnyObject { public extension MessagesDataSource { func isFromCurrentSender(message: MessageType) -> Bool { - return message.sender == currentSender() + return message.sender.id == currentSender().id } func numberOfItems(inSection section: Int, in messagesCollectionView: MessagesCollectionView) -> Int { diff --git a/Sources/Protocols/MessagesDisplayDelegate.swift b/Sources/Protocols/MessagesDisplayDelegate.swift index 334042c4..29d43e80 100644 --- a/Sources/Protocols/MessagesDisplayDelegate.swift +++ b/Sources/Protocols/MessagesDisplayDelegate.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -50,7 +50,7 @@ public protocol MessagesDisplayDelegate: AnyObject { /// /// - Note: /// The default value is `UIColor.clear` for emoji messages. - /// For all other `MessageKind` cases, the color depends on the `Sender`. + /// For all other `MessageKind` cases, the color depends on the `SenderType`. /// /// Current sender: Green /// @@ -106,7 +106,7 @@ public protocol MessagesDisplayDelegate: AnyObject { /// - messagesCollectionView: The `MessagesCollectionView` in which this cell will be displayed. /// /// - Note: - /// The default value returned by this method is determined by the messages `Sender`. + /// The default value returned by this method is determined by the messages `SenderType`. /// /// Current sender: UIColor.white /// diff --git a/Sources/Protocols/MessagesLayoutDelegate.swift b/Sources/Protocols/MessagesLayoutDelegate.swift index 55aaaf49..57c4ec33 100644 --- a/Sources/Protocols/MessagesLayoutDelegate.swift +++ b/Sources/Protocols/MessagesLayoutDelegate.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Protocols/SenderType.swift b/Sources/Protocols/SenderType.swift new file mode 100644 index 00000000..82f80e28 --- /dev/null +++ b/Sources/Protocols/SenderType.swift @@ -0,0 +1,38 @@ +/* + MIT License + + Copyright (c) 2017-2019 MessageKit + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import Foundation + +/// A standard protocol representing a sender. +/// Use this protocol to adhere a object as the sender of a MessageType +public protocol SenderType { + + /// The unique String identifier for the sender. + /// + /// Note: This value must be unique across all senders. + var id: String { get } + + /// The display name of a sender. + var displayName: String { get } +} diff --git a/Sources/Supporting/Info.plist b/Sources/Supporting/Info.plist index 60b9c008..e0f4bf77 100644 --- a/Sources/Supporting/Info.plist +++ b/Sources/Supporting/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.0 + 3.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Sources/Supporting/MessageInputBar.swift b/Sources/Supporting/MessageInputBar.swift new file mode 100644 index 00000000..f41c0a57 --- /dev/null +++ b/Sources/Supporting/MessageInputBar.swift @@ -0,0 +1,54 @@ +/* + MIT License + + Copyright (c) 2017-2019 MessageKit + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import UIKit +import InputBarAccessoryView + +public typealias MessageInputBar = InputBarAccessoryView + +@available(*, renamed: "InputBarAccessoryViewDelegate") +public typealias MessageInputBarDelegate = InputBarAccessoryViewDelegate + +public extension MessageInputBarDelegate { + + @available(*, obsoleted: 3.0.0, message: "`MessageInputBar` has been replaced with `InputBarAccessoryView` in 3.0.0. Use `inputBar(_ inputBar: InputBarAccessoryView, didPressSendButtonWith text: String)` instead.") + func messageInputBar(_ inputBar: MessageInputBar, didPressSendButtonWith text: String) { + } + + @available(*, obsoleted: 3.0.0, message: "`MessageInputBar` has been replaced with `InputBarAccessoryView` in 3.0.0. Use `inputBar(_ inputBar: InputBarAccessoryView, textViewTextDidChangeTo text: String)` instead.") + func messageInputBar(_ inputBar: MessageInputBar, textViewTextDidChangeTo text: String) { + } + + @available(*, obsoleted: 3.0.0, message: "`MessageInputBar` has been replaced with `InputBarAccessoryView` in 3.0.0. Use `inputBar(_ inputBar: InputBarAccessoryView, didChangeIntrinsicContentTo size: CGSize)` instead.") + func messageInputBar(_ inputBar: MessageInputBar, didChangeIntrinsicContentTo size: CGSize) { + } +} + +extension InputBarButtonItem { + + @available(*, renamed: "inputBarAccessoryView") + public var messageInputBar: MessageInputBar? { + return inputBarAccessoryView + } +} diff --git a/Sources/Supporting/MessageKit+Availability.swift b/Sources/Supporting/MessageKit+Availability.swift index 735409e3..16d40626 100644 --- a/Sources/Supporting/MessageKit+Availability.swift +++ b/Sources/Supporting/MessageKit+Availability.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/AvatarView.swift b/Sources/Views/AvatarView.swift index cf3c1456..6563143e 100644 --- a/Sources/Views/AvatarView.swift +++ b/Sources/Views/AvatarView.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/Cells/AudioMessageCell.swift b/Sources/Views/Cells/AudioMessageCell.swift index 4c32567d..b672ca88 100644 --- a/Sources/Views/Cells/AudioMessageCell.swift +++ b/Sources/Views/Cells/AudioMessageCell.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -96,41 +96,35 @@ open class AudioMessageCell: MessageContentCell { open override func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) { super.configure(with: message, at: indexPath, and: messagesCollectionView) - configureCellApperance(with: message, indexPath: indexPath, messagesCollectionView: messagesCollectionView) - - guard let displayDelegate = messagesCollectionView.messagesDisplayDelegate else { - fatalError(MessageKitError.nilMessagesDisplayDelegate) - } - // default implementation for decorate cell - guard case let .audio(audioItem) = message.kind else { fatalError("Failed decorate audio cell") } - durationLabel.text = displayDelegate.audioProgressTextFormat(audioItem.duration, for: self, in: messagesCollectionView) - progressView.progress = 0.0 - playButton.isSelected = false - // call configure delegate for fourther config - displayDelegate.configureAudioCell(self, message: message) - } - private func configureCellApperance(with message: MessageType, indexPath: IndexPath, messagesCollectionView: MessagesCollectionView) { - // modify elements constrains based on message direction (incoming or outgoing) guard let dataSource = messagesCollectionView.messagesDataSource else { fatalError(MessageKitError.nilMessagesDataSource) } - let playButtonLeftConstrain = messageContainerView.constraints.filter({ $0.identifier == "left" }).first - let durationLabelRightConstrain = messageContainerView.constraints.filter({ $0.identifier == "right" }).first - if dataSource.isFromCurrentSender(message: message) == false { // outgoing message - playButtonLeftConstrain?.constant = 12 - durationLabelRightConstrain?.constant = -8 - } else { // incoming message - playButtonLeftConstrain?.constant = 5 - durationLabelRightConstrain?.constant = -15 + + let playButtonLeftConstraint = messageContainerView.constraints.filter { $0.identifier == "left" }.first + let durationLabelRightConstraint = messageContainerView.constraints.filter { $0.identifier == "right" }.first + + if !dataSource.isFromCurrentSender(message: message) { + playButtonLeftConstraint?.constant = 12 + durationLabelRightConstraint?.constant = -8 + } else { + playButtonLeftConstraint?.constant = 5 + durationLabelRightConstraint?.constant = -15 } + guard let displayDelegate = messagesCollectionView.messagesDisplayDelegate else { fatalError(MessageKitError.nilMessagesDisplayDelegate) } + let tintColor = displayDelegate.audioTintColor(for: message, at: indexPath, in: messagesCollectionView) playButton.imageView?.tintColor = tintColor durationLabel.textColor = tintColor progressView.tintColor = tintColor - } + displayDelegate.configureAudioCell(self, message: message) + + if case let .audio(audioItem) = message.kind { + durationLabel.text = displayDelegate.audioProgressTextFormat(audioItem.duration, for: self, in: messagesCollectionView) + } + } } diff --git a/Sources/Views/Cells/LocationMessageCell.swift b/Sources/Views/Cells/LocationMessageCell.swift index ed84ed75..23dcfb22 100644 --- a/Sources/Views/Cells/LocationMessageCell.swift +++ b/Sources/Views/Cells/LocationMessageCell.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/Cells/MediaMessageCell.swift b/Sources/Views/Cells/MediaMessageCell.swift index 94f885e8..d7e1967b 100644 --- a/Sources/Views/Cells/MediaMessageCell.swift +++ b/Sources/Views/Cells/MediaMessageCell.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -55,6 +55,11 @@ open class MediaMessageCell: MessageContentCell { messageContainerView.addSubview(playButtonView) setupConstraints() } + + open override func prepareForReuse() { + super.prepareForReuse() + self.imageView.image = nil + } open override func configure(with message: MessageType, at indexPath: IndexPath, and messagesCollectionView: MessagesCollectionView) { super.configure(with: message, at: indexPath, and: messagesCollectionView) diff --git a/Sources/Views/Cells/MessageCollectionViewCell.swift b/Sources/Views/Cells/MessageCollectionViewCell.swift index f8929c21..51855a1c 100644 --- a/Sources/Views/Cells/MessageCollectionViewCell.swift +++ b/Sources/Views/Cells/MessageCollectionViewCell.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/Cells/MessageContentCell.swift b/Sources/Views/Cells/MessageContentCell.swift index 0bcabc02..9fdfefeb 100644 --- a/Sources/Views/Cells/MessageContentCell.swift +++ b/Sources/Views/Cells/MessageContentCell.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -198,12 +198,13 @@ open class MessageContentCell: MessageCollectionViewCell { /// - attributes: The `MessagesCollectionViewLayoutAttributes` for the cell. open func layoutAvatarView(with attributes: MessagesCollectionViewLayoutAttributes) { var origin: CGPoint = .zero + let padding = attributes.avatarLeadingTrailingPadding switch attributes.avatarPosition.horizontal { case .cellLeading: - break + origin.x = padding case .cellTrailing: - origin.x = attributes.frame.width - attributes.avatarSize.width + origin.x = attributes.frame.width - attributes.avatarSize.width - padding case .natural: fatalError(MessageKitError.avatarPositionUnresolved) } @@ -250,11 +251,12 @@ open class MessageContentCell: MessageCollectionViewCell { } } + let avatarPadding = attributes.avatarLeadingTrailingPadding switch attributes.avatarPosition.horizontal { case .cellLeading: - origin.x = attributes.avatarSize.width + attributes.messageContainerPadding.left + origin.x = attributes.avatarSize.width + attributes.messageContainerPadding.left + avatarPadding case .cellTrailing: - origin.x = attributes.frame.width - attributes.avatarSize.width - attributes.messageContainerSize.width - attributes.messageContainerPadding.right + origin.x = attributes.frame.width - attributes.avatarSize.width - attributes.messageContainerSize.width - attributes.messageContainerPadding.right - avatarPadding case .natural: fatalError(MessageKitError.avatarPositionUnresolved) } @@ -308,10 +310,23 @@ open class MessageContentCell: MessageCollectionViewCell { /// - attributes: The `MessagesCollectionViewLayoutAttributes` for the cell. open func layoutAccessoryView(with attributes: MessagesCollectionViewLayoutAttributes) { - // Accessory view aligned to the middle of the messageContainerView - let y = messageContainerView.frame.midY - (attributes.accessoryViewSize.height / 2) - - var origin = CGPoint(x: 0, y: y) + var origin: CGPoint = .zero + + // Accessory view is set at the side space of the messageContainerView + switch attributes.accessoryViewPosition { + case .messageLabelTop: + origin.y = messageTopLabel.frame.minY + case .messageTop: + origin.y = messageContainerView.frame.minY + case .messageBottom: + origin.y = messageContainerView.frame.maxY - attributes.accessoryViewSize.height + case .messageCenter: + origin.y = messageContainerView.frame.midY - (attributes.accessoryViewSize.height / 2) + case .cellBottom: + origin.y = attributes.frame.height - attributes.accessoryViewSize.height + default: + break + } // Accessory view is always on the opposite side of avatar switch attributes.avatarPosition.horizontal { diff --git a/Sources/Views/Cells/TextMessageCell.swift b/Sources/Views/Cells/TextMessageCell.swift index 481411ba..e93675be 100644 --- a/Sources/Views/Cells/TextMessageCell.swift +++ b/Sources/Views/Cells/TextMessageCell.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/Headers & Footers/MessageReusableView.swift b/Sources/Views/Headers & Footers/MessageReusableView.swift index 56270dd3..4f5321c8 100644 --- a/Sources/Views/Headers & Footers/MessageReusableView.swift +++ b/Sources/Views/Headers & Footers/MessageReusableView.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/InsetLabel.swift b/Sources/Views/InsetLabel.swift index 72bb9f8d..5cdfa172 100644 --- a/Sources/Views/InsetLabel.swift +++ b/Sources/Views/InsetLabel.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/MessageContainerView.swift b/Sources/Views/MessageContainerView.swift index 71423293..cbecffa4 100644 --- a/Sources/Views/MessageContainerView.swift +++ b/Sources/Views/MessageContainerView.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/MessageLabel.swift b/Sources/Views/MessageLabel.swift index d451d486..061b6504 100644 --- a/Sources/Views/MessageLabel.swift +++ b/Sources/Views/MessageLabel.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/MessagesCollectionView.swift b/Sources/Views/MessagesCollectionView.swift index 54020ce2..c9d97bc5 100644 --- a/Sources/Views/MessagesCollectionView.swift +++ b/Sources/Views/MessagesCollectionView.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Sources/Views/PlayButtonView.swift b/Sources/Views/PlayButtonView.swift index b446ccfd..8ccd9843 100644 --- a/Sources/Views/PlayButtonView.swift +++ b/Sources/Views/PlayButtonView.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/AvatarSpec.swift b/Tests/AvatarSpec.swift index ebd15e8b..06ac9af5 100644 --- a/Tests/AvatarSpec.swift +++ b/Tests/AvatarSpec.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/ControllersTest/MessageLabelSpec.swift b/Tests/ControllersTest/MessageLabelSpec.swift index abf28a00..76af3cea 100644 --- a/Tests/ControllersTest/MessageLabelSpec.swift +++ b/Tests/ControllersTest/MessageLabelSpec.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/ControllersTest/MessagesViewControllerSpec.swift b/Tests/ControllersTest/MessagesViewControllerSpec.swift index 1cf4d565..59646326 100644 --- a/Tests/ControllersTest/MessagesViewControllerSpec.swift +++ b/Tests/ControllersTest/MessagesViewControllerSpec.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -51,7 +51,6 @@ final class MessagesViewControllerSpec: QuickSpec { } it("sets inputAccessoryView to the messageInputBar") { expect(controller.inputAccessoryView).toNot(beNil()) - expect(controller.inputAccessoryView is MessageInputBar).to(beTrue()) } it("has a MessagesCollectionView") { expect(controller.messagesCollectionView).toNot(beNil()) diff --git a/Tests/ControllersTest/MessagesViewControllerTests.swift b/Tests/ControllersTest/MessagesViewControllerTests.swift index 9b72a759..640bbacd 100644 --- a/Tests/ControllersTest/MessagesViewControllerTests.swift +++ b/Tests/ControllersTest/MessagesViewControllerTests.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -90,7 +90,7 @@ class MessagesViewControllerTests: XCTestCase { let messagesDataSource = MockMessagesDataSource() sut.messagesCollectionView.messagesDataSource = messagesDataSource messagesDataSource.messages.append(MockMessage(text: "Test", - sender: messagesDataSource.senders[0], + user: messagesDataSource.senders[0], messageId: "test_id")) sut.messagesCollectionView.reloadData() @@ -108,7 +108,7 @@ class MessagesViewControllerTests: XCTestCase { let attributes = [NSAttributedString.Key.foregroundColor: UIColor.black] let attriutedString = NSAttributedString(string: "Test", attributes: attributes) messagesDataSource.messages.append(MockMessage(attributedText: attriutedString, - sender: messagesDataSource.senders[0], + user: messagesDataSource.senders[0], messageId: "test_id")) sut.messagesCollectionView.reloadData() @@ -124,7 +124,7 @@ class MessagesViewControllerTests: XCTestCase { let messagesDataSource = MockMessagesDataSource() sut.messagesCollectionView.messagesDataSource = messagesDataSource messagesDataSource.messages.append(MockMessage(image: UIImage(), - sender: messagesDataSource.senders[0], + user: messagesDataSource.senders[0], messageId: "test_id")) sut.messagesCollectionView.reloadData() @@ -140,7 +140,7 @@ class MessagesViewControllerTests: XCTestCase { let messagesDataSource = MockMessagesDataSource() sut.messagesCollectionView.messagesDataSource = messagesDataSource messagesDataSource.messages.append(MockMessage(thumbnail: UIImage(), - sender: messagesDataSource.senders[0], + user: messagesDataSource.senders[0], messageId: "test_id")) sut.messagesCollectionView.reloadData() @@ -156,7 +156,7 @@ class MessagesViewControllerTests: XCTestCase { let messagesDataSource = MockMessagesDataSource() sut.messagesCollectionView.messagesDataSource = messagesDataSource messagesDataSource.messages.append(MockMessage(location: CLLocation(latitude: 60.0, longitude: 70.0), - sender: messagesDataSource.senders[0], + user: messagesDataSource.senders[0], messageId: "test_id")) sut.messagesCollectionView.reloadData() @@ -173,7 +173,7 @@ class MessagesViewControllerTests: XCTestCase { sut.messagesCollectionView.messagesDataSource = messagesDataSource messagesDataSource.messages.append(MockMessage(audioURL: URL.init(fileURLWithPath: ""), duration: 4.0, - sender: messagesDataSource.senders[0], + user: messagesDataSource.senders[0], messageId: "test_id")) sut.messagesCollectionView.reloadData() @@ -187,9 +187,9 @@ class MessagesViewControllerTests: XCTestCase { // MARK: - Assistants - private func makeMessages(for senders: [Sender]) -> [MessageType] { - return [MockMessage(text: "Text 1", sender: senders[0], messageId: "test_id_1"), - MockMessage(text: "Text 2", sender: senders[1], messageId: "test_id_2")] + private func makeMessages(for senders: [MockUser]) -> [MessageType] { + return [MockMessage(text: "Text 1", user: senders[0], messageId: "test_id_1"), + MockMessage(text: "Text 2", user: senders[1], messageId: "test_id_2")] } } diff --git a/Tests/DetectorTypeSpec.swift b/Tests/DetectorTypeSpec.swift index 60426131..75208abd 100644 --- a/Tests/DetectorTypeSpec.swift +++ b/Tests/DetectorTypeSpec.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/Mocks/MockMessage.swift b/Tests/Mocks/MockMessage.swift index 812852a7..e688bca0 100644 --- a/Tests/Mocks/MockMessage.swift +++ b/Tests/Mocks/MockMessage.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -72,47 +72,50 @@ private struct MockAudiotem: AudioItem { struct MockMessage: MessageType { var messageId: String - var sender: Sender + var sender: SenderType { + return user + } var sentDate: Date var kind: MessageKind + var user: MockUser - private init(kind: MessageKind, sender: Sender, messageId: String) { + private init(kind: MessageKind, user: MockUser, messageId: String) { self.kind = kind - self.sender = sender + self.user = user self.messageId = messageId self.sentDate = Date() } - init(text: String, sender: Sender, messageId: String) { - self.init(kind: .text(text), sender: sender, messageId: messageId) + init(text: String, user: MockUser, messageId: String) { + self.init(kind: .text(text), user: user, messageId: messageId) } - init(attributedText: NSAttributedString, sender: Sender, messageId: String) { - self.init(kind: .attributedText(attributedText), sender: sender, messageId: messageId) + init(attributedText: NSAttributedString, user: MockUser, messageId: String) { + self.init(kind: .attributedText(attributedText), user: user, messageId: messageId) } - init(image: UIImage, sender: Sender, messageId: String) { + init(image: UIImage, user: MockUser, messageId: String) { let mediaItem = MockMediaItem(image: image) - self.init(kind: .photo(mediaItem), sender: sender, messageId: messageId) + self.init(kind: .photo(mediaItem), user: user, messageId: messageId) } - init(thumbnail: UIImage, sender: Sender, messageId: String) { + init(thumbnail: UIImage, user: MockUser, messageId: String) { let mediaItem = MockMediaItem(image: thumbnail) - self.init(kind: .video(mediaItem), sender: sender, messageId: messageId) + self.init(kind: .video(mediaItem), user: user, messageId: messageId) } - init(location: CLLocation, sender: Sender, messageId: String) { + init(location: CLLocation, user: MockUser, messageId: String) { let locationItem = MockLocationItem(location: location) - self.init(kind: .location(locationItem), sender: sender, messageId: messageId) + self.init(kind: .location(locationItem), user: user, messageId: messageId) } - init(emoji: String, sender: Sender, messageId: String) { - self.init(kind: .emoji(emoji), sender: sender, messageId: messageId) + init(emoji: String, user: MockUser, messageId: String) { + self.init(kind: .emoji(emoji), user: user, messageId: messageId) } - init(audioURL: URL, duration: Float, sender: Sender, messageId: String) { + init(audioURL: URL, duration: Float, user: MockUser, messageId: String) { let audioItem = MockAudiotem(url: audioURL, duration: duration) - self.init(kind: .audio(audioItem), sender: sender, messageId: messageId) + self.init(kind: .audio(audioItem), user: user, messageId: messageId) } } diff --git a/Tests/Mocks/MockMessagesDataSource.swift b/Tests/Mocks/MockMessagesDataSource.swift index 566d8d27..31703420 100644 --- a/Tests/Mocks/MockMessagesDataSource.swift +++ b/Tests/Mocks/MockMessagesDataSource.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -28,13 +28,17 @@ import Foundation class MockMessagesDataSource: MessagesDataSource { var messages: [MessageType] = [] - let senders: [Sender] = [Sender(id: "sender_1", displayName: "Sender 1"), - Sender(id: "sender_2", displayName: "Sender 2")] + let senders: [MockUser] = [MockUser(id: "sender_1", displayName: "Sender 1"), + MockUser(id: "sender_2", displayName: "Sender 2")] - func currentSender() -> Sender { + var currentUser: MockUser { return senders[0] } + func currentSender() -> SenderType { + return currentUser + } + func numberOfSections(in messagesCollectionView: MessagesCollectionView) -> Int { return messages.count } diff --git a/Tests/Mocks/MockUser.swift b/Tests/Mocks/MockUser.swift new file mode 100644 index 00000000..7e0f951c --- /dev/null +++ b/Tests/Mocks/MockUser.swift @@ -0,0 +1,31 @@ +/* + MIT License + + Copyright (c) 2017-2019 MessageKit + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + +import Foundation +@testable import MessageKit + +struct MockUser: SenderType { + var id: String + var displayName: String +} diff --git a/Tests/ModelTests/MessageKitDateFormatterTests.swift b/Tests/ModelTests/MessageKitDateFormatterTests.swift index e9b24175..3fe3b5df 100644 --- a/Tests/ModelTests/MessageKitDateFormatterTests.swift +++ b/Tests/ModelTests/MessageKitDateFormatterTests.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/ModelTests/MessageStyleTests.swift b/Tests/ModelTests/MessageStyleTests.swift index 7534ac99..781b9402 100644 --- a/Tests/ModelTests/MessageStyleTests.swift +++ b/Tests/ModelTests/MessageStyleTests.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/ProtocolsTests/MessagesDisplayDelegateTests.swift b/Tests/ProtocolsTests/MessagesDisplayDelegateTests.swift index 4d2dae9d..6cbfb632 100644 --- a/Tests/ProtocolsTests/MessagesDisplayDelegateTests.swift +++ b/Tests/ProtocolsTests/MessagesDisplayDelegateTests.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -76,7 +76,7 @@ class MessagesDisplayDelegateTests: XCTestCase { func testBackgroundColorForMessageWithEmoji_returnsClearForDefault() { sut.dataProvider.messages.append(MockMessage(emoji: "🤔", - sender: sut.dataProvider.currentSender(), + user: sut.dataProvider.currentUser, messageId: "003")) let backgroundColor = sut.backgroundColor(for: sut.dataProvider.messages[2], at: IndexPath(item: 0, section: 0), @@ -196,10 +196,10 @@ private class MockMessagesViewController: MessagesViewController, MessagesDispla fileprivate func makeDataSource() -> MockMessagesDataSource { let dataSource = MockMessagesDataSource() dataSource.messages.append(MockMessage(text: "Text 1", - sender: dataSource.senders[0], + user: dataSource.senders[0], messageId: "001")) dataSource.messages.append(MockMessage(text: "Text 2", - sender: dataSource.senders[1], + user: dataSource.senders[1], messageId: "002")) return dataSource diff --git a/Tests/SenderSpec.swift b/Tests/SenderSpec.swift index 56910a3d..2ed8839c 100644 --- a/Tests/SenderSpec.swift +++ b/Tests/SenderSpec.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -32,16 +32,16 @@ final class SenderSpec: QuickSpec { describe("equality between two Senders") { context("they have the same id ") { it("should be equal") { - let sender1 = Sender(id: "1", displayName: "Steven") - let sender2 = Sender(id: "1", displayName: "Nathan") - expect(sender1).to(equal(sender2)) + let sender1 = MockUser(id: "1", displayName: "Steven") + let sender2 = MockUser(id: "1", displayName: "Nathan") + expect(sender1.id == sender2.id).to(equal(true)) } } context("they have a different id") { it("should not be equal") { - let sender1 = Sender(id: "1", displayName: "Steven") - let sender2 = Sender(id: "2", displayName: "Nathan") - expect(sender1).toNot(equal(sender2)) + let sender1 = MockUser(id: "1", displayName: "Steven") + let sender2 = MockUser(id: "2", displayName: "Nathan") + expect(sender1.id == sender2.id).to(equal(false)) } } } diff --git a/Tests/ViewsTests/AvatarViewTests.swift b/Tests/ViewsTests/AvatarViewTests.swift index a6e9a00e..e919f141 100644 --- a/Tests/ViewsTests/AvatarViewTests.swift +++ b/Tests/ViewsTests/AvatarViewTests.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/ViewsTests/MessageCollectionViewCellTests.swift b/Tests/ViewsTests/MessageCollectionViewCellTests.swift index cbaa1a26..4bce2cf0 100644 --- a/Tests/ViewsTests/MessageCollectionViewCellTests.swift +++ b/Tests/ViewsTests/MessageCollectionViewCellTests.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Tests/ViewsTests/MessagesCollectionViewTests.swift b/Tests/ViewsTests/MessagesCollectionViewTests.swift index a2f35e0c..a42fa54d 100644 --- a/Tests/ViewsTests/MessagesCollectionViewTests.swift +++ b/Tests/ViewsTests/MessagesCollectionViewTests.swift @@ -1,7 +1,7 @@ /* MIT License - Copyright (c) 2017-2018 MessageKit + Copyright (c) 2017-2019 MessageKit Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal