2016-11-23 17:07:38 +01:00
//
2018-02-23 18:46:04 +01:00
// C o p y r i g h t ( c ) 2 0 1 8 O p e n W h i s p e r S y s t e m s . A l l r i g h t s r e s e r v e d .
2016-11-23 17:07:38 +01:00
//
import UIKit
2017-05-01 20:28:37 +02:00
import Contacts
2017-11-28 00:17:46 +01:00
import SignalServiceKit
2016-11-23 17:07:38 +01:00
class ContactCell : UITableViewCell {
2018-05-01 22:38:54 +02:00
public static let kSeparatorHInset : CGFloat = CGFloat ( kAvatarDiameter ) + 16 + 8
2017-05-01 20:28:37 +02:00
2018-05-01 22:38:54 +02:00
static let kAvatarSpacing : CGFloat = 6
static let kAvatarDiameter : UInt = 40
let contactImageView : AvatarImageView
let textStackView : UIStackView
let titleLabel : UILabel
var subtitleLabel : UILabel
2017-05-01 20:28:37 +02:00
2016-11-23 17:07:38 +01:00
var contact : Contact ?
2018-05-09 17:54:10 +02:00
var showsWhenSelected : Bool = false
2017-05-01 20:28:37 +02:00
2018-05-01 22:38:54 +02:00
override init ( style : UITableViewCellStyle , reuseIdentifier : String ? ) {
self . contactImageView = AvatarImageView ( )
self . textStackView = UIStackView ( )
self . titleLabel = UILabel ( )
self . titleLabel . font = UIFont . ows_dynamicTypeBody
self . subtitleLabel = UILabel ( )
self . subtitleLabel . font = UIFont . ows_dynamicTypeSubheadline
super . init ( style : style , reuseIdentifier : reuseIdentifier )
2016-11-23 17:07:38 +01:00
selectionStyle = UITableViewCellSelectionStyle . none
2018-05-01 22:38:54 +02:00
textStackView . axis = . vertical
textStackView . addArrangedSubview ( titleLabel )
contactImageView . autoSetDimensions ( to : CGSize ( width : CGFloat ( ContactCell . kAvatarDiameter ) , height : CGFloat ( ContactCell . kAvatarDiameter ) ) )
let contentColumns : UIStackView = UIStackView ( arrangedSubviews : [ contactImageView , textStackView ] )
contentColumns . axis = . horizontal
contentColumns . spacing = ContactCell . kAvatarSpacing
contentColumns . alignment = . center
self . contentView . addSubview ( contentColumns )
contentColumns . autoPinEdgesToSuperviewMargins ( )
2017-05-01 20:28:37 +02:00
2016-11-23 17:07:38 +01:00
NotificationCenter . default . addObserver ( self , selector : #selector ( self . didChangePreferredContentSize ) , name : NSNotification . Name . UIContentSizeCategoryDidChange , object : nil )
}
2018-05-01 22:38:54 +02:00
required init ? ( coder aDecoder : NSCoder ) {
fatalError ( " init(coder:) has not been implemented " )
}
2016-11-23 17:07:38 +01:00
override func prepareForReuse ( ) {
accessoryType = . none
2018-05-01 22:38:54 +02:00
self . subtitleLabel . removeFromSuperview ( )
2016-11-23 17:07:38 +01:00
}
override func setSelected ( _ selected : Bool , animated : Bool ) {
super . setSelected ( selected , animated : animated )
2018-05-09 17:54:10 +02:00
if showsWhenSelected {
accessoryType = selected ? . checkmark : . none
}
2016-11-23 17:07:38 +01:00
}
func didChangePreferredContentSize ( ) {
2018-05-01 22:38:54 +02:00
self . titleLabel . font = UIFont . ows_dynamicTypeBody
self . subtitleLabel . font = UIFont . ows_dynamicTypeSubheadline
2016-11-23 17:07:38 +01:00
}
2018-05-09 17:54:10 +02:00
func configure ( contact : Contact , subtitleType : SubtitleCellValue , showsWhenSelected : Bool , contactsManager : OWSContactsManager ) {
2016-11-23 17:07:38 +01:00
self . contact = contact
2018-05-09 17:54:10 +02:00
self . showsWhenSelected = showsWhenSelected
2016-11-23 17:07:38 +01:00
2018-05-01 22:38:54 +02:00
titleLabel . attributedText = contact . cnContact ? . formattedFullName ( font : titleLabel . font )
updateSubtitle ( subtitleType : subtitleType , contact : contact )
2016-11-23 17:07:38 +01:00
2018-05-01 22:38:54 +02:00
if let contactImage = contact . image {
contactImageView . image = contactImage
} else {
2016-11-23 17:07:38 +01:00
let contactIdForDeterminingBackgroundColor : String
if let signalId = contact . parsedPhoneNumbers . first ? . toE164 ( ) {
contactIdForDeterminingBackgroundColor = signalId
} else {
contactIdForDeterminingBackgroundColor = contact . fullName
}
2017-08-07 21:46:18 +02:00
let avatarBuilder = OWSContactAvatarBuilder ( nonSignalName : contact . fullName ,
colorSeed : contactIdForDeterminingBackgroundColor ,
2018-05-01 22:38:54 +02:00
diameter : ContactCell . kAvatarDiameter ,
2018-02-23 18:46:04 +01:00
contactsManager : contactsManager )
2017-08-07 21:46:18 +02:00
2018-05-17 14:44:07 +02:00
contactImageView . image = avatarBuilder . build ( )
2016-11-23 17:07:38 +01:00
}
}
2017-05-01 20:28:37 +02:00
2018-05-01 22:38:54 +02:00
func updateSubtitle ( subtitleType : SubtitleCellValue , contact : Contact ) {
2016-11-23 17:07:38 +01:00
switch subtitleType {
2018-05-01 22:38:54 +02:00
case . none :
assert ( self . subtitleLabel . superview = = nil )
break
case . phoneNumber :
self . textStackView . addArrangedSubview ( self . subtitleLabel )
if let firstPhoneNumber = contact . userTextPhoneNumbers . first {
self . subtitleLabel . text = firstPhoneNumber
2016-11-23 17:07:38 +01:00
} else {
2018-05-01 22:38:54 +02:00
self . subtitleLabel . text = NSLocalizedString ( " CONTACT_PICKER_NO_PHONE_NUMBERS_AVAILABLE " , comment : " table cell subtitle when contact card has no known phone number " )
2016-11-23 17:07:38 +01:00
}
2018-05-01 22:38:54 +02:00
case . email :
self . textStackView . addArrangedSubview ( self . subtitleLabel )
if let firstEmail = contact . emails . first {
self . subtitleLabel . text = firstEmail
2016-11-23 17:07:38 +01:00
} else {
2018-05-01 22:38:54 +02:00
self . subtitleLabel . text = NSLocalizedString ( " CONTACT_PICKER_NO_EMAILS_AVAILABLE " , comment : " table cell subtitle when contact card has no email " )
2016-11-23 17:07:38 +01:00
}
}
}
}
fileprivate extension CNContact {
/* *
* Bold the sorting portion of the name . e . g . if we sort by family name , bold the family name .
*/
func formattedFullName ( font : UIFont ) -> NSAttributedString ? {
let keyToHighlight = ContactSortOrder = = . familyName ? CNContactFamilyNameKey : CNContactGivenNameKey
2016-12-09 20:19:18 +01:00
let boldDescriptor = font . fontDescriptor . withSymbolicTraits ( . traitBold )
let boldAttributes = [
2018-02-23 18:46:04 +01:00
NSFontAttributeName : UIFont ( descriptor : boldDescriptor ! , size : 0 )
2016-12-09 20:19:18 +01:00
]
2016-11-23 17:07:38 +01:00
if let attributedName = CNContactFormatter . attributedString ( from : self , style : . fullName , defaultAttributes : nil ) {
let highlightedName = attributedName . mutableCopy ( ) as ! NSMutableAttributedString
2018-05-16 21:47:17 +02:00
highlightedName . enumerateAttributes ( in : NSRange ( location : 0 , length : highlightedName . length ) , options : [ ] , using : { ( attrs , range , _ ) in
2016-11-23 17:07:38 +01:00
if let property = attrs [ CNContactPropertyAttribute ] as ? String , property = = keyToHighlight {
highlightedName . addAttributes ( boldAttributes , range : range )
}
} )
return highlightedName
}
2016-12-09 20:19:18 +01:00
if let emailAddress = ( self . emailAddresses . first ? . value as String ? ) {
return NSAttributedString ( string : emailAddress , attributes : boldAttributes )
}
2016-11-23 17:07:38 +01:00
return nil
}
}