Skip to content

Commit

Permalink
Merge pull request #58 from zwang/dev
Browse files Browse the repository at this point in the history
Time separators in ChattoApp. Also removes dynamicType when fetching resources from the framework.
  • Loading branch information
diegosanchezr committed Mar 13, 2016
2 parents 2733b83 + 1699199 commit 78aa23d
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,6 @@ public class MessageViewModelDefaultBuilder {

public func createMessageViewModel(message: MessageModelProtocol) -> MessageViewModelProtocol {
// Override to use default avatarImage
return MessageViewModel(dateFormatter: self.dynamicType.dateFormatter, showsTail: false, messageModel: message, avatarImage: nil)
return MessageViewModel(dateFormatter: MessageViewModelDefaultBuilder.dateFormatter, showsTail: false, messageModel: message, avatarImage: nil)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,19 @@ public class PhotoMessageCollectionViewCellDefaultStyle: PhotoMessageCollectionV
lazy private var baseStyle = BaseMessageCollectionViewCellDefaultStyle()

lazy private var maskImageIncomingTail: UIImage = {
return UIImage(named: "bubble-incoming-tail", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)!
return UIImage(named: "bubble-incoming-tail", inBundle: NSBundle(forClass: PhotoMessageCollectionViewCellDefaultStyle.self), compatibleWithTraitCollection: nil)!
}()

lazy private var maskImageIncomingNoTail: UIImage = {
return UIImage(named: "bubble-incoming", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)!
return UIImage(named: "bubble-incoming", inBundle: NSBundle(forClass: PhotoMessageCollectionViewCellDefaultStyle.self), compatibleWithTraitCollection: nil)!
}()

lazy private var maskImageOutgoingTail: UIImage = {
return UIImage(named: "bubble-outgoing-tail", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)!
return UIImage(named: "bubble-outgoing-tail", inBundle: NSBundle(forClass: PhotoMessageCollectionViewCellDefaultStyle.self), compatibleWithTraitCollection: nil)!
}()

lazy private var maskImageOutgoingNoTail: UIImage = {
return UIImage(named: "bubble-outgoing", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)!
return UIImage(named: "bubble-outgoing", inBundle: NSBundle(forClass: PhotoMessageCollectionViewCellDefaultStyle.self), compatibleWithTraitCollection: nil)!
}()

lazy private var placeholderBackgroundIncoming: UIImage = {
Expand All @@ -69,7 +69,7 @@ public class PhotoMessageCollectionViewCellDefaultStyle: PhotoMessageCollectionV
}()

lazy private var placeholderIcon: UIImage = {
return UIImage(named: "photo-bubble-placeholder-icon", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)!
return UIImage(named: "photo-bubble-placeholder-icon", inBundle: NSBundle(forClass: PhotoMessageCollectionViewCellDefaultStyle.self), compatibleWithTraitCollection: nil)!
}()

public func maskingImage(viewModel viewModel: PhotoMessageViewModelProtocol) -> UIImage {
Expand Down
4 changes: 2 additions & 2 deletions ChattoAdditions/Source/Input/Photos/LiveCameraCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ class LiveCameraCell: UICollectionViewCell {
private func updateIcon() {
switch self.authorizationStatus {
case .NotDetermined, .Authorized:
self.iconImageView.image = UIImage(named: Constants.cameraImageName, inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)
self.iconImageView.image = UIImage(named: Constants.cameraImageName, inBundle: NSBundle(forClass: LiveCameraCell.self), compatibleWithTraitCollection: nil)
case .Restricted, .Denied:
self.iconImageView.image = UIImage(named: Constants.lockedCameraImageName, inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)
self.iconImageView.image = UIImage(named: Constants.lockedCameraImageName, inBundle: NSBundle(forClass: LiveCameraCell.self), compatibleWithTraitCollection: nil)
}
self.setNeedsLayout()
}
Expand Down
6 changes: 3 additions & 3 deletions ChattoAdditions/Source/Input/Photos/PhotosChatInputItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ import Foundation
lazy private var internalTabView: UIButton = {
var button = UIButton(type: .Custom)
button.exclusiveTouch = true
button.setImage(UIImage(named: "camera-icon-unselected", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil), forState: .Normal)
button.setImage(UIImage(named: "camera-icon-selected", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil), forState: .Highlighted)
button.setImage(UIImage(named: "camera-icon-selected", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil), forState: .Selected)
button.setImage(UIImage(named: "camera-icon-unselected", inBundle: NSBundle(forClass: PhotosChatInputItem.self), compatibleWithTraitCollection: nil), forState: .Normal)
button.setImage(UIImage(named: "camera-icon-selected", inBundle: NSBundle(forClass: PhotosChatInputItem.self), compatibleWithTraitCollection: nil), forState: .Highlighted)
button.setImage(UIImage(named: "camera-icon-selected", inBundle: NSBundle(forClass: PhotosChatInputItem.self), compatibleWithTraitCollection: nil), forState: .Selected)
return button
}()

Expand Down
2 changes: 1 addition & 1 deletion ChattoAdditions/Source/Input/Photos/PhotosInputCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class PhotosInputPlaceholderCell: UICollectionViewCell {
private func commonInit() {
self.imageView = UIImageView()
self.imageView.contentMode = .Center
self.imageView.image = UIImage(named: Constants.imageName, inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)
self.imageView.image = UIImage(named: Constants.imageName, inBundle: NSBundle(forClass: PhotosInputPlaceholderCell.self), compatibleWithTraitCollection: nil)
self.contentView.addSubview(self.imageView)
self.contentView.backgroundColor = Constants.backgroundColor
}
Expand Down
6 changes: 3 additions & 3 deletions ChattoAdditions/Source/Input/Text/TextChatInputItem.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ import Foundation
lazy private var internalTabView: UIButton = {
var button = UIButton(type: .Custom)
button.exclusiveTouch = true
button.setImage(UIImage(named: "text-icon-unselected", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil), forState: .Normal)
button.setImage(UIImage(named: "text-icon-selected", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil), forState: .Highlighted)
button.setImage(UIImage(named: "text-icon-selected", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil), forState: .Selected)
button.setImage(UIImage(named: "text-icon-unselected", inBundle: NSBundle(forClass: TextChatInputItem.self), compatibleWithTraitCollection: nil), forState: .Normal)
button.setImage(UIImage(named: "text-icon-selected", inBundle: NSBundle(forClass: TextChatInputItem.self), compatibleWithTraitCollection: nil), forState: .Highlighted)
button.setImage(UIImage(named: "text-icon-selected", inBundle: NSBundle(forClass: TextChatInputItem.self), compatibleWithTraitCollection: nil), forState: .Selected)
return button
}()

Expand Down
4 changes: 4 additions & 0 deletions ChattoApp/ChattoApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
C3F91DCC1C75EFE300D461D2 /* SendingStatusCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F91DC91C75EFE300D461D2 /* SendingStatusCollectionViewCell.swift */; };
C3F91DCD1C75EFE300D461D2 /* SendingStatusCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C3F91DCA1C75EFE300D461D2 /* SendingStatusCollectionViewCell.xib */; };
C3F91DCE1C75EFE300D461D2 /* SendingStatusPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F91DCB1C75EFE300D461D2 /* SendingStatusPresenter.swift */; };
FE1A697B1C93FF10004DF45A /* TimestampSeparatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE1A697A1C93FF10004DF45A /* TimestampSeparatorView.swift */; };
FE2D050B1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE2D050A1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -97,6 +98,7 @@
C3F91DC91C75EFE300D461D2 /* SendingStatusCollectionViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendingStatusCollectionViewCell.swift; sourceTree = "<group>"; };
C3F91DCA1C75EFE300D461D2 /* SendingStatusCollectionViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SendingStatusCollectionViewCell.xib; sourceTree = "<group>"; };
C3F91DCB1C75EFE300D461D2 /* SendingStatusPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SendingStatusPresenter.swift; sourceTree = "<group>"; };
FE1A697A1C93FF10004DF45A /* TimestampSeparatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TimestampSeparatorView.swift; sourceTree = "<group>"; };
FE2D050A1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseMessageCollectionViewCellAvatarStyle.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -211,6 +213,7 @@
C3F91DC81C75EFE300D461D2 /* Sending status */,
C3F91DB11C75EF9E00D461D2 /* Text Messages */,
FE2D050A1C915ADB006F902B /* BaseMessageCollectionViewCellAvatarStyle.swift */,
FE1A697A1C93FF10004DF45A /* TimestampSeparatorView.swift */,
);
path = Source;
sourceTree = "<group>";
Expand Down Expand Up @@ -452,6 +455,7 @@
C3F91DC61C75EF9E00D461D2 /* DemoTextMessageViewModel.swift in Sources */,
C3F91DC01C75EF9E00D461D2 /* DemoPhotoMessageHandler.swift in Sources */,
C3F91DBC1C75EF9E00D461D2 /* DemoChatViewController.swift in Sources */,
FE1A697B1C93FF10004DF45A /* TimestampSeparatorView.swift in Sources */,
C3F91DBD1C75EF9E00D461D2 /* FakeDataSource.swift in Sources */,
C3F91DB61C75EF9E00D461D2 /* AppDelegate.swift in Sources */,
C3F91DCE1C75EFE300D461D2 /* SendingStatusPresenter.swift in Sources */,
Expand Down
15 changes: 15 additions & 0 deletions ChattoApp/ChattoApp/Source/ChatItemsDemoDecorator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,42 @@ final class ChatItemsDemoDecorator: ChatItemsDecoratorProtocol {

for (index, chatItem) in chatItems.enumerate() {
let next: ChatItemProtocol? = (index + 1 < chatItems.count) ? chatItems[index + 1] : nil
let prev: ChatItemProtocol? = (index > 0) ? chatItems[index - 1] : nil

let bottomMargin = self.separationAfterItem(chatItem, next: next)
var showsTail = false
var additionalItems = [DecoratedChatItem]()

var showWeekDayDateStamp = false
if let currentMessage = chatItem as? MessageModelProtocol {
if let nextMessage = next as? MessageModelProtocol {
showsTail = currentMessage.senderId != nextMessage.senderId
} else {
showsTail = true
}

if let prevMsg = prev as? MessageModelProtocol {
showWeekDayDateStamp = NSCalendar.currentCalendar().compareDate(currentMessage.date, toDate: prevMsg.date, toUnitGranularity: NSCalendarUnit.Day) != NSComparisonResult.OrderedSame
} else {
showWeekDayDateStamp = true
}

if self.showsStatusForMessage(currentMessage) {
additionalItems.append(
DecoratedChatItem(
chatItem: SendingStatusModel(uid: "\(currentMessage.uid)-decoration-status", status: currentMessage.status),
decorationAttributes: nil)
)
}

if showWeekDayDateStamp {
let dateTimeStamp = DecoratedChatItem(chatItem: WeekDayDatestamp(date: currentMessage.date), decorationAttributes: ChatItemDecorationAttributes(bottomMargin: 0, showsTail: false))
decoratedChatItems.append(dateTimeStamp)
}
}



decoratedChatItems.append(DecoratedChatItem(
chatItem: chatItem,
decorationAttributes: ChatItemDecorationAttributes(bottomMargin: bottomMargin, showsTail: showsTail))
Expand Down
5 changes: 3 additions & 2 deletions ChattoApp/ChattoApp/Source/DemoChatViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class DemoChatViewController: BaseChatViewController {

override func viewDidLoad() {
super.viewDidLoad()
let image = UIImage(named: "bubble-incoming-tail-border", inBundle: NSBundle(forClass: self.dynamicType), compatibleWithTraitCollection: nil)?.bma_tintWithColor(UIColor.blueColor())
let image = UIImage(named: "bubble-incoming-tail-border", inBundle: NSBundle(forClass: DemoChatViewController.self), compatibleWithTraitCollection: nil)?.bma_tintWithColor(UIColor.blueColor())
super.chatItemsDecorator = ChatItemsDemoDecorator()
let addIncomingMessageButton = UIBarButtonItem(image: image, style: .Plain, target: self, action: "addRandomIncomingMessage")
self.navigationItem.rightBarButtonItem = addIncomingMessageButton
Expand Down Expand Up @@ -83,7 +83,8 @@ class DemoChatViewController: BaseChatViewController {
interactionHandler: DemoPhotoMessageHandler(baseHandler: self.baseMessageHandler)
)
],
SendingStatusModel.chatItemType: [SendingStatusPresenterBuilder()]
SendingStatusModel.chatItemType: [SendingStatusPresenterBuilder()],
WeekDayDatestamp.chatItemType: [WeekDayDatestampPresenterBuilder()]
]
}

Expand Down
148 changes: 148 additions & 0 deletions ChattoApp/ChattoApp/Source/TimestampSeparatorView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
The MIT License (MIT)

Copyright (c) 2016-present Zhao Wang.

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 UIKit
import Chatto

extension NSDate {
// Have a time stamp formatter to avoid keep creating new ones. This improves performance
private static let weekdayAndDateStampDateFormatter: NSDateFormatter = {
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone.localTimeZone()
dateFormatter.dateFormat = "EEEE, MMM dd yyyy" // "Monday, Mar 7 2016"
return dateFormatter
}()

func toWeekDayAndDateString() -> String {
return NSDate.weekdayAndDateStampDateFormatter.stringFromDate(self)
}
}

class WeekDayDatestamp: ChatItemProtocol {
let uid: String
let type: String = WeekDayDatestamp.chatItemType

static var chatItemType: ChatItemType {
return "WeekDayDatestamp"
}

init(date: NSDate) {
let datestampString = date.toWeekDayAndDateString()
self.uid = datestampString.uppercaseString
}
}

class WeekDayDatestampCollectionViewCell: UICollectionViewCell {
private let label: UILabel = UILabel()

override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}

private func commonInit() {
label.font = UIFont.systemFontOfSize(12)
label.textAlignment = .Center
label.textColor = UIColor.grayColor()

self.contentView.addSubview(label)
}

var text: String = "" {
didSet {
if oldValue != text {
setTextOnLabel(text)
}
}
}

private func setTextOnLabel(text: String) {
label.text = text
label.sizeToFit()
setNeedsLayout()
}

override func layoutSubviews() {
super.layoutSubviews()
label.center = self.contentView.center
}
}

public class WeekDayDatestampPresenterBuilder: ChatItemPresenterBuilderProtocol {

public func canHandleChatItem(chatItem: ChatItemProtocol) -> Bool {
return chatItem is WeekDayDatestamp
}

public func createPresenterWithChatItem(chatItem: ChatItemProtocol) -> ChatItemPresenterProtocol {
assert(self.canHandleChatItem(chatItem))
return WeekDayDatestampPresenter(weekDayDatestamp: chatItem as! WeekDayDatestamp)
}

public var presenterType: ChatItemPresenterProtocol.Type {
return WeekDayDatestampPresenter.self
}
}

class WeekDayDatestampPresenter: ChatItemPresenterProtocol {

let weekDayDatestamp: WeekDayDatestamp
init (weekDayDatestamp: WeekDayDatestamp) {
self.weekDayDatestamp = weekDayDatestamp
}

private static let cellReuseIdentifier = WeekDayDatestampCollectionViewCell.self.description()

static func registerCells(collectionView: UICollectionView) {
collectionView.registerClass(WeekDayDatestampCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
}

func dequeueCell(collectionView collectionView: UICollectionView, indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(WeekDayDatestampPresenter.cellReuseIdentifier, forIndexPath: indexPath)
return cell
}

func configureCell(cell: UICollectionViewCell, decorationAttributes: ChatItemDecorationAttributesProtocol?) {
guard let datestamp = cell as? WeekDayDatestampCollectionViewCell else {
assert(false, "expecting status cell")
return
}

datestamp.text = weekDayDatestamp.uid
}

var canCalculateHeightInBackground: Bool {
return true
}

func heightForCell(maximumWidth width: CGFloat, decorationAttributes: ChatItemDecorationAttributesProtocol?) -> CGFloat {
return 24
}
}

0 comments on commit 78aa23d

Please sign in to comment.