Chatto/README.md

160 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Chatto [![Build Status](https://travis-ci.org/badoo/Chatto.svg?branch=master)](https://travis-ci.org/badoo/Chatto) [![codecov.io](https://codecov.io/github/badoo/Chatto/coverage.svg?branch=master)](https://codecov.io/github/badoo/Chatto?branch=master) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Chatto.svg)](https://img.shields.io/cocoapods/v/Chatto.svg) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
`Chatto` is a Swift lightweight framework to build chat applications. It's been designed to be extensible and performant. Along with `Chatto` there is `ChattoAdditions`, a companion framework which includes cells for messages and an extensible input component. You can find more details about how it was implemented in our [blog](https://techblog.badoo.com/blog/2015/12/04/how-we-made-chatto/). See them in action!
<div align="center">
<img src="./readme-images/readme-pic-1.png" />
<img src="./readme-images/readme-pic-2.png" />
<img src="./readme-images/readme-pic-3.png" />
<img src="./readme-images/readme-pic-4.png" />
</div>
## Features
- Calculation of collection view changes and layout in background
- Supports pagination in both directions and autoloading
- Message count contention for fast pagination and rotation with thousands of messsages
- Accessory view revealing by swiping from right
- Interactive keyboard dismissal
- Text bubbles
- Photo bubbles
- Extensible input bar
## How to use
1. Subclass BaseChatViewController
2. Override `createChatInputView()` to use `ChattoAdditions.ChatInputBar` or provide your own component
3. Provide a data source with your messages
4. Override `createPresenterBuilders()`. There will be a presenter for each message that will be responsible for the UI of that message.
```swift
override func createPresenterBuilders() -> [ChatItemType: [ChatItemPresenterBuilderProtocol]] {
return [
TextMessageModel.chatItemType: [
TextMessagePresenterBuilder(
viewModelBuilder: TextMessageViewModelDefaultBuilder<TextMessageModel>(),
interactionHandler: TextMessageHandler(baseHandler: self.baseMessageHandler)
)
]
]
}
override func createChatInputView() -> UIView {
let chatInputView = ChatInputBar.loadNib()
self.configureChatInputBar(chatInputView)
self.chatInputPresenter = ChatInputBarPresenter(chatInputView: chatInputView, chatInputItems: self.createChatInputItems())
return chatInputView
}
override func viewDidLoad() {
super.viewDidLoad()
self.chatDataSource = self.myDataSource
}
```
### Data source
The only requirement for your data source items is to conform to the ChatItemProtocol protocol, which basically asks for a unique identifier (uid) and a type. The uid will be used to calculate changes in the collection view and the type to quickly find a presenter builder for it. Your data source must conform to ChatDataSourceProtocol:
```swift
public protocol ChatDataSourceProtocol: class {
var hasMoreNext: Bool { get }
var hasMorePrevious: Bool { get }
var chatItems: [ChatItemProtocol] { get }
weak var delegate: ChatDataSourceDelegateProtocol? { get set }
func loadNext(completion: () -> Void)
func loadPrevious(completion: () -> Void)
func adjustNumberOfMessages(preferredMaxCount preferredMaxCount: Int?, focusPosition: Double, completion:(didAdjust: Bool) -> Void) // If you want, implement message count contention for performance, otherwise just call completion(false)
}
```
If you want to handle smooth loading of new pages, or more challenging, smooth rotation with thousands of messages (calculating 10K text message sizes can take ~15s on iPhone 4s) you should opt-in for adjustNumberOfMessages(preferredMaxCount:focusPosition:completion:). See how it's done in ChattoApp!
### Presenters
The presenter is the key entity that enables scalability in `Chatto`'s architecture. Each message will be paired with a presenter who will be responsible for the UI related to that message (cell configuration, calculation of size, user handling,... ). Take a look at `TextMessagePresenter`, `PhotoMessagePresenter` in ChattoAdditions and `ChatItemPresenterProtocol`
```swift
public protocol ChatItemPresenterProtocol: class {
static func registerCells(collectionView: UICollectionView)
var canCalculateHeightInBackground: Bool { get } // Default is false
func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat
func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell
func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?)
func cellWillBeShown(cell: UICollectionViewCell) // optional
func cellWasHidden(cell: UICollectionViewCell) // optional
func shouldShowMenu() -> Bool // optional. Default is false
func canPerformMenuControllerAction(action: Selector) -> Bool // optional. Default is false
func performMenuControllerAction(action: Selector) // optional
}
```
### Decoration
As you may have noticed, there's an interesting decorationAttributes parameter in `configureCell(_:decorationAttributes:)`
```swift
public protocol ChatItemDecorationAttributesProtocol {
var bottomMargin: CGFloat { get }
}
```
Decoration attributes have two different purposes:
1. Provide margins for `ChatCollectionViewLayout`
2. Provide context to your presenters so you can further customize your UI (for instance to flag if a bubble should show the tail)
By default, no decorationAttributes will be provided to your presenters, and the margin between messages will be zero. You may opt-in for a message decorator as in ChattoApp
```swift
public protocol ChatItemsDecoratorProtocol {
func decorateItems(chatItems: [ChatItemProtocol]) -> [DecoratedChatItem]
}
```
In your decorator you may even create new ChatItems. The decorator in ChattoApp not only provides different margins for the bubbles, but it also inserts new ChatItems that represents sending/failed status. Decoration happens in background so the UI stays responsive while scrolling.
### Input bar
You can return your own input component when overriding `createChatInputView()` or use `ChattoAdditions.ChatInputBar`
`ChattoAdditions.ChatInputBar` is an extensible component on its own. Each input item defines a `tabView` that serves as the call to action to activate that input item and an `inputView` with your custom input UI. ChatInputBarPresenter will take a collection of `ChatInputItemProtocol` and it will configure ChatInputBar to display them.
```swift
public protocol ChatInputItemProtocol: AnyObject {
var tabView: UIView { get }
var inputView: UIView? { get }
var presentationMode: ChatInputItemPresentationMode { get }
var showsSendButton: Bool { get }
var selected: Bool { get set }
func handleInput(input: AnyObject)
}
```
## How to install
### CocoaPods
1. Make sure `use_frameworks!` is added to your `Podfile`.
2. Include the following in your `Podfile`:
```
pod 'Chatto', '= 1.0.0'
pod 'ChattoAdditions', '= 1.0.0' # if you want to use the cells or the input component
```
If you like to live on the bleeding edge, you can use the `master` branch with:
```
pod 'Chatto', :git => 'https://github.com/badoo/Chatto'
pod 'ChattoAdditions', :git => 'https://github.com/badoo/Chatto'
```
3. Run `pod install`
### Carthage
If youre using [Carthage](https://github.com/Carthage/Carthage#if-youre-building-for-ios-tvos-or-watchos), simply add Chatto to your Cartfile:
```
github "badoo/Chatto"
```
### Manually
1. Clone, add as a submodule or [download.](https://github.com/badoo/Chatto/archive/master.zip)
2. Drag and drop `Chatto` and/or `ChattoAdditions` project to your workspace
3. Add `Chatto` and/or `ChattoAdditions` to Embedded binaries
## License
Source code is distributed under MIT license.
##Blog
Read more on our [tech blog](http://techblog.badoo.com/) or explore our other [open source projects](https://github.com/badoo)