Skip to content

Commit

Permalink
AvatarView (MessageKit#31)
Browse files Browse the repository at this point in the history
* Add AvatarView along with `AvatarView.Playground` Implemented code review changes.

* Add tests because your are supposed to add tests for everything.

* Replace references to the Avatar with AvatarView. Update Example Project.

* Updated my `swiftLint` and fixed issues.
  • Loading branch information
MacMeDan authored Aug 6, 2017
1 parent 6fa2d17 commit 3b94565
Show file tree
Hide file tree
Showing 11 changed files with 254 additions and 65 deletions.
7 changes: 3 additions & 4 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
line_length:
warning: 150
ignores_comments: true

disabled_rules:
identifier_name
- identifier_name
- trailing_whitespace
- line_length
4 changes: 2 additions & 2 deletions Example/Sources/ConversationViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ extension ConversationViewController: MessagesDataSource {

extension ConversationViewController: MessagesDisplayDataSource {

func avatarForMessage(_ message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> Avatar {
func avatarForMessage(_ message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> AvatarView {
let image = isFromCurrentSender(message: message) ? #imageLiteral(resourceName: "Steve-Jobs") : #imageLiteral(resourceName: "Tim-Cook")
return Avatar(placeholderImage: image)
return AvatarView(image: image)
}

func headerForMessage(_ message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageHeaderView? {
Expand Down
14 changes: 10 additions & 4 deletions MessageKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
372F6AEB1F36C15600B57FBD /* AvatarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372F6AEA1F36C15600B57FBD /* AvatarView.swift */; };
372F6AEF1F36C61000B57FBD /* AvatarViewTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 372F6AEE1F36C61000B57FBD /* AvatarViewTests.swift */; };
882D75841DE507320033F95F /* MessagesDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 882D75831DE507320033F95F /* MessagesDataSource.swift */; };
888CEBFC1D3FD525005178DE /* MessagesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 888CEBFB1D3FD525005178DE /* MessagesViewController.swift */; };
88916B2D1CF0DF2F00469F91 /* MessageKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 88916B221CF0DF2F00469F91 /* MessageKit.framework */; };
Expand All @@ -16,7 +18,6 @@
B015E8191F24623D007EDFB6 /* MessagesCollectionViewLayoutAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015E8181F24623D007EDFB6 /* MessagesCollectionViewLayoutAttributes.swift */; };
B015E81F1F259D8E007EDFB6 /* MessageInputBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B015E81E1F259D8E007EDFB6 /* MessageInputBarDelegate.swift */; };
B03FF9AF1F31BB1200754FE5 /* MessageCellDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B03FF9AE1F31BB1200754FE5 /* MessageCellDelegate.swift */; };
B0655A261F23D6C500542A83 /* Avatar.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0655A251F23D6C500542A83 /* Avatar.swift */; };
B0655A281F23D71400542A83 /* MessageDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0655A271F23D71400542A83 /* MessageDirection.swift */; };
B0655A2A1F23D77200542A83 /* Sender.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0655A291F23D77200542A83 /* Sender.swift */; };
B0655A2C1F23D81600542A83 /* MessageData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0655A2B1F23D81600542A83 /* MessageData.swift */; };
Expand All @@ -43,6 +44,9 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
372F6AEA1F36C15600B57FBD /* AvatarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvatarView.swift; sourceTree = "<group>"; };
372F6AED1F36C1C100B57FBD /* AvatarView.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = AvatarView.playground; sourceTree = "<group>"; };
372F6AEE1F36C61000B57FBD /* AvatarViewTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvatarViewTests.swift; sourceTree = "<group>"; };
882D75831DE507320033F95F /* MessagesDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagesDataSource.swift; sourceTree = "<group>"; };
888CEBFB1D3FD525005178DE /* MessagesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagesViewController.swift; sourceTree = "<group>"; };
88916B221CF0DF2F00469F91 /* MessageKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MessageKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand All @@ -55,7 +59,6 @@
B015E8181F24623D007EDFB6 /* MessagesCollectionViewLayoutAttributes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagesCollectionViewLayoutAttributes.swift; sourceTree = "<group>"; };
B015E81E1F259D8E007EDFB6 /* MessageInputBarDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageInputBarDelegate.swift; sourceTree = "<group>"; };
B03FF9AE1F31BB1200754FE5 /* MessageCellDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageCellDelegate.swift; sourceTree = "<group>"; };
B0655A251F23D6C500542A83 /* Avatar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Avatar.swift; sourceTree = "<group>"; };
B0655A271F23D71400542A83 /* MessageDirection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageDirection.swift; sourceTree = "<group>"; };
B0655A291F23D77200542A83 /* Sender.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Sender.swift; sourceTree = "<group>"; };
B0655A2B1F23D81600542A83 /* MessageData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageData.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -127,6 +130,7 @@
children = (
88916B421CF0DF5900469F91 /* Info.plist */,
88916B431CF0DF5900469F91 /* MessageKitTests.swift */,
372F6AEE1F36C61000B57FBD /* AvatarViewTests.swift */,
);
path = Tests;
sourceTree = SOURCE_ROOT;
Expand All @@ -143,7 +147,6 @@
B09643991F295D58004D0129 /* Models */ = {
isa = PBXGroup;
children = (
B0655A251F23D6C500542A83 /* Avatar.swift */,
B0655A291F23D77200542A83 /* Sender.swift */,
B0655A2B1F23D81600542A83 /* MessageData.swift */,
B0655A271F23D71400542A83 /* MessageDirection.swift */,
Expand All @@ -156,6 +159,8 @@
children = (
B0655A2D1F23D8BC00542A83 /* MessagesCollectionView.swift */,
B0655A4C1F244C0600542A83 /* MessageCollectionViewCell.swift */,
372F6AEA1F36C15600B57FBD /* AvatarView.swift */,
372F6AED1F36C1C100B57FBD /* AvatarView.playground */,
B0655A371F23EE8B00542A83 /* MessageInputBar.swift */,
B074EE921F35587100ABB8C8 /* MessageHeaderView.swift */,
B074EE941F35588A00ABB8C8 /* MessageFooterView.swift */,
Expand Down Expand Up @@ -335,7 +340,6 @@
B0655A2C1F23D81600542A83 /* MessageData.swift in Sources */,
B09643861F286C9E004D0129 /* String+Extensions.swift in Sources */,
B0655A281F23D71400542A83 /* MessageDirection.swift in Sources */,
B0655A261F23D6C500542A83 /* Avatar.swift in Sources */,
B015E81F1F259D8E007EDFB6 /* MessageInputBarDelegate.swift in Sources */,
B0655A2A1F23D77200542A83 /* Sender.swift in Sources */,
B074EE931F35587100ABB8C8 /* MessageHeaderView.swift in Sources */,
Expand All @@ -344,6 +348,7 @@
B074EE951F35588A00ABB8C8 /* MessageFooterView.swift in Sources */,
B09643901F289142004D0129 /* UIColor+Extensions.swift in Sources */,
B0655A381F23EE8B00542A83 /* MessageInputBar.swift in Sources */,
372F6AEB1F36C15600B57FBD /* AvatarView.swift in Sources */,
88916B471CF0DFE600469F91 /* MessageType.swift in Sources */,
B03FF9AF1F31BB1200754FE5 /* MessageCellDelegate.swift in Sources */,
B096438E1F2890FB004D0129 /* MessagesDisplayDataSource.swift in Sources */,
Expand All @@ -356,6 +361,7 @@
buildActionMask = 2147483647;
files = (
88916B451CF0DF5900469F91 /* MessageKitTests.swift in Sources */,
372F6AEF1F36C61000B57FBD /* AvatarViewTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
51 changes: 0 additions & 51 deletions Sources/Avatar.swift

This file was deleted.

37 changes: 37 additions & 0 deletions Sources/AvatarView.playground/Contents.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import UIKit
import MessageKit
import PlaygroundSupport

//: Discover what is possible with the Avatar Class
//Get an image
let testImage = #imageLiteral(resourceName: "NiceSelfi.jpg")

let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 200))

view.backgroundColor = UIColor.white

//: Uncomment any line to see how it changes the `Avatar`.
//: By default its a circlular avatar with a gray background and initals of ?
let avatar = AvatarView()

//: Configure any one of the initilization parameters and delete the ones you dont want to set.
//let avatar = AvatarView(size: 50, image: testImage, highlightedImage: testImage, initals: "PL", cornerRounding: 9)

//: Throw in just an image.
//let avatar = AvatarView(image: testImage)

//: Dont have an image just add the users initals
//let avatar = AvatarView(initals: "PL")

//: Want rounded squares instead of circles just change the `cornderRounding`.
//let avatar = AvatarView(image: testImage, cornerRounding: 9)

//:Change its size
//let avatar = AvatarView(size: 5)

//let avatar = AvatarView(size: 100)

//: Everything has a default so if you dont want to set it then you dont have to.

//Helper method.
PlaygroundPage.current.liveView = avatar
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions Sources/AvatarView.playground/contents.xcplayground
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='ios'>
<timeline fileName='timeline.xctimeline'/>
</playground>
115 changes: 115 additions & 0 deletions Sources/AvatarView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
MIT License

Copyright (c) 2017 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

open class AvatarView: UIView {
// MARK: - Properties
internal var initalsLabel = UILabel()
internal var imageView = UIImageView()
internal var initals: String = "?"

// MARK: - initializers
override init(frame: CGRect) {
super.init(frame: frame)
prepareView()
}

convenience public init(size: CGFloat = 30, image: UIImage? = nil, highlightedImage: UIImage? = nil, initals inInitals: String = "?", cornerRounding: CGFloat? = nil) {
let frame = CGRect(x: 0, y: 0, width: size, height: size)
self.init(frame: frame)
setCorner(radius: cornerRounding)
setBackground(color: UIColor.gray)
imageView.image = image
imageView.highlightedImage = highlightedImage
initals = inInitals
prepareView()
}

convenience public init() {
let frame = CGRect(x: 0, y: 0, width: 30, height: 30)
self.init(frame: frame)
setBackground(color: UIColor.gray)
setCorner(radius: nil)
prepareView()
}

required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - internal methods

internal func prepareView() {
prepareInitalsLabel()
prepareImageView()
imageView.isHidden = imageView.image == nil
}

internal func prepareInitalsLabel() {
initalsLabel.text = initals
initalsLabel.textAlignment = .center
setInitalsFont()
addSubview(initalsLabel)
initalsLabel.center = center
initalsLabel.frame = frame
}

internal func prepareImageView() {
contentMode = .scaleAspectFill
layer.masksToBounds = true
clipsToBounds = true
addSubview(imageView)
imageView.contentMode = .scaleAspectFill
imageView.frame = frame
}

// MARK: - Open methods

open func set(image: UIImage) {
imageView.image = image
}

open func setInitalsFont(size: CGFloat = 16, color: UIColor = .white) {
initalsLabel.font = UIFont.systemFont(ofSize: size)
initalsLabel.textColor = color
}

open func setBackground(color: UIColor) {
backgroundColor = color
}

open func getImage() -> UIImage? {
return imageView.image
}

open func setCorner(radius: CGFloat?) {
guard let radius = radius else {
//if corner radius not set default to Circle
layer.cornerRadius = frame.height/2
return
}
layer.cornerRadius = radius
}
}
2 changes: 1 addition & 1 deletion Sources/MessagesDisplayDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public protocol MessagesDisplayDataSource: class, MessagesDataSource {

func messageColorFor(_ message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> UIColor

func avatarForMessage(_ message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> Avatar
func avatarForMessage(_ message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> AvatarView

func headerForMessage(_ message: MessageType, at indexPath: IndexPath, in messagesCollectionView: MessagesCollectionView) -> MessageHeaderView?

Expand Down
5 changes: 2 additions & 3 deletions Sources/MessagesViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,8 @@ extension MessagesViewController: UICollectionViewDataSource {
let message = displayDataSource.messageForItem(at: indexPath, in: messagesCollectionView)
let messageColor = displayDataSource.messageColorFor(message, at: indexPath, in: messagesCollectionView)
let avatar = displayDataSource.avatarForMessage(message, at: indexPath, in: messagesCollectionView)

cell.avatarImageView.image = avatar.image(highlighted: false)
cell.avatarImageView.highlightedImage = avatar.image(highlighted: true)
//TODO: replace this completely
cell.avatarImageView.image = avatar.getImage()
cell.messageContainerView.backgroundColor = messageColor
cell.configure(with: message)

Expand Down
Loading

0 comments on commit 3b94565

Please sign in to comment.