diff --git a/SignalMessaging/ViewModels/ContactShareViewModel.swift b/SignalMessaging/ViewModels/ContactShareViewModel.swift index bb80ceaae..81ab28a7c 100644 --- a/SignalMessaging/ViewModels/ContactShareViewModel.swift +++ b/SignalMessaging/ViewModels/ContactShareViewModel.swift @@ -9,14 +9,25 @@ public class ContactShareViewModel: NSObject { public let dbRecord: OWSContact - public let avatarImageData: Data? - lazy var avatarImage: UIImage? = { + public var avatarImageData: Data? { + didSet { + self.cachedAvatarImage = nil + } + } + + var cachedAvatarImage: UIImage? + var avatarImage: UIImage? { + if self.cachedAvatarImage != nil { + return self.cachedAvatarImage + } + guard let avatarImageData = self.avatarImageData else { return nil } - return UIImage(data: avatarImageData) - }() + self.cachedAvatarImage = UIImage(data: avatarImageData) + return cachedAvatarImage + } public required init(contactShareRecord: OWSContact, avatarImageData: Data?) { self.dbRecord = contactShareRecord @@ -129,7 +140,8 @@ public class ContactShareViewModel: NSObject { // TODO move the `newContact` logic into the view model? let newDbRecord = dbRecord.newContact(with: name) - return ContactShareViewModel(contactShareRecord: newDbRecord, avatarImageData: self.avatarImageData) + // If we want to keep the avatar image, the caller will need to re-apply it. + return ContactShareViewModel(contactShareRecord: newDbRecord, avatarImageData: nil) } } diff --git a/SignalMessaging/attachments/ApproveContactShareViewController.swift b/SignalMessaging/attachments/ApproveContactShareViewController.swift index f992d3fd8..4434a6405 100644 --- a/SignalMessaging/attachments/ApproveContactShareViewController.swift +++ b/SignalMessaging/attachments/ApproveContactShareViewController.swift @@ -97,6 +97,40 @@ class ContactShareAddress: ContactShareFieldBase { } } +// Stub class so that avatars conform to OWSContactField. +class OWSContactAvatar: NSObject, OWSContactField { + + public let avatarImage: UIImage + public let avatarData: Data + + required init(avatarImage: UIImage, avatarData: Data) { + self.avatarImage = avatarImage + self.avatarData = avatarData + + super.init() + } + + public func ows_isValid() -> Bool { + return true + } + + public func localizedLabel() -> String { + return "" + } + + override public var debugDescription: String { + return "Avatar" + } +} + +class ContactShareAvatarField: ContactShareFieldBase { + override func applyToContact(contact: ContactShareViewModel) { + assert(isIncluded()) + + contact.avatarImageData = value.avatarData + } +} + // MARK: - protocol ContactShareFieldViewDelegate: class { @@ -213,10 +247,21 @@ public class ApproveContactShareViewController: OWSViewController, EditContactSh func buildFields() { var fieldViews = [ContactShareFieldView]() - // TODO: Avatar - let previewInsets = UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 0) + if let avatarData = contactShare.avatarImageData { + if let avatarImage = contactShare.avatarImage { + let field = ContactShareAvatarField(OWSContactAvatar(avatarImage: avatarImage, avatarData: avatarData)) + let fieldView = ContactShareFieldView(field: field, previewViewBlock: { + return ContactFieldView.contactFieldView(forAvatarImage: avatarImage, layoutMargins: previewInsets, actionBlock: nil) + }, + delegate: self) + fieldViews.append(fieldView) + } else { + owsFail("\(logTag) could not load avatar image.") + } + } + for phoneNumber in contactShare.phoneNumbers { let field = ContactSharePhoneNumber(phoneNumber) let fieldView = ContactShareFieldView(field: field, previewViewBlock: { diff --git a/SignalMessaging/attachments/ContactFieldView.swift b/SignalMessaging/attachments/ContactFieldView.swift index 68bd2d7de..e17ca7cc7 100644 --- a/SignalMessaging/attachments/ContactFieldView.swift +++ b/SignalMessaging/attachments/ContactFieldView.swift @@ -60,7 +60,32 @@ public class ContactFieldView: UIView { lastRow?.autoPinEdge(toSuperviewEdge: .bottom, withInset: 0) } - + + public class func contactFieldView(forAvatarImage avatarImage: UIImage, layoutMargins: UIEdgeInsets, actionBlock : (() -> Void)?) -> UIView { + var stackView: UIStackView + if let actionBlock = actionBlock { + stackView = TappableStackView(actionBlock: actionBlock) + } else { + stackView = UIStackView() + } + stackView.axis = .vertical + stackView.alignment = .leading + stackView.spacing = 3 + stackView.layoutMargins = layoutMargins + stackView.isLayoutMarginsRelativeArrangement = true + + let avatarView = AvatarImageView() + avatarView.image = avatarImage + let avatarSize = CGFloat(50) + avatarView.autoSetDimension(.width, toSize: avatarSize) + avatarView.autoSetDimension(.height, toSize: avatarSize) + avatarView.setCompressionResistanceHigh() + avatarView.setContentHuggingHigh() + stackView.addArrangedSubview(avatarView) + + return stackView + } + public class func contactFieldView(forOrganizationName organizationName: String, layoutMargins: UIEdgeInsets) -> UIView { return simpleFieldView(name: NSLocalizedString("CONTACT_FIELD_ORGANIZATION_NAME", comment: "Label for the 'organization name' field of a contact."), value: organizationName,