Add updating logic to text message (#178)

* Add updating logic to text message

* Change Observable to class

* Fix avatar hiding

* Move willBeShown/wasHidden declarations to common protocol
This commit is contained in:
Max Konovalov 2016-08-01 01:53:52 +04:00 committed by Diego Sánchez
parent 7541a5ab64
commit 1ef46a0e35
7 changed files with 50 additions and 13 deletions

View File

@ -97,9 +97,7 @@ public class BaseMessagePresenter<BubbleViewT, ViewModelBuilderT, InteractionHan
public func configureCell(cell: CellT, decorationAttributes: ChatItemDecorationAttributes, animated: Bool, additionalConfiguration: (() -> Void)?) {
cell.performBatchUpdates({ () -> Void in
self.messageViewModel.showsTail = decorationAttributes.showsTail
if !decorationAttributes.canShowAvatar {
self.messageViewModel.avatarImage.value = nil
}
cell.avatarView.hidden = !decorationAttributes.canShowAvatar
cell.bubbleView.userInteractionEnabled = true // just in case something went wrong while showing UIMenuController
cell.baseStyle = self.cellStyle
cell.messageViewModel = self.messageViewModel

View File

@ -54,6 +54,8 @@ public protocol MessageViewModelProtocol: class { // why class? https://gist.git
public protocol DecoratedMessageViewModelProtocol: MessageViewModelProtocol {
var messageViewModel: MessageViewModelProtocol { get }
func willBeShown()
func wasHidden()
}
extension DecoratedMessageViewModelProtocol {

View File

@ -65,6 +65,7 @@ public class PhotoMessagePresenter<ViewModelBuilderT, InteractionHandlerT where
let updateClosure = { [weak self] (old: Any, new: Any) -> () in
self?.updateCurrentCell()
}
viewModel.avatarImage.observe(self, closure: updateClosure)
viewModel.image.observe(self, closure: updateClosure)
viewModel.transferDirection.observe(self, closure: updateClosure)
viewModel.transferProgress.observe(self, closure: updateClosure)

View File

@ -42,13 +42,6 @@ public protocol PhotoMessageViewModelProtocol: DecoratedMessageViewModelProtocol
var transferStatus: Observable<TransferStatus> { get set }
var image: Observable<UIImage?> { get set }
var imageSize: CGSize { get }
func willBeShown() // Optional
func wasHidden() // Optional
}
public extension PhotoMessageViewModelProtocol {
func willBeShown() {}
func wasHidden() {}
}
public class PhotoMessageViewModel<PhotoMessageModelT: PhotoMessageModelProtocol>: PhotoMessageViewModelProtocol {

View File

@ -64,6 +64,26 @@ public class TextMessagePresenter<ViewModelBuilderT, InteractionHandlerT where
let identifier = self.messageViewModel.isIncoming ? "text-message-incoming" : "text-message-outcoming"
return collectionView.dequeueReusableCellWithReuseIdentifier(identifier, forIndexPath: indexPath)
}
public override func createViewModel() -> ViewModelBuilderT.ViewModelT {
let viewModel = self.viewModelBuilder.createViewModel(self.messageModel)
let updateClosure = { [weak self] (old: Any, new: Any) -> () in
self?.updateCurrentCell()
}
viewModel.avatarImage.observe(self, closure: updateClosure)
return viewModel
}
public var textCell: TextMessageCollectionViewCell? {
if let cell = self.cell {
if let textCell = cell as? TextMessageCollectionViewCell {
return textCell
} else {
assert(false, "Invalid cell was given to presenter!")
}
}
return nil
}
public override func configureCell(cell: BaseMessageCollectionViewCell<TextBubbleView>, decorationAttributes: ChatItemDecorationAttributes, animated: Bool, additionalConfiguration: (() -> Void)?) {
guard let cell = cell as? TextMessageCollectionViewCell else {
@ -78,6 +98,20 @@ public class TextMessagePresenter<ViewModelBuilderT, InteractionHandlerT where
additionalConfiguration?()
}
}
public override func cellWillBeShown() {
self.messageViewModel.willBeShown()
}
public override func cellWasHidden() {
self.messageViewModel.wasHidden()
}
public func updateCurrentCell() {
if let cell = self.textCell, decorationAttributes = self.decorationAttributes {
self.configureCell(cell, decorationAttributes: decorationAttributes, animated: self.itemVisibility != .Appearing, additionalConfiguration: nil)
}
}
public override func canShowMenu() -> Bool {
return true

View File

@ -39,6 +39,14 @@ public class TextMessageViewModel<TextMessageModelT: TextMessageModelProtocol>:
self.textMessage = textMessage
self.messageViewModel = messageViewModel
}
public func willBeShown() {
// Need to declare empty. Otherwise subclass code won't execute (as of Xcode 7.2)
}
public func wasHidden() {
// Need to declare empty. Otherwise subclass code won't execute (as of Xcode 7.2)
}
}
public class TextMessageViewModelDefaultBuilder<TextMessageModelT: TextMessageModelProtocol>: ViewModelBuilderProtocol {

View File

@ -25,7 +25,8 @@
import Foundation
// Be aware this is not thread safe!
public struct Observable<T> {
// Why class? https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20160711/002580.html
public class Observable<T> {
public init(_ value: T) {
self.value = value
@ -40,12 +41,12 @@ public struct Observable<T> {
}
}
public mutating func observe(observer: AnyObject, closure: (old: T, new: T) -> ()) {
public func observe(observer: AnyObject, closure: (old: T, new: T) -> ()) {
self.observers.append(Observer(owner: observer, closure: closure))
self.cleanDeadObservers()
}
private mutating func cleanDeadObservers() {
private func cleanDeadObservers() {
self.observers = self.observers.filter { $0.owner != nil }
}