Merge branch 'v0.9.0' into v0.9.0

This commit is contained in:
Andrew Robinson
2017-10-03 21:25:37 -05:00
committed by GitHub
16 changed files with 118 additions and 68 deletions
+14
View File
@@ -0,0 +1,14 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
# Set default charset
[*.{js,py,swift,m,json}]
charset = utf-8
# 4 space indentation
[*.swift]
indent_style = space
indent_size = 4
+2 -2
View File
@@ -46,9 +46,9 @@ The more information you can provide, the easier it will be for us to resolve yo
- This ensures the feature is in scope and no ones time is wasted.
- **Please DO NOT submit pull requests to the `master` branch**
- This branch is always stable and represents a relase.
- This branch is always stable and represents a release.
- **Please DO submit your pull request to the branch repersenting the next release version**
- **Please DO submit your pull request to the branch representing the next release version**
1. Link to any issues the pull request resolves. If none exist, create one.
2. Write unit tests for new functionality or fix any broken by your changes.
-3
View File
@@ -198,6 +198,3 @@ final class SampleData {
}
}
+35 -14
View File
@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
171D5AB91F36712B0053DF69 /* InputTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 171D5AB81F36712B0053DF69 /* InputTextView.swift */; };
2EB618EF1F8462CA007FBA0E /* UICollectionView+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EB618EE1F8462CA007FBA0E /* UICollectionView+Extensions.swift */; };
372F6AEB1F36C15600B57FBD /* AvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372F6AEA1F36C15600B57FBD /* AvatarView.swift */; };
372F6AEF1F36C61000B57FBD /* AvatarViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372F6AEE1F36C61000B57FBD /* AvatarViewTests.swift */; };
376AD1821F4258D80083072A /* TestMessageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376AD1811F4258D80083072A /* TestMessageModel.swift */; };
@@ -74,6 +75,7 @@
/* Begin PBXFileReference section */
171D5AB81F36712B0053DF69 /* InputTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputTextView.swift; sourceTree = "<group>"; };
2EB618EE1F8462CA007FBA0E /* UICollectionView+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionView+Extensions.swift"; sourceTree = "<group>"; };
372F6AEA1F36C15600B57FBD /* AvatarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvatarView.swift; sourceTree = "<group>"; };
372F6AEE1F36C61000B57FBD /* AvatarViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvatarViewTests.swift; sourceTree = "<group>"; };
376AD1811F4258D80083072A /* TestMessageModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestMessageModel.swift; sourceTree = "<group>"; };
@@ -150,6 +152,27 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
2EB618F01F84676A007FBA0E /* Cells */ = {
isa = PBXGroup;
children = (
B01049111F6F86E8008DBA58 /* LocationMessageCell.swift */,
B0D943BD1F6DC9AB008B7BFD /* MediaMessageCell.swift */,
B0655A4C1F244C0600542A83 /* MessageCollectionViewCell.swift */,
B0291DA81F6DBB9F00BEDF03 /* TextMessageCell.swift */,
);
name = Cells;
sourceTree = "<group>";
};
2EB618F11F846899007FBA0E /* Headers & Footers */ = {
isa = PBXGroup;
children = (
B074EE921F35587100ABB8C8 /* MessageHeaderView.swift */,
B0147C8F1F5ED0810035B36E /* MessageDateHeaderView.swift */,
B074EE941F35588A00ABB8C8 /* MessageFooterView.swift */,
);
name = "Headers & Footers";
sourceTree = "<group>";
};
376AD1801F4258C50083072A /* Support Files */ = {
isa = PBXGroup;
children = (
@@ -167,6 +190,7 @@
88916B231CF0DF2F00469F91 /* Products */,
);
sourceTree = "<group>";
usesTabs = 0;
};
88916B231CF0DF2F00469F91 /* Products */ = {
isa = PBXGroup;
@@ -216,11 +240,12 @@
B09643981F295D43004D0129 /* Extensions */ = {
isa = PBXGroup;
children = (
38C867991F50EA1000811974 /* UIView+Extensions.swift */,
B09643851F286C9E004D0129 /* String+Extensions.swift */,
B096438F1F289142004D0129 /* UIColor+Extensions.swift */,
B0AA1F521F44388900BAE583 /* NSAttributedString+Extensions.swift */,
B0147C821F5BE9220035B36E /* Bundle+Extensions.swift */,
B0AA1F521F44388900BAE583 /* NSAttributedString+Extensions.swift */,
B09643851F286C9E004D0129 /* String+Extensions.swift */,
2EB618EE1F8462CA007FBA0E /* UICollectionView+Extensions.swift */,
B096438F1F289142004D0129 /* UIColor+Extensions.swift */,
38C867991F50EA1000811974 /* UIView+Extensions.swift */,
);
name = Extensions;
sourceTree = "<group>";
@@ -246,21 +271,16 @@
B096439A1F295D68004D0129 /* Views */ = {
isa = PBXGroup;
children = (
B0655A2D1F23D8BC00542A83 /* MessagesCollectionView.swift */,
B0655A4C1F244C0600542A83 /* MessageCollectionViewCell.swift */,
2EB618F11F846899007FBA0E /* Headers & Footers */,
2EB618F01F84676A007FBA0E /* Cells */,
372F6AEA1F36C15600B57FBD /* AvatarView.swift */,
B0655A371F23EE8B00542A83 /* MessageInputBar.swift */,
38C8679D1F50EA4A00811974 /* InputBarItem.swift */,
171D5AB81F36712B0053DF69 /* InputTextView.swift */,
B074EE921F35587100ABB8C8 /* MessageHeaderView.swift */,
B074EE941F35588A00ABB8C8 /* MessageFooterView.swift */,
B074EEA71F3971A600ABB8C8 /* MessageLabel.swift */,
E8586DB41F59A1C300C9BE9D /* MessageContainerView.swift */,
B0147C8F1F5ED0810035B36E /* MessageDateHeaderView.swift */,
B0291DA81F6DBB9F00BEDF03 /* TextMessageCell.swift */,
B0D943BD1F6DC9AB008B7BFD /* MediaMessageCell.swift */,
B0655A371F23EE8B00542A83 /* MessageInputBar.swift */,
B074EEA71F3971A600ABB8C8 /* MessageLabel.swift */,
B0655A2D1F23D8BC00542A83 /* MessagesCollectionView.swift */,
B010490F1F6F8684008DBA58 /* PlayButtonView.swift */,
B01049111F6F86E8008DBA58 /* LocationMessageCell.swift */,
);
name = Views;
sourceTree = "<group>";
@@ -456,6 +476,7 @@
B09643861F286C9E004D0129 /* String+Extensions.swift in Sources */,
B015E81F1F259D8E007EDFB6 /* MessageInputBarDelegate.swift in Sources */,
B01280F31F4E8798004BCD3E /* MessageLabelDelegate.swift in Sources */,
2EB618EF1F8462CA007FBA0E /* UICollectionView+Extensions.swift in Sources */,
B0147C981F61AF930035B36E /* LabelAlignment.swift in Sources */,
376AD1881F4259D20083072A /* TestMessagesViewControllerModel.swift in Sources */,
B0655A2A1F23D77200542A83 /* Sender.swift in Sources */,
+1
View File
@@ -26,6 +26,7 @@ import UIKit
import MapKit
open class LocationMessageCell: MessageCollectionViewCell<UIImageView> {
open override class func reuseIdentifier() -> String { return "messagekit.cell.location" }
// MARK: - Properties
@@ -25,7 +25,6 @@
import Foundation
import MapKit
/// Conform to this protocol to customize location messages's style
public protocol LocationMessageDisplayDelegate: MessagesDisplayDelegate {
@@ -50,7 +49,6 @@ public protocol LocationMessageDisplayDelegate: MessagesDisplayDelegate {
/// - Returns: Your customized MKAnnotationView or nil to not show any.
func annotationViewForLocation(message: MessageType, at indexPath: IndexPath, in messageCollectionView: MessagesCollectionView) -> MKAnnotationView?
/// Ask the delegate for a custom animation block to run when whe map screenshot is ready to be displaied in the given location message
/// The animation block is called with the image view to be animated. You can animate it with CoreAnimation, UIView.animate or any library you prefer.
///
+1
View File
@@ -25,6 +25,7 @@
import UIKit
open class MediaMessageCell: MessageCollectionViewCell<UIImageView> {
open override class func reuseIdentifier() -> String { return "messagekit.cell.mediamessage" }
// MARK: - Properties
+2 -1
View File
@@ -24,7 +24,8 @@
import UIKit
open class MessageCollectionViewCell<ContentView: UIView>: UICollectionViewCell {
open class MessageCollectionViewCell<ContentView: UIView>: UICollectionViewCell, CollectionViewReusable {
open class func reuseIdentifier() -> String { return "messagekit.cell.base-cell" }
// MARK: - Properties
+1
View File
@@ -25,6 +25,7 @@
import UIKit
open class MessageDateHeaderView: MessageHeaderView {
open override class func reuseIdentifier() -> String { return "messagekit.header.date" }
// MARK: - Properties
+2 -1
View File
@@ -24,7 +24,8 @@
import UIKit
open class MessageFooterView: UICollectionReusableView {
open class MessageFooterView: UICollectionReusableView, CollectionViewReusable {
open class func reuseIdentifier() -> String { return "messagekit.footer.base" }
// MARK: - Initializers
+2 -3
View File
@@ -24,12 +24,11 @@
import UIKit
open class MessageHeaderView: UICollectionReusableView {
open class MessageHeaderView: UICollectionReusableView, CollectionViewReusable {
open class func reuseIdentifier() -> String { return "messagekit.header.base" }
// MARK: - Properties
static let identifier = "MessageHeaderView"
public override init(frame: CGRect) {
super.init(frame: frame)
}
+9 -30
View File
@@ -34,7 +34,6 @@ open class MessagesViewController: UIViewController {
open var scrollsToBottomOnFirstLayout: Bool = false
open var scrollsToBottomOnKeybordBeginsEditing: Bool = false
open var additionalTopContentInset: CGFloat = 0 {
@@ -107,26 +106,13 @@ open class MessagesViewController: UIViewController {
private func registerReusableViews() {
messagesCollectionView.register(TextMessageCell.self,
forCellWithReuseIdentifier: "TextMessageCell")
messagesCollectionView.register(TextMessageCell.self)
messagesCollectionView.register(MediaMessageCell.self)
messagesCollectionView.register(LocationMessageCell.self)
messagesCollectionView.register(MediaMessageCell.self,
forCellWithReuseIdentifier: "MediaMessageCell")
messagesCollectionView.register(LocationMessageCell.self,
forCellWithReuseIdentifier: "LocationMessageCell")
messagesCollectionView.register(MessageFooterView.self,
forSupplementaryViewOfKind: UICollectionElementKindSectionFooter,
withReuseIdentifier: "MessageFooterView")
messagesCollectionView.register(MessageHeaderView.self,
forSupplementaryViewOfKind: UICollectionElementKindSectionHeader,
withReuseIdentifier: "MessageHeaderView")
messagesCollectionView.register(MessageDateHeaderView.self,
forSupplementaryViewOfKind: UICollectionElementKindSectionHeader,
withReuseIdentifier: "MessageDateHeaderView")
messagesCollectionView.register(MessageFooterView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionFooter)
messagesCollectionView.register(MessageHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader)
messagesCollectionView.register(MessageDateHeaderView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader)
}
@@ -186,21 +172,15 @@ extension MessagesViewController: UICollectionViewDataSource {
switch message.data {
case .text, .attributedText, .emoji:
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TextMessageCell", for: indexPath) as? TextMessageCell else {
fatalError("Unable to dequeue TextMessageCell")
}
let cell = collectionView.dequeueReusableCell(TextMessageCell.self, for: indexPath)
cell.configure(with: message, at: indexPath, and: messagesCollectionView)
return cell
case .photo, .video:
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MediaMessageCell", for: indexPath) as? MediaMessageCell else {
fatalError("Unable to dequeue MediaMessageCell")
}
let cell = collectionView.dequeueReusableCell(MediaMessageCell.self, for: indexPath)
cell.configure(with: message, at: indexPath, and: messagesCollectionView)
return cell
case .location:
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "LocationMessageCell", for: indexPath) as? LocationMessageCell else {
fatalError("Unable to dequeue LocationMessageCell")
}
let cell = collectionView.dequeueReusableCell(LocationMessageCell.self, for: indexPath)
cell.configure(with: message, at: indexPath, and: messagesCollectionView)
return cell
}
@@ -252,7 +232,6 @@ extension MessagesViewController: UICollectionViewDataSource {
extension MessagesViewController {
fileprivate func addKeyboardObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(handleKeyboardDidChangeState), name: .UIKeyboardWillChangeFrame, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleTextViewDidBeginEditing), name: .UITextViewTextDidBeginEditing, object: messageInputBar.inputTextView)
+5 -5
View File
@@ -49,11 +49,11 @@ public class NSLayoutConstraintSet {
self.height = height
}
/// All of the currently configured constraints
private var availableConstraints: [NSLayoutConstraint] {
return [top, bottom, left, right, centerX, centerY, width, height]
.flatMap {$0}
}
/// All of the currently configured constraints
private var availableConstraints: [NSLayoutConstraint] {
return [top, bottom, left, right, centerX, centerY, width, height]
.flatMap {$0}
}
/// Activates all of the non-nil constraints
///
+1
View File
@@ -25,6 +25,7 @@
import UIKit
open class TextMessageCell: MessageCollectionViewCell<MessageLabel> {
open override class func reuseIdentifier() -> String { return "messagekit.cell.text" }
// MARK: - Properties
+36
View File
@@ -0,0 +1,36 @@
//
// UICollectionView+Extensions.swift
// MessageKit
//
// Created by Frederic Barthelemy on 10/3/17.
// Copyright © 2017 MessageKit. All rights reserved.
//
import Foundation
/// Optional Cell Protocol to Simplify registration/cell type loading in a generic way
protocol CollectionViewReusable: class {
static func reuseIdentifier() -> String
}
extension UICollectionView {
/// Registers a particular cell using its reuse-identifier
func register<CellType: UICollectionViewCell & CollectionViewReusable>(_ cellClass: CellType.Type) {
register(cellClass, forCellWithReuseIdentifier: CellType.reuseIdentifier())
}
/// Registers a reusable view for a specific SectionKind
func register<ViewType: UICollectionReusableView & CollectionViewReusable>(_ headerFooterClass: ViewType.Type, forSupplementaryViewOfKind kind: String) {
register(headerFooterClass,
forSupplementaryViewOfKind: kind,
withReuseIdentifier: ViewType.reuseIdentifier())
}
/// Generically dequeues a cell of the correct type allowing you to avoid scattering your code with guard-let-else-fatal
func dequeueReusableCell<CellType: UICollectionViewCell & CollectionViewReusable>(_ cellClass: CellType.Type, for indexPath: IndexPath) -> CellType {
guard let cell = dequeueReusableCell(withReuseIdentifier: cellClass.reuseIdentifier(), for: indexPath) as? CellType else {
fatalError("Unable to dequeue \(String(describing: cellClass)) with reuseId of \(cellClass.reuseIdentifier())")
}
return cell
}
}
+7 -7
View File
@@ -32,13 +32,13 @@ extension UIView {
}
translatesAutoresizingMaskIntoConstraints = false
let constraints: [NSLayoutConstraint] = [
leftAnchor.constraint(equalTo: superview.leftAnchor),
rightAnchor.constraint(equalTo: superview.rightAnchor),
topAnchor.constraint(equalTo: superview.topAnchor),
bottomAnchor.constraint(equalTo: superview.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)
let constraints: [NSLayoutConstraint] = [
leftAnchor.constraint(equalTo: superview.leftAnchor),
rightAnchor.constraint(equalTo: superview.rightAnchor),
topAnchor.constraint(equalTo: superview.topAnchor),
bottomAnchor.constraint(equalTo: superview.bottomAnchor)
]
NSLayoutConstraint.activate(constraints)
}
@discardableResult